summaryrefslogtreecommitdiff
path: root/drivers/unix
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/unix')
-rw-r--r--drivers/unix/SCsub14
-rw-r--r--drivers/unix/ip_unix.cpp9
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp27
-rw-r--r--drivers/unix/socket_helpers.h32
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp4
-rw-r--r--drivers/unix/tcp_server_posix.cpp12
-rw-r--r--drivers/unix/tcp_server_posix.h2
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();