diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 462aa8a758e..a68e7f26ac2 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -1231,7 +1231,7 @@ PHP_FUNCTION(swoole_coroutine_socketpair) { php_swoole_check_reactor(); - auto sock_type = swoole::network::Socket::convert_to_type(domain, type, protocol); + auto sock_type = swoole::network::Socket::convert_to_type(domain, type); zend_object *s1 = php_swoole_create_socket_from_fd(pair[0], sock_type); if (s1 == nullptr) { @@ -1362,7 +1362,7 @@ static PHP_METHOD(swoole_socket_coro, connect) { swoole_get_socket_coro(sock, ZEND_THIS); - if (sock->socket->get_sock_domain() == AF_INET6 || sock->socket->get_sock_domain() == AF_INET) { + if (sock->socket->is_port_required()) { if (ZEND_NUM_ARGS() == 1) { php_swoole_error(E_WARNING, "Socket of type AF_INET/AF_INET6 requires port argument"); RETURN_FALSE; diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 42c6e51ea41..162a8fe5df0 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -79,6 +79,10 @@ class Socket { return sock_fd == SW_BAD_SOCKET; } + bool is_port_required() { + return type <= SW_SOCK_UDP6; + } + bool check_liveness(); ssize_t peek(void *__buf, size_t __n); ssize_t recv(void *__buf, size_t __n); diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 57e22d1ce4a..6472bfc7434 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -568,16 +568,21 @@ struct Socket { return catch_error(err); } - static inline SocketType convert_to_type(int domain, int type, int protocol = 0) { - switch (domain) { - case AF_INET: - return type == SOCK_STREAM ? SW_SOCK_TCP : SW_SOCK_UDP; - case AF_INET6: - return type == SOCK_STREAM ? SW_SOCK_TCP6 : SW_SOCK_UDP6; - case AF_UNIX: - return type == SOCK_STREAM ? SW_SOCK_UNIX_STREAM : SW_SOCK_UNIX_DGRAM; - default: + static inline SocketType convert_to_type(int domain, int type) { + if (domain == AF_INET && type == SOCK_STREAM) { return SW_SOCK_TCP; + } else if (domain == AF_INET6 && type == SOCK_STREAM) { + return SW_SOCK_TCP6; + } else if (domain == AF_UNIX && type == SOCK_STREAM) { + return SW_SOCK_UNIX_STREAM; + } else if (domain == AF_INET && type == SOCK_DGRAM) { + return SW_SOCK_UDP; + } else if (domain == AF_INET6 && type == SOCK_DGRAM) { + return SW_SOCK_UDP6; + } else if (domain == AF_UNIX && type == SOCK_DGRAM) { + return SW_SOCK_UNIX_DGRAM; + } else { + return SW_SOCK_RAW; } } @@ -633,6 +638,9 @@ int getaddrinfo(GetaddrinfoRequest *req); } // namespace network network::Socket *make_socket(int fd, FdType fd_type); network::Socket *make_socket(SocketType socket_type, FdType fd_type, int flags); +network::Socket *make_socket( + SocketType type, FdType fd_type, int sock_domain, int sock_type, int socket_protocol, int flags); +int socket(int sock_domain, int sock_type, int socket_protocol, int flags); network::Socket *make_server_socket(SocketType socket_type, const char *address, int port = 0, diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 1a2dbb244c3..a141d2b1ebe 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -472,13 +472,14 @@ bool Socket::http_proxy_handshake() { return ret; } -void Socket::init_sock_type(SocketType _sw_type) { - type = _sw_type; - network::Socket::get_domain_and_type(_sw_type, &sock_domain, &sock_type); +void Socket::init_sock_type(SocketType _type) { + type = _type; + network::Socket::get_domain_and_type(_type, &sock_domain, &sock_type); } bool Socket::init_sock() { - socket = make_socket(type, SW_FD_CO_SOCKET, SW_SOCK_CLOEXEC | SW_SOCK_NONBLOCK); + socket = + make_socket(type, SW_FD_CO_SOCKET, sock_domain, sock_type, sock_protocol, SW_SOCK_NONBLOCK | SW_SOCK_CLOEXEC); if (socket == nullptr) { return false; } @@ -501,7 +502,7 @@ bool Socket::init_reactor_socket(int _fd) { Socket::Socket(int _domain, int _type, int _protocol) : sock_domain(_domain), sock_type(_type), sock_protocol(_protocol) { - type = network::Socket::convert_to_type(_domain, _type, _protocol); + type = network::Socket::convert_to_type(_domain, _type); if (sw_unlikely(!init_sock())) { return; } @@ -517,20 +518,20 @@ Socket::Socket(SocketType _type) { } Socket::Socket(int _fd, SocketType _type) { - init_sock_type(_type); if (sw_unlikely(!init_reactor_socket(_fd))) { return; } if (_type == SW_SOCK_RAW) { return; } + init_sock_type(_type); socket->set_nonblock(); init_options(); } Socket::Socket(int _fd, int _domain, int _type, int _protocol) : sock_domain(_domain), sock_type(_type), sock_protocol(_protocol) { - type = network::Socket::convert_to_type(_domain, _type, _protocol); + type = network::Socket::convert_to_type(_domain, _type); if (sw_unlikely(!init_reactor_socket(_fd))) { return; } @@ -658,7 +659,7 @@ bool Socket::connect(std::string _host, int _port, int flags) { _port = http_proxy->proxy_port; } - if (sock_domain == AF_INET6 || sock_domain == AF_INET) { + if (is_port_required()) { if (_port == -1) { set_err(EINVAL, "Socket of type AF_INET/AF_INET6 requires port argument"); return false; diff --git a/src/network/socket.cc b/src/network/socket.cc index 76d4e9bf062..d6c5609ec2e 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -1468,9 +1468,28 @@ Socket *make_socket(SocketType type, FdType fd_type, int flags) { if (Socket::get_domain_and_type(type, &sock_domain, &sock_type) < 0) { swoole_warning("unknown socket type [%d]", type); errno = ESOCKTNOSUPPORT; + swoole_set_last_error(errno); return nullptr; } + return make_socket(type, fd_type, sock_domain, sock_type, 0, flags); +} + +Socket *make_socket(SocketType type, FdType fd_type, int sock_domain, int sock_type, int socket_protocol, int flags) { + int sockfd = swoole::socket(sock_domain, sock_type, socket_protocol, flags); + if (sockfd < 0) { + swoole_set_last_error(errno); + return nullptr; + } + + auto _socket = swoole::make_socket(sockfd, fd_type); + _socket->nonblock = !!(flags & SW_SOCK_NONBLOCK); + _socket->cloexec = !!(flags & SW_SOCK_CLOEXEC); + _socket->socket_type = type; + return _socket; +} + +int socket(int sock_domain, int sock_type, int socket_protocol, int flags) { bool nonblock = flags & SW_SOCK_NONBLOCK; bool cloexec = flags & SW_SOCK_CLOEXEC; @@ -1482,27 +1501,23 @@ Socket *make_socket(SocketType type, FdType fd_type, int flags) { if (cloexec) { sock_flags |= SOCK_CLOEXEC; } - int sockfd = socket(sock_domain, sock_type | sock_flags, 0); + int sockfd = ::socket(sock_domain, sock_type | sock_flags, socket_protocol); if (sockfd < 0) { - return nullptr; + return sockfd; } #else - int sockfd = socket(sock_domain, sock_type, 0); + int sockfd = ::socket(sock_domain, sock_type, socket_protocol); if (sockfd < 0) { - return nullptr; + return sockfd; } if (nonblock || cloexec) { if (!network::_fcntl_set_option(sockfd, nonblock ? 1 : -1, cloexec ? 1 : -1)) { close(sockfd); - return nullptr; + return sockfd; } } #endif - auto _socket = swoole::make_socket(sockfd, fd_type); - _socket->nonblock = nonblock; - _socket->cloexec = cloexec; - _socket->socket_type = type; - return _socket; + return sockfd; } Socket *make_server_socket(SocketType type, const char *address, int port, int backlog) { diff --git a/tests/swoole_socket_coro/icmp.phpt b/tests/swoole_socket_coro/icmp.phpt new file mode 100644 index 00000000000..2e1d2dcfbaa --- /dev/null +++ b/tests/swoole_socket_coro/icmp.phpt @@ -0,0 +1,19 @@ +--TEST-- +swoole_socket_coro: icmp +--SKIPIF-- + +--FILE-- +connect($host); + $socket->send($package, strlen($package)); + $pkt = $socket->recv(256); + Assert::notEmpty($pkt); +}); +?> +--EXPECT--