diff options
Diffstat (limited to 'drivers/unix')
-rw-r--r-- | drivers/unix/SCsub | 14 | ||||
-rw-r--r-- | drivers/unix/ip_unix.cpp | 9 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.cpp | 27 | ||||
-rw-r--r-- | drivers/unix/socket_helpers.h | 32 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.cpp | 4 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.cpp | 12 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.h | 2 |
7 files changed, 76 insertions, 24 deletions
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub index fe427e747f..3766e782e4 100644 --- a/drivers/unix/SCsub +++ b/drivers/unix/SCsub @@ -2,13 +2,13 @@ Import('env') -g_set_p='#ifdef UNIX_ENABLED\n' -g_set_p+='#include "os_unix.h"\n' -g_set_p+='String OS_Unix::get_global_settings_path() const {\n' -g_set_p+='\treturn "' + env["unix_global_settings_path"]+'";\n' -g_set_p+='}\n' -g_set_p+='#endif' -f = open("os_unix_global_settings_path.cpp","wb") +g_set_p = '#ifdef UNIX_ENABLED\n' +g_set_p += '#include "os_unix.h"\n' +g_set_p += 'String OS_Unix::get_global_settings_path() const {\n' +g_set_p += '\treturn "' + env["unix_global_settings_path"] + '";\n' +g_set_p += '}\n' +g_set_p += '#endif' +f = open("os_unix_global_settings_path.cpp", "wb") f.write(g_set_p) f.close() diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index d6d1be3395..e3d32618ee 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -33,6 +33,13 @@ #include <string.h> #ifdef WINDOWS_ENABLED + // Workaround mingw missing flags! + #ifndef AI_ADDRCONFIG + #define AI_ADDRCONFIG 0x00000400 + #endif + #ifndef AI_V4MAPPED + #define AI_V4MAPPED 0x00000800 + #endif #ifdef WINRT_ENABLED #include <ws2tcpip.h> #include <winsock2.h> @@ -90,8 +97,10 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::Addr hints.ai_family = AF_INET; } else if (p_type == IP_Address::TYPE_IPV6) { hints.ai_family = AF_INET6; + hints.ai_flags = 0; } else { hints.ai_family = AF_UNSPEC; + hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); }; int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index d6fc697c6d..ed295f0459 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -119,17 +119,24 @@ int PacketPeerUDPPosix::get_max_packet_size() const{ return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size) { - - ERR_FAIL_COND_V(p_address_type != IP_Address::TYPE_IPV4 && p_address_type != IP_Address::TYPE_IPV6, ERR_INVALID_PARAMETER); +Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_type, int p_recv_buffer_size) { close(); - int sock = _get_socket(p_address_type); + int sock = _get_socket(p_type); + if (sock == -1 ) return ERR_CANT_CREATE; + if(p_type == IP_Address::TYPE_IPV6) { + // Use IPv6 only socket + int yes = 1; + if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) { + WARN_PRINT("Unable to unset IPv4 address mapping over IPv6"); + } + } + sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, NULL); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); @@ -168,7 +175,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { rb.write(&type, 1); struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; rb.write((uint8_t*)&sin_from->sin_addr, 4); - port = sin_from->sin_port; + port = ntohs(sin_from->sin_port); } else if (from.ss_family == AF_INET6) { @@ -178,7 +185,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; rb.write((uint8_t*)&s6_from->sin6_addr, 16); - port = s6_from->sin6_port; + port = ntohs(s6_from->sin6_port); } else { // WARN_PRINT("Ignoring packet with unknown address family"); @@ -223,11 +230,7 @@ int PacketPeerUDPPosix::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; - - sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); - ERR_FAIL_COND_V( sockfd == -1, -1 ); - //fcntl(sockfd, F_SETFL, O_NONBLOCK); + sockfd = _socket_create(p_type, SOCK_DGRAM, IPPROTO_UDP); return sockfd; } diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 4ee40e3d3d..3aaae82da2 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -3,6 +3,17 @@ #include <string.h> +#ifdef WINDOWS_ENABLED + // Workaround mingw missing flags! + #ifndef IPV6_V6ONLY + #define IPV6_V6ONLY 27 + #endif +#endif + +#ifdef WINRT_ENABLED +#define in6addr_any IN6ADDR_ANY_INIT +#endif + // helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { @@ -45,6 +56,27 @@ static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, }; }; +static int _socket_create(IP_Address::AddrType p_type, int type, int protocol) { + + ERR_FAIL_COND_V(p_type > IP_Address::TYPE_ANY || p_type < IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); + + int family = p_type == IP_Address::TYPE_IPV4 ? AF_INET : AF_INET6; + int sockfd = socket(family, type, protocol); + + ERR_FAIL_COND_V( sockfd == -1, -1 ); + + if(family == AF_INET6) { + // Ensure IPv4 over IPv6 is enabled + int no = 0; + if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&no, sizeof(no)) != 0) { + WARN_PRINT("Unable to set IPv4 address mapping over IPv6"); + } + } + + return sockfd; +} + + static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_storage* p_addr) { if (p_addr->ss_family == AF_INET) { diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index f2915b0a16..b1636abd69 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -137,8 +137,8 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; - if ((sockfd = socket(family, SOCK_STREAM, 0)) == -1) { + sockfd = _socket_create(p_host.type, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == -1) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 05b739804c..7028c1a107 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -71,9 +71,17 @@ void TCPServerPosix::make_default() { Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts) { int sockfd; - int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; - sockfd = socket(family, SOCK_STREAM, 0); + sockfd = _socket_create(p_type, SOCK_STREAM, IPPROTO_TCP); + ERR_FAIL_COND_V(sockfd == -1, FAILED); + + if(p_type == IP_Address::TYPE_IPV6) { + // Use IPv6 only socket + int yes = 1; + if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) { + WARN_PRINT("Unable to unset IPv4 address mapping over IPv6"); + } + } #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); #else diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 134ec494cb..a700b6ae0e 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -40,7 +40,7 @@ class TCPServerPosix : public TCP_Server { public: - virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref<StreamPeerTCP> take_connection(); |