/** * php-asio/socket.hpp * * @author CismonX */ #pragma once #include "common.hpp" #include "base.hpp" #include #define ENABLE_IF_INET(P) std::string(P::endpoint::*port)() #define ENABLE_IF_LOCAL(P) std::string(P::endpoint::*path)() namespace asio { /// Wrapper for Boost.Asio socket. template class socket : public base { /// Boost.Asio socket instance. typename Protocol::socket socket_; template using enable_if_same = std::enable_if_t::value>; #ifdef ENABLE_COROUTINE /// Address of client who sent the last request. template > static thread_local std::string last_addr_; /// Port of client who sent the last request. template > static thread_local unsigned short last_port_; /// Socket path of client who sent the last request. template > static thread_local std::string last_path_; #endif // ENABLE_COROUTINE /// Connect handler. zval* connect_handler(const boost::system::error_code& error, zval* callback, zval* argument); /// Read handler for stream socket. template , typename P::socket>> zval* read_handler(const boost::system::error_code& error, size_t length, zend_string* buffer, zval* callback, zval* argument); /// Write/send handler for socket. zval* write_handler(const boost::system::error_code& error, size_t length, zend_string* buffer, zval* callback, zval* argument); /// Receive handler for datagram socket. zval* recv_handler(const boost::system::error_code& error, size_t length, zend_string* buffer, typename Protocol::endpoint* endpoint, zval* callback, zval* argument); public: /// Constructor. explicit socket( boost::asio::io_service& io_service ) : base(io_service), socket_(io_service) {} /// Get reference of socket. typename Protocol::socket& get_socket() { return socket_; } template using inet_p = typename P::endpoint::port; /* {{{ proto int InetSocket::open(bool inet6); * Open INET socket (AF_INET or AF_INET6). */ template P3_METHOD_DECLARE(open_inet); /* }}} */ /* {{{ proto int LocalSocket::open(void); * Open UNIX domain socket. */ template P3_METHOD_DECLARE(open_local); /* }}} */ /* {{{ proto int InetSocket::assign(bool inet6, int|resource fd); * Assign an existing native socket to the socket. */ template P3_METHOD_DECLARE(assign_inet); /* }}} */ /* {{{ proto int LocalSocket::assign(int|resource fd); * Assign an existing native socket to the socket. */ template P3_METHOD_DECLARE(assign_local); /* }}} */ /* {{{ proto int InetSocket::bind(string address, int port); * Bind socket to a local endpoint (AF_INET or AF_INET6). */ template P3_METHOD_DECLARE(bind_inet); /* }}} */ /* {{{ proto int LocalSocket::bind(string path); * Bind socket to a local endpoint (AF_UNIX). */ template P3_METHOD_DECLARE(bind_local); /* }}} */ P3_METHOD_DECLARE(connect); /* {{{ proto Future StreamSocket::read(int length, [bool read_some = true], * [callable callback], [mixed argument]); * Read asynchronously from stream socket. */ template , typename P::socket>> P3_METHOD_DECLARE(read); /* }}} */ /* {{{ proto Future StreamSocket::write(string data, [bool write_some = false], * [callable callback], [mixed argument]); * Write asynchronously to stream socket. */ template , typename P::socket>> P3_METHOD_DECLARE(write); /* }}} */ /* {{{ proto Future DatagramSocket::recvFrom(int length, * [callable callback], [mixed argument]); * Receive asynchronously from datagram socket.*/ template , typename P::socket>> P3_METHOD_DECLARE(recvFrom); /* }}} */ template , typename P::socket>> P3_METHOD_DECLARE(sendTo); /* {{{ proto string InetSocket::remoteAddr(void); * Get remote address (AF_INET or AF_INET6). */ template P3_METHOD_DECLARE(remoteAddr) const; /* }}} */ /* {{{ proto int InetSocket::remotePort(void); * Get remote port (AF_INET or AF_INET6). */ template P3_METHOD_DECLARE(remotePort) const; /* }}} */ /* {{{ proto string LocalSocket::remotePath(void); * Get socket file path of remote endpoint (AF_UNIX). */ template P3_METHOD_DECLARE(remotePath) const; /* }}} */ /* {{{ proto int Socket::available([int &ec]); * Determine the number of bytes available for reading. */ P3_METHOD_DECLARE(available) const; /* }}} */ /* {{{ proto bool Socket::atMark([int &ec]); * Determine whether the socket is at the out-of-band data mark. */ P3_METHOD_DECLARE(atMark) const; /* }}} */ /* {{{ proto int Socket::cancel(void); * Cancel all asynchronous operations on the socket. */ P3_METHOD_DECLARE(cancel); /* }}} */ /* {{{ proto int Socket::close(void); * Close the socket. */ P3_METHOD_DECLARE(close); /* }}} */ PHP_ASIO_CE_DECLARE(); }; using tcp_socket = socket; using unix_socket = socket; using udp_socket = socket; using udg_socket = socket; }