diff options
Diffstat (limited to 'drivers/unix')
-rw-r--r-- | drivers/unix/net_socket_unix.cpp (renamed from drivers/unix/net_socket_posix.cpp) | 328 | ||||
-rw-r--r-- | drivers/unix/net_socket_unix.h (renamed from drivers/unix/net_socket_posix.h) | 80 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 95 | ||||
-rw-r--r-- | drivers/unix/os_unix.h | 6 |
4 files changed, 211 insertions, 298 deletions
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_unix.cpp index 5caa33100e..3eaf1b2885 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_unix.cpp @@ -1,5 +1,5 @@ /**************************************************************************/ -/* net_socket_posix.cpp */ +/* net_socket_unix.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include "net_socket_posix.h" - // Some proprietary Unix-derived platforms don't expose Unix sockets // so this allows skipping this file to reimplement this API differently. -#ifndef UNIX_SOCKET_UNAVAILABLE +#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE) -#if defined(UNIX_ENABLED) +#include "net_socket_unix.h" #include <errno.h> #include <fcntl.h> @@ -62,44 +60,11 @@ #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif -// Some custom defines to minimize ifdefs -#define SOCK_EMPTY -1 -#define SOCK_BUF(x) x -#define SOCK_CBUF(x) x -#define SOCK_IOCTL ioctl -#define SOCK_FIONREAD_LEN_TYPE int -#define SOCK_CLOSE ::close -#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::connect(p_sock, p_addr, p_addr_len) - -/* Windows */ -#elif defined(WINDOWS_ENABLED) -#include <winsock2.h> -#include <ws2tcpip.h> - -#include <mswsock.h> -// Some custom defines to minimize ifdefs -#define SOCK_EMPTY INVALID_SOCKET -#define SOCK_BUF(x) (char *)(x) -#define SOCK_CBUF(x) (const char *)(x) -#define SOCK_IOCTL ioctlsocket -#define SOCK_FIONREAD_LEN_TYPE unsigned long -#define SOCK_CLOSE closesocket -// connect is broken on windows under certain conditions, reasons unknown: -// See https://github.com/godotengine/webrtc-native/issues/6 -#define SOCK_CONNECT(p_sock, p_addr, p_addr_len) ::WSAConnect(p_sock, p_addr, p_addr_len, nullptr, nullptr, nullptr, nullptr) - -// Workaround missing flag in MinGW -#if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) -#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15) -#endif - -#endif // UNIX_ENABLED - -size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { +size_t NetSocketUnix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); - if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket + if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket. - // IPv6 only socket with IPv4 address + // IPv6 only socket with IPv4 address. ERR_FAIL_COND_V(!p_ip.is_wildcard() && p_ip_type == IP::TYPE_IPV6 && p_ip.is_ipv4(), 0); struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr; @@ -111,14 +76,14 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const addr6->sin6_addr = in6addr_any; } return sizeof(sockaddr_in6); - } else { // IPv4 socket + } else { // IPv4 socket. - // IPv4 socket with IPv6 address + // IPv4 socket with IPv6 address. ERR_FAIL_COND_V(!p_ip.is_wildcard() && !p_ip.is_ipv4(), 0); struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; addr4->sin_family = AF_INET; - addr4->sin_port = htons(p_port); // short, network byte order + addr4->sin_port = htons(p_port); // Short, network byte order. if (p_ip.is_valid()) { memcpy(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4); @@ -130,7 +95,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const } } -void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { +void NetSocketUnix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) { if (p_addr->ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; if (r_ip) { @@ -150,34 +115,21 @@ void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ } } -NetSocket *NetSocketPosix::_create_func() { - return memnew(NetSocketPosix); +NetSocket *NetSocketUnix::_create_func() { + return memnew(NetSocketUnix); } -void NetSocketPosix::make_default() { -#if defined(WINDOWS_ENABLED) - if (_create == nullptr) { - WSADATA data; - WSAStartup(MAKEWORD(2, 2), &data); - } -#endif +void NetSocketUnix::make_default() { _create = _create_func; } -void NetSocketPosix::cleanup() { -#if defined(WINDOWS_ENABLED) - if (_create != nullptr) { - WSACleanup(); - } - _create = nullptr; -#endif +void NetSocketUnix::cleanup() { } -NetSocketPosix::NetSocketPosix() : - _sock(SOCK_EMPTY) { +NetSocketUnix::NetSocketUnix() { } -NetSocketPosix::~NetSocketPosix() { +NetSocketUnix::~NetSocketUnix() { close(); } @@ -188,30 +140,7 @@ NetSocketPosix::~NetSocketPosix() { #pragma GCC diagnostic ignored "-Wlogical-op" #endif -NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const { -#if defined(WINDOWS_ENABLED) - int err = WSAGetLastError(); - if (err == WSAEISCONN) { - return ERR_NET_IS_CONNECTED; - } - if (err == WSAEINPROGRESS || err == WSAEALREADY) { - return ERR_NET_IN_PROGRESS; - } - if (err == WSAEWOULDBLOCK) { - return ERR_NET_WOULD_BLOCK; - } - if (err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL) { - return ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE; - } - if (err == WSAEACCES) { - return ERR_NET_UNAUTHORIZED; - } - if (err == WSAEMSGSIZE || err == WSAENOBUFS) { - return ERR_NET_BUFFER_TOO_SMALL; - } - print_verbose("Socket error: " + itos(err)); - return ERR_NET_OTHER; -#else +NetSocketUnix::NetError NetSocketUnix::_get_socket_error() const { if (errno == EISCONN) { return ERR_NET_IS_CONNECTED; } @@ -230,16 +159,15 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const { if (errno == ENOBUFS) { return ERR_NET_BUFFER_TOO_SMALL; } - print_verbose("Socket error: " + itos(errno)); + print_verbose("Socket error: " + itos(errno) + "."); return ERR_NET_OTHER; -#endif } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif -bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { +bool NetSocketUnix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const { if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) { return false; } else if (!p_for_bind && !p_ip.is_valid()) { @@ -250,11 +178,11 @@ bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) c return !(_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type); } -_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { +_FORCE_INLINE_ Error NetSocketUnix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_ip, false), ERR_INVALID_PARAMETER); - // Need to force level and af_family to IP(v4) when using dual stacking and provided multicast group is IPv4 + // Need to force level and af_family to IP(v4) when using dual stacking and provided multicast group is IPv4. IP::Type type = _ip_type == IP::TYPE_ANY && p_ip.is_ipv4() ? IP::TYPE_IPV4 : _ip_type; // This needs to be the proper level for the multicast group, no matter if the socket is dual stacking. int level = type == IP::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; @@ -277,7 +205,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str for (const IPAddress &F : c.ip_addresses) { if (!F.is_ipv4()) { - continue; // Wrong IP type + continue; // Wrong IP type. } if_ip = F; break; @@ -304,7 +232,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str return OK; } -void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream) { +void NetSocketUnix::_set_socket(int p_sock, IP::Type p_ip_type, bool p_is_stream) { _sock = p_sock; _ip_type = p_ip_type; _is_stream = p_is_stream; @@ -312,15 +240,13 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_ _set_close_exec_enabled(true); } -void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) { -#ifndef WINDOWS_ENABLED +void NetSocketUnix::_set_close_exec_enabled(bool p_enabled) { // Enable close on exec to avoid sharing with subprocesses. Off by default on Windows. int opts = fcntl(_sock, F_GETFD); fcntl(_sock, F_SETFD, opts | FD_CLOEXEC); -#endif } -Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { +Error NetSocketUnix::open(Type p_sock_type, IP::Type &ip_type) { ERR_FAIL_COND_V(is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(ip_type > IP::TYPE_ANY || ip_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER); @@ -336,7 +262,7 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { int type = p_sock_type == TYPE_TCP ? SOCK_STREAM : SOCK_DGRAM; _sock = socket(family, type, protocol); - if (_sock == SOCK_EMPTY && ip_type == IP::TYPE_ANY) { + if (_sock == -1 && ip_type == IP::TYPE_ANY) { // Careful here, changing the referenced parameter so the caller knows that we are using an IPv4 socket // in place of a dual stack one, and further calls to _set_sock_addr will work as expected. ip_type = IP::TYPE_IPV4; @@ -344,11 +270,11 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { _sock = socket(family, type, protocol); } - ERR_FAIL_COND_V(_sock == SOCK_EMPTY, FAILED); + ERR_FAIL_COND_V(_sock == -1, FAILED); _ip_type = ip_type; if (family == AF_INET6) { - // Select IPv4 over IPv6 mapping + // Select IPv4 over IPv6 mapping. set_ipv6_only_enabled(ip_type != IP::TYPE_ANY); } @@ -363,41 +289,27 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) { // Disable descriptor sharing with subprocesses. _set_close_exec_enabled(true); -#if defined(WINDOWS_ENABLED) - if (!_is_stream) { - // Disable windows feature/bug reporting WSAECONNRESET/WSAENETRESET when - // recv/recvfrom and an ICMP reply was received from a previous send/sendto. - unsigned long disable = 0; - if (ioctlsocket(_sock, SIO_UDP_CONNRESET, &disable) == SOCKET_ERROR) { - print_verbose("Unable to turn off UDP WSAECONNRESET behavior on Windows"); - } - if (ioctlsocket(_sock, SIO_UDP_NETRESET, &disable) == SOCKET_ERROR) { - // This feature seems not to be supported on wine. - print_verbose("Unable to turn off UDP WSAENETRESET behavior on Windows"); - } - } -#endif #if defined(SO_NOSIGPIPE) - // Disable SIGPIPE (should only be relevant to stream sockets, but seems to affect UDP too on iOS) + // Disable SIGPIPE (should only be relevant to stream sockets, but seems to affect UDP too on iOS). int par = 1; - if (setsockopt(_sock, SOL_SOCKET, SO_NOSIGPIPE, SOCK_CBUF(&par), sizeof(int)) != 0) { - print_verbose("Unable to turn off SIGPIPE on socket"); + if (setsockopt(_sock, SOL_SOCKET, SO_NOSIGPIPE, &par, sizeof(int)) != 0) { + print_verbose("Unable to turn off SIGPIPE on socket."); } #endif return OK; } -void NetSocketPosix::close() { - if (_sock != SOCK_EMPTY) { - SOCK_CLOSE(_sock); +void NetSocketUnix::close() { + if (_sock != -1) { + ::close(_sock); } - _sock = SOCK_EMPTY; + _sock = -1; _ip_type = IP::TYPE_NONE; _is_stream = false; } -Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { +Error NetSocketUnix::bind(IPAddress p_addr, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER); @@ -406,7 +318,7 @@ Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { if (::bind(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); - print_verbose("Failed to bind socket. Error: " + itos(err)); + print_verbose("Failed to bind socket. Error: " + itos(err) + "."); close(); return ERR_UNAVAILABLE; } @@ -414,7 +326,7 @@ Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) { return OK; } -Error NetSocketPosix::listen(int p_max_pending) { +Error NetSocketUnix::listen(int p_max_pending) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); if (::listen(_sock, p_max_pending) != 0) { @@ -427,26 +339,26 @@ Error NetSocketPosix::listen(int p_max_pending) { return OK; } -Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) { +Error NetSocketUnix::connect_to_host(IPAddress p_host, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER); struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_host, p_port, _ip_type); - if (SOCK_CONNECT(_sock, (struct sockaddr *)&addr, addr_size) != 0) { + if (::connect(_sock, (struct sockaddr *)&addr, addr_size) != 0) { NetError err = _get_socket_error(); switch (err) { - // We are already connected + // We are already connected. case ERR_NET_IS_CONNECTED: return OK; - // Still waiting to connect, try again in a while + // Still waiting to connect, try again in a while. case ERR_NET_WOULD_BLOCK: case ERR_NET_IN_PROGRESS: return ERR_BUSY; default: - print_verbose("Connection to remote host failed!"); + print_verbose("Connection to remote host failed."); close(); return FAILED; } @@ -455,66 +367,9 @@ Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) { return OK; } -Error NetSocketPosix::poll(PollType p_type, int p_timeout) const { +Error NetSocketUnix::poll(PollType p_type, int p_timeout) const { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); -#if defined(WINDOWS_ENABLED) - bool ready = false; - fd_set rd, wr, ex; - fd_set *rdp = nullptr; - fd_set *wrp = nullptr; - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(_sock, &ex); - struct timeval timeout = { p_timeout / 1000, (p_timeout % 1000) * 1000 }; - // For blocking operation, pass nullptr timeout pointer to select. - struct timeval *tp = nullptr; - if (p_timeout >= 0) { - // If timeout is non-negative, we want to specify the timeout instead. - tp = &timeout; - } - - switch (p_type) { - case POLL_TYPE_IN: - FD_SET(_sock, &rd); - rdp = &rd; - break; - case POLL_TYPE_OUT: - FD_SET(_sock, &wr); - wrp = ≀ - break; - case POLL_TYPE_IN_OUT: - FD_SET(_sock, &rd); - FD_SET(_sock, &wr); - rdp = &rd; - wrp = ≀ - } - int ret = select(1, rdp, wrp, &ex, tp); - - if (ret == SOCKET_ERROR) { - return FAILED; - } - - if (ret == 0) { - return ERR_BUSY; - } - - if (FD_ISSET(_sock, &ex)) { - _get_socket_error(); - print_verbose("Exception when polling socket."); - return FAILED; - } - - if (rdp && FD_ISSET(_sock, rdp)) { - ready = true; - } - if (wrp && FD_ISSET(_sock, wrp)) { - ready = true; - } - - return ready ? OK : ERR_BUSY; -#else struct pollfd pfd; pfd.fd = _sock; pfd.events = POLLIN; @@ -544,13 +399,12 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const { } return OK; -#endif } -Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { +Error NetSocketUnix::recv(uint8_t *p_buffer, int p_len, int &r_read) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); - r_read = ::recv(_sock, SOCK_BUF(p_buffer), p_len, 0); + r_read = ::recv(_sock, p_buffer, p_len, 0); if (r_read < 0) { NetError err = _get_socket_error(); @@ -568,14 +422,14 @@ Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { return OK; } -Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { +Error NetSocketUnix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage from; socklen_t len = sizeof(struct sockaddr_storage); memset(&from, 0, len); - r_read = ::recvfrom(_sock, SOCK_BUF(p_buffer), p_len, p_peek ? MSG_PEEK : 0, (struct sockaddr *)&from, &len); + r_read = ::recvfrom(_sock, p_buffer, p_len, p_peek ? MSG_PEEK : 0, (struct sockaddr *)&from, &len); if (r_read < 0) { NetError err = _get_socket_error(); @@ -606,7 +460,7 @@ Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddr return OK; } -Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { +Error NetSocketUnix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); int flags = 0; @@ -615,7 +469,7 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { flags = MSG_NOSIGNAL; } #endif - r_sent = ::send(_sock, SOCK_CBUF(p_buffer), p_len, flags); + r_sent = ::send(_sock, p_buffer, p_len, flags); if (r_sent < 0) { NetError err = _get_socket_error(); @@ -632,12 +486,12 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) { return OK; } -Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { +Error NetSocketUnix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); struct sockaddr_storage addr; size_t addr_size = _set_addr_storage(&addr, p_ip, p_port, _ip_type); - r_sent = ::sendto(_sock, SOCK_CBUF(p_buffer), p_len, 0, (struct sockaddr *)&addr, addr_size); + r_sent = ::sendto(_sock, p_buffer, p_len, 0, (struct sockaddr *)&addr, addr_size); if (r_sent < 0) { NetError err = _get_socket_error(); @@ -654,7 +508,7 @@ Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP return OK; } -Error NetSocketPosix::set_broadcasting_enabled(bool p_enabled) { +Error NetSocketUnix::set_broadcasting_enabled(bool p_enabled) { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); // IPv6 has no broadcast support. if (_ip_type == IP::TYPE_IPV6) { @@ -662,90 +516,68 @@ Error NetSocketPosix::set_broadcasting_enabled(bool p_enabled) { } int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, SOCK_CBUF(&par), sizeof(int)) != 0) { - WARN_PRINT("Unable to change broadcast setting"); + if (setsockopt(_sock, SOL_SOCKET, SO_BROADCAST, &par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change broadcast setting."); return FAILED; } return OK; } -void NetSocketPosix::set_blocking_enabled(bool p_enabled) { +void NetSocketUnix::set_blocking_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); int ret = 0; -#if defined(WINDOWS_ENABLED) - unsigned long par = p_enabled ? 0 : 1; - ret = SOCK_IOCTL(_sock, FIONBIO, &par); -#else int opts = fcntl(_sock, F_GETFL); if (p_enabled) { ret = fcntl(_sock, F_SETFL, opts & ~O_NONBLOCK); } else { ret = fcntl(_sock, F_SETFL, opts | O_NONBLOCK); } -#endif if (ret != 0) { - WARN_PRINT("Unable to change non-block mode"); + WARN_PRINT("Unable to change non-block mode."); } } -void NetSocketPosix::set_ipv6_only_enabled(bool p_enabled) { +void NetSocketUnix::set_ipv6_only_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); // This option is only available in IPv6 sockets. ERR_FAIL_COND(_ip_type == IP::TYPE_IPV4); int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, SOCK_CBUF(&par), sizeof(int)) != 0) { - WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option"); + if (setsockopt(_sock, IPPROTO_IPV6, IPV6_V6ONLY, &par, sizeof(int)) != 0) { + WARN_PRINT("Unable to change IPv4 address mapping over IPv6 option."); } } -void NetSocketPosix::set_tcp_no_delay_enabled(bool p_enabled) { +void NetSocketUnix::set_tcp_no_delay_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); - ERR_FAIL_COND(!_is_stream); // Not TCP + ERR_FAIL_COND(!_is_stream); // Not TCP. int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, SOCK_CBUF(&par), sizeof(int)) < 0) { - ERR_PRINT("Unable to set TCP no delay option"); + if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, &par, sizeof(int)) < 0) { + WARN_PRINT("Unable to set TCP no delay option."); } } -void NetSocketPosix::set_reuse_address_enabled(bool p_enabled) { +void NetSocketUnix::set_reuse_address_enabled(bool p_enabled) { ERR_FAIL_COND(!is_open()); -// On Windows, enabling SO_REUSEADDR actually would also enable reuse port, very bad on TCP. Denying... -// Windows does not have this option, SO_REUSEADDR in this magical world means SO_REUSEPORT -#ifndef WINDOWS_ENABLED - int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, SOCK_CBUF(&par), sizeof(int)) < 0) { - WARN_PRINT("Unable to set socket REUSEADDR option!"); - } -#endif -} - -void NetSocketPosix::set_reuse_port_enabled(bool p_enabled) { - ERR_FAIL_COND(!is_open()); - -// See comment above... -#ifdef WINDOWS_ENABLED -#define SO_REUSEPORT SO_REUSEADDR -#endif int par = p_enabled ? 1 : 0; - if (setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, SOCK_CBUF(&par), sizeof(int)) < 0) { - WARN_PRINT("Unable to set socket REUSEPORT option!"); + if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &par, sizeof(int)) < 0) { + WARN_PRINT("Unable to set socket REUSEADDR option."); } } -bool NetSocketPosix::is_open() const { - return _sock != SOCK_EMPTY; +bool NetSocketUnix::is_open() const { + return _sock != -1; } -int NetSocketPosix::get_available_bytes() const { +int NetSocketUnix::get_available_bytes() const { ERR_FAIL_COND_V(!is_open(), -1); - SOCK_FIONREAD_LEN_TYPE len; - int ret = SOCK_IOCTL(_sock, FIONREAD, &len); + int len; + int ret = ioctl(_sock, FIONREAD, &len); if (ret == -1) { _get_socket_error(); print_verbose("Error when checking available bytes on socket."); @@ -754,7 +586,7 @@ int NetSocketPosix::get_available_bytes() const { return len; } -Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { +Error NetSocketUnix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const { ERR_FAIL_COND_V(!is_open(), FAILED); struct sockaddr_storage saddr; @@ -768,14 +600,14 @@ Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) cons return OK; } -Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) { +Ref<NetSocket> NetSocketUnix::accept(IPAddress &r_ip, uint16_t &r_port) { Ref<NetSocket> out; ERR_FAIL_COND_V(!is_open(), out); struct sockaddr_storage their_addr; socklen_t size = sizeof(their_addr); - SOCKET_TYPE fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size); - if (fd == SOCK_EMPTY) { + int fd = ::accept(_sock, (struct sockaddr *)&their_addr, &size); + if (fd == -1) { _get_socket_error(); print_verbose("Error when accepting socket connection."); return out; @@ -783,18 +615,18 @@ Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) { _set_ip_port(&their_addr, &r_ip, &r_port); - NetSocketPosix *ns = memnew(NetSocketPosix); + NetSocketUnix *ns = memnew(NetSocketUnix); ns->_set_socket(fd, _ip_type, _is_stream); ns->set_blocking_enabled(false); return Ref<NetSocket>(ns); } -Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { +Error NetSocketUnix::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, true); } -Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { +Error NetSocketUnix::leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) { return _change_multicast_group(p_multi_address, p_if_name, false); } -#endif // UNIX_SOCKET_UNAVAILABLE +#endif // UNIX_ENABLED && !UNIX_SOCKET_UNAVAILABLE diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_unix.h index aa59ff36ee..08c45f2ac3 100644 --- a/drivers/unix/net_socket_posix.h +++ b/drivers/unix/net_socket_unix.h @@ -1,5 +1,5 @@ /**************************************************************************/ -/* net_socket_posix.h */ +/* net_socket_unix.h */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,25 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef NET_SOCKET_POSIX_H -#define NET_SOCKET_POSIX_H +#ifndef NET_SOCKET_UNIX_H +#define NET_SOCKET_UNIX_H -#include "core/io/net_socket.h" +#if defined(UNIX_ENABLED) && !defined(UNIX_SOCKET_UNAVAILABLE) -#if defined(WINDOWS_ENABLED) -#include <winsock2.h> -#include <ws2tcpip.h> -#define SOCKET_TYPE SOCKET +#include "core/io/net_socket.h" -#else #include <sys/socket.h> -#define SOCKET_TYPE int -#endif - -class NetSocketPosix : public NetSocket { +class NetSocketUnix : public NetSocket { private: - SOCKET_TYPE _sock; // NOLINT - the default value is defined in the .cpp + int _sock = -1; IP::Type _ip_type = IP::TYPE_NONE; bool _is_stream = false; @@ -61,7 +54,7 @@ private: }; NetError _get_socket_error() const; - void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream); + void _set_socket(int p_sock, IP::Type p_ip_type, bool p_is_stream); _FORCE_INLINE_ Error _change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add); _FORCE_INLINE_ void _set_close_exec_enabled(bool p_enabled); @@ -76,33 +69,34 @@ public: static void _set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port); static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type); - virtual Error open(Type p_sock_type, IP::Type &ip_type); - virtual void close(); - virtual Error bind(IPAddress p_addr, uint16_t p_port); - virtual Error listen(int p_max_pending); - virtual Error connect_to_host(IPAddress p_host, uint16_t p_port); - virtual Error poll(PollType p_type, int timeout) const; - virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read); - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false); - virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent); - virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port); - virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port); - - virtual bool is_open() const; - virtual int get_available_bytes() const; - virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const; - - virtual Error set_broadcasting_enabled(bool p_enabled); - virtual void set_blocking_enabled(bool p_enabled); - virtual void set_ipv6_only_enabled(bool p_enabled); - virtual void set_tcp_no_delay_enabled(bool p_enabled); - virtual void set_reuse_address_enabled(bool p_enabled); - virtual void set_reuse_port_enabled(bool p_enabled); - virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name); - virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name); - - NetSocketPosix(); - ~NetSocketPosix(); + virtual Error open(Type p_sock_type, IP::Type &ip_type) override; + virtual void close() override; + virtual Error bind(IPAddress p_addr, uint16_t p_port) override; + virtual Error listen(int p_max_pending) override; + virtual Error connect_to_host(IPAddress p_host, uint16_t p_port) override; + virtual Error poll(PollType p_type, int timeout) const override; + virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) override; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false) override; + virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) override; + virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) override; + virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port) override; + + virtual bool is_open() const override; + virtual int get_available_bytes() const override; + virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const override; + + virtual Error set_broadcasting_enabled(bool p_enabled) override; + virtual void set_blocking_enabled(bool p_enabled) override; + virtual void set_ipv6_only_enabled(bool p_enabled) override; + virtual void set_tcp_no_delay_enabled(bool p_enabled) override; + virtual void set_reuse_address_enabled(bool p_enabled) override; + virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override; + + NetSocketUnix(); + ~NetSocketUnix() override; }; -#endif // NET_SOCKET_POSIX_H +#endif // UNIX_ENABLED && !UNIX_SOCKET_UNAVAILABLE + +#endif // NET_SOCKET_UNIX_H diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 8a9b130068..3976ae7d84 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -38,7 +38,7 @@ #include "drivers/unix/dir_access_unix.h" #include "drivers/unix/file_access_unix.h" #include "drivers/unix/file_access_unix_pipe.h" -#include "drivers/unix/net_socket_posix.h" +#include "drivers/unix/net_socket_unix.h" #include "drivers/unix/thread_posix.h" #include "servers/rendering_server.h" @@ -77,6 +77,7 @@ #include <stdlib.h> #include <string.h> #include <sys/resource.h> +#include <sys/stat.h> #include <sys/time.h> #include <sys/wait.h> #include <time.h> @@ -166,7 +167,9 @@ void OS_Unix::initialize_core() { DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA); DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM); - NetSocketPosix::make_default(); +#ifndef UNIX_SOCKET_UNAVAILABLE + NetSocketUnix::make_default(); +#endif IPUnix::make_default(); process_map = memnew((HashMap<ProcessID, ProcessInfo>)); @@ -175,16 +178,96 @@ void OS_Unix::initialize_core() { void OS_Unix::finalize_core() { memdelete(process_map); - NetSocketPosix::cleanup(); +#ifndef UNIX_SOCKET_UNAVAILABLE + NetSocketUnix::cleanup(); +#endif } Vector<String> OS_Unix::get_video_adapter_driver_info() const { return Vector<String>(); } -String OS_Unix::get_stdin_string() { - char buff[1024]; - return String::utf8(fgets(buff, 1024, stdin)); +String OS_Unix::get_stdin_string(int64_t p_buffer_size) { + Vector<uint8_t> data; + data.resize(p_buffer_size); + if (fgets((char *)data.ptrw(), data.size(), stdin)) { + return String::utf8((char *)data.ptr()); + } + return String(); +} + +PackedByteArray OS_Unix::get_stdin_buffer(int64_t p_buffer_size) { + Vector<uint8_t> data; + data.resize(p_buffer_size); + size_t sz = fread((void *)data.ptrw(), 1, data.size(), stdin); + if (sz > 0) { + data.resize(sz); + return data; + } + return PackedByteArray(); +} + +OS_Unix::StdHandleType OS_Unix::get_stdin_type() const { + int h = fileno(stdin); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; +} + +OS_Unix::StdHandleType OS_Unix::get_stdout_type() const { + int h = fileno(stdout); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; +} + +OS_Unix::StdHandleType OS_Unix::get_stderr_type() const { + int h = fileno(stderr); + if (h == -1) { + return STD_HANDLE_INVALID; + } + + if (isatty(h)) { + return STD_HANDLE_CONSOLE; + } + struct stat statbuf; + if (fstat(h, &statbuf) < 0) { + return STD_HANDLE_UNKNOWN; + } + if (S_ISFIFO(statbuf.st_mode)) { + return STD_HANDLE_PIPE; + } else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { + return STD_HANDLE_FILE; + } + return STD_HANDLE_UNKNOWN; } Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) { diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 3add5df055..2c7920c142 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -58,7 +58,11 @@ public: virtual Vector<String> get_video_adapter_driver_info() const override; - virtual String get_stdin_string() override; + virtual String get_stdin_string(int64_t p_buffer_size = 1024) override; + virtual PackedByteArray get_stdin_buffer(int64_t p_buffer_size = 1024) override; + virtual StdHandleType get_stdin_type() const override; + virtual StdHandleType get_stdout_type() const override; + virtual StdHandleType get_stderr_type() const override; virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; |