From cdc1ca0f1301bb907121292db83f98706722ff1e Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Fri, 2 Dec 2016 04:10:55 +0100 Subject: [PATCH 01/12] Fix _set_ip_addr_port not setting the address. --- drivers/unix/socket_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 5e8e8dfd7a7..84b1ca57409 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -92,7 +92,7 @@ static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_sto r_ip.type = IP_Address::TYPE_IPV6; struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; - copymem(&addr6->sin6_addr.s6_addr, r_ip.field8, 16); + copymem(&r_ip.field8, addr6->sin6_addr.s6_addr, 16); r_port = ntohs(addr6->sin6_port); }; From 4f07b595a17a633c65c5df43ecdaa37667a475e9 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 8 Dec 2016 19:59:16 +0100 Subject: [PATCH 02/12] Properly handle tcp connection failure --- drivers/unix/stream_peer_tcp_posix.cpp | 7 ++++++- platform/windows/stream_peer_winsock.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index b1636abd692..19f1ed4b347 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -107,7 +107,12 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { return OK; }; - return OK; + if (errno == EINPROGRESS || errno == EALREADY) { + return OK; + } + + status = STATUS_ERROR; + return ERR_CONNECTION_ERROR; } else { status = STATUS_CONNECTED; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index 44c17c73e5e..48dd37e9c44 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -98,7 +98,12 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { return OK; }; - return OK; + if (errno == WSAEINPROGRESS || errno == WSAEALREADY) { + return OK; + } + + status = STATUS_ERROR; + return ERR_CONNECTION_ERROR; } else { status = STATUS_CONNECTED; From 311f1f165be12ea290799e42f9951011d997ab40 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 30 Nov 2016 03:01:40 +0100 Subject: [PATCH 03/12] Fix getaddrinfo failing on android --- drivers/unix/ip_unix.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index d998c63dfa7..8b8e09c9126 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -100,7 +100,12 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::Addr hints.ai_flags = 0; } else { hints.ai_family = AF_UNSPEC; +#ifdef ANDROID_ENABLED + // AI_V4MAPPED is not supported by android getaadrinfo + hints.ai_flags = AI_ADDRCONFIG; +#else hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); +#endif }; int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); From 95bdd977686005d3d813eb09aca625384f1774c1 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 30 Nov 2016 20:45:19 +0100 Subject: [PATCH 04/12] Use an instance variable for ip_type in raw sockets PacketPeerUDP/StreamPeerTCP/TCP_Server now uses an instance variable to store the selected ip_type (IPv4/IPv6/ANY, where ANY = dual stack). All calls to resolve addresses, sending/receving data, connecting/listening will use that socket type. --- core/io/packet_peer_udp.cpp | 9 +++++---- core/io/packet_peer_udp.h | 6 ++++-- core/io/stream_peer_tcp.cpp | 7 ++++--- core/io/stream_peer_tcp.h | 4 +++- core/io/tcp_server.cpp | 7 ++++--- core/io/tcp_server.h | 6 ++++-- drivers/unix/packet_peer_udp_posix.cpp | 15 ++++++++------- drivers/unix/packet_peer_udp_posix.h | 4 ++-- drivers/unix/stream_peer_tcp_posix.cpp | 6 ++++-- drivers/unix/stream_peer_tcp_posix.h | 2 +- drivers/unix/tcp_server_posix.cpp | 11 ++++++----- drivers/unix/tcp_server_posix.h | 2 +- platform/windows/packet_peer_udp_winsock.cpp | 15 ++++++++------- platform/windows/packet_peer_udp_winsock.h | 4 ++-- platform/windows/stream_peer_winsock.cpp | 6 ++++-- platform/windows/stream_peer_winsock.h | 2 +- platform/windows/tcp_server_winsock.cpp | 11 ++++++----- platform/windows/tcp_server_winsock.h | 2 +- 18 files changed, 68 insertions(+), 51 deletions(-) diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 925d00a84a7..81066479103 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -38,13 +38,13 @@ String PacketPeerUDP::_get_packet_ip() const { return get_packet_address(); } -Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port,IP_Address::AddrType p_type) { +Error PacketPeerUDP::_set_send_address(const String& p_address, int p_port) { IP_Address ip; if (p_address.is_valid_ip_address()) { ip=p_address; } else { - ip=IP::get_singleton()->resolve_hostname(p_address, p_type); + ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); if (ip==IP_Address()) return ERR_CANT_RESOLVE; } @@ -55,14 +55,14 @@ Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port,IP_Add void PacketPeerUDP::_bind_methods() { - ObjectTypeDB::bind_method(_MD("listen:Error","port","ip_type", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(IP_Address::TYPE_ANY),DEFVAL(65536)); + ObjectTypeDB::bind_method(_MD("listen:Error","port", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536)); ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close); ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening); ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip); //ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address); ObjectTypeDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port); - ObjectTypeDB::bind_method(_MD("set_send_address","host","port","ip_type"),&PacketPeerUDP::_set_send_address,DEFVAL(IP_Address::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address); } @@ -83,4 +83,5 @@ PacketPeerUDP* PacketPeerUDP::create() { PacketPeerUDP::PacketPeerUDP() { + ip_type = IP_Address::TYPE_ANY; } diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 37e700cebdf..011e8dd9aac 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -37,16 +37,18 @@ class PacketPeerUDP : public PacketPeer { protected: + IP_Address::AddrType ip_type; + static PacketPeerUDP* (*_create)(); static void _bind_methods(); String _get_packet_ip() const; - virtual Error _set_send_address(const String& p_address,int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_ANY); + virtual Error _set_send_address(const String& p_address,int p_port); public: - virtual Error listen(int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_ANY, int p_recv_buffer_size=65536)=0; + virtual Error listen(int p_port, int p_recv_buffer_size=65536)=0; virtual void close()=0; virtual Error wait()=0; virtual bool is_listening() const=0; diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 528f2e8cab4..b18bba4d2ea 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -32,13 +32,13 @@ StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL; VARIANT_ENUM_CAST(IP_Address::AddrType); -Error StreamPeerTCP::_connect(const String& p_address,int p_port,IP_Address::AddrType p_type) { +Error StreamPeerTCP::_connect(const String& p_address,int p_port) { IP_Address ip; if (p_address.is_valid_ip_address()) { ip=p_address; } else { - ip=IP::get_singleton()->resolve_hostname(p_address, p_type); + ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); if (ip==IP_Address()) return ERR_CANT_RESOLVE; } @@ -49,7 +49,7 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port,IP_Address::Add void StreamPeerTCP::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect","host","port","ip_type"),&StreamPeerTCP::_connect,DEFVAL(IP_Address::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("connect","host","port"),&StreamPeerTCP::_connect); ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected); ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status); ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host); @@ -79,6 +79,7 @@ StreamPeerTCP* StreamPeerTCP::create() { StreamPeerTCP::StreamPeerTCP() { + ip_type = IP_Address::TYPE_ANY; } StreamPeerTCP::~StreamPeerTCP() { diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index a151fffad87..10e061972bd 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -51,7 +51,9 @@ public: protected: - virtual Error _connect(const String& p_address, int p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); + IP_Address::AddrType ip_type; + + virtual Error _connect(const String& p_address, int p_port); static StreamPeerTCP* (*_create)(); static void _bind_methods(); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 894cccf691f..29e8bd0c02b 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -46,19 +46,19 @@ TCP_Server* TCP_Server::create() { return _create(); } -Error TCP_Server::_listen(uint16_t p_port, IP_Address::AddrType p_type, DVector p_accepted_hosts) { +Error TCP_Server::_listen(uint16_t p_port, DVector p_accepted_hosts) { List hosts; for(int i=0;i())); + ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector())); ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); ObjectTypeDB::bind_method(_MD("stop"),&TCP_Server::stop); @@ -68,4 +68,5 @@ void TCP_Server::_bind_methods() { TCP_Server::TCP_Server() { + ip_type = IP_Address::TYPE_ANY; } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 02678950086..c380db52d06 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -38,14 +38,16 @@ class TCP_Server : public Reference { OBJ_TYPE( TCP_Server, Reference ); protected: + IP_Address::AddrType ip_type; + static TCP_Server* (*_create)(); //bind helper - Error _listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY ,DVector p_accepted_hosts=DVector()); + Error _listen(uint16_t p_port, DVector p_accepted_hosts=DVector()); static void _bind_methods(); public: - virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY, const List *p_accepted_hosts=NULL)=0; + virtual Error listen(uint16_t p_port, const List *p_accepted_hosts=NULL)=0; virtual bool is_connection_available() const=0; virtual Ref take_connection()=0; diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index ed295f04599..52f2c07134b 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -96,7 +96,7 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED); - int sock = _get_socket(peer_addr.type); + int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); @@ -119,15 +119,15 @@ int PacketPeerUDPPosix::get_max_packet_size() const{ return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_type, int p_recv_buffer_size) { +Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) { close(); - int sock = _get_socket(p_type); + int sock = _get_socket(); if (sock == -1 ) return ERR_CANT_CREATE; - if(p_type == IP_Address::TYPE_IPV6) { + if(ip_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) { @@ -136,7 +136,7 @@ Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_type, int p_ } sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); @@ -225,12 +225,12 @@ int PacketPeerUDPPosix::get_packet_port() const{ return packet_port; } -int PacketPeerUDPPosix::_get_socket(IP_Address::AddrType p_type) { +int PacketPeerUDPPosix::_get_socket() { if (sockfd != -1) return sockfd; - sockfd = _socket_create(p_type, SOCK_DGRAM, IPPROTO_UDP); + sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP); return sockfd; } @@ -259,6 +259,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { packet_port=0; queue_count=0; peer_port=0; + ip_type = IP_Address::TYPE_ANY; } PacketPeerUDPPosix::~PacketPeerUDPPosix() { diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h index 13b6969e538..e679d18df4f 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -52,7 +52,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP { IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); + _FORCE_INLINE_ int _get_socket(); static PacketPeerUDP* _create(); virtual Error _poll(bool p_block); @@ -65,7 +65,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); + virtual Error listen(int p_port, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 19f1ed4b347..95e56aa40bd 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -122,8 +122,9 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { return OK; }; -void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) { +void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type) { + ip_type = p_ip_type; sockfd = p_sockfd; #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -142,7 +143,7 @@ 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); - sockfd = _socket_create(p_host.type, SOCK_STREAM, IPPROTO_TCP); + sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == -1) { ERR_PRINT("Socket creation failed!"); disconnect(); @@ -392,6 +393,7 @@ StreamPeerTCPPosix::StreamPeerTCPPosix() { sockfd = -1; status = STATUS_NONE; peer_port = 0; + ip_type = IP_Address::TYPE_ANY; }; StreamPeerTCPPosix::~StreamPeerTCPPosix() { diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index a379efe3ca9..1d3e94c7c2b 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -69,7 +69,7 @@ public: virtual int get_available_bytes() const; - void set_socket(int p_sockfd, IP_Address p_host, int p_port); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type); virtual IP_Address get_connected_host() const; virtual uint16_t get_connected_port() const; diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 7028c1a1074..e6f3614cb56 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -68,14 +68,14 @@ void TCPServerPosix::make_default() { TCP_Server::_create = TCPServerPosix::_create; }; -Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List *p_accepted_hosts) { +Error TCPServerPosix::listen(uint16_t p_port,const List *p_accepted_hosts) { int sockfd; - sockfd = _socket_create(p_type, SOCK_STREAM, IPPROTO_TCP); + sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); ERR_FAIL_COND_V(sockfd == -1, FAILED); - if(p_type == IP_Address::TYPE_IPV6) { + if(ip_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) { @@ -95,7 +95,7 @@ Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const } struct sockaddr_storage addr; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, p_accepted_hosts); // automatically fill with my IP TODO: use p_accepted_hosts @@ -164,7 +164,7 @@ Ref TCPServerPosix::take_connection() { int port; _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, port); + conn->set_socket(fd, ip, port, ip_type); return conn; }; @@ -183,6 +183,7 @@ void TCPServerPosix::stop() { TCPServerPosix::TCPServerPosix() { listen_sockfd = -1; + ip_type = IP_Address::TYPE_ANY; }; TCPServerPosix::~TCPServerPosix() { diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index a700b6ae0e6..570bcaab129 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, const List *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port,const List *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref take_connection(); diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 73c6116aa3b..595f1edd8b5 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -71,7 +71,7 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si } Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(peer_addr.type); + int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); @@ -112,14 +112,14 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { }; } -Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_type, int p_recv_buffer_size) { +Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) { close(); - int sock = _get_socket(p_type); + int sock = _get_socket(); if (sock == -1 ) return ERR_CANT_CREATE; - if(p_type == IP_Address::TYPE_IPV6) { + if(ip_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) { @@ -128,7 +128,7 @@ Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_type, int } struct sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); @@ -242,12 +242,12 @@ int PacketPeerUDPWinsock::get_packet_port() const{ return packet_port; } -int PacketPeerUDPWinsock::_get_socket(IP_Address::AddrType p_type) { +int PacketPeerUDPWinsock::_get_socket() { if (sockfd != -1) return sockfd; - sockfd = _socket_create(p_type, SOCK_DGRAM, IPPROTO_UDP); + sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP); return sockfd; } @@ -277,6 +277,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { packet_port=0; queue_count=0; peer_port=0; + ip_type = IP_Address::TYPE_ANY; } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h index 9837ef66217..1ffdc816858 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -50,7 +50,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP { IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); + _FORCE_INLINE_ int _get_socket(); static PacketPeerUDP* _create(); @@ -67,7 +67,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536); + virtual Error listen(int p_port, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index 48dd37e9c44..d11724eb8e2 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -289,8 +289,9 @@ void StreamPeerWinsock::disconnect() { peer_port = 0; }; -void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port) { +void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type) { + ip_type = p_ip_type; sockfd = p_sockfd; status = STATUS_CONNECTING; peer_host = p_host; @@ -301,7 +302,7 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - sockfd = _socket_create(p_host.type, SOCK_STREAM, IPPROTO_TCP); + sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == INVALID_SOCKET) { ERR_PRINT("Socket creation failed!"); disconnect(); @@ -367,6 +368,7 @@ StreamPeerWinsock::StreamPeerWinsock() { sockfd = INVALID_SOCKET; status = STATUS_NONE; peer_port = 0; + ip_type = IP_Address::TYPE_ANY; }; StreamPeerWinsock::~StreamPeerWinsock() { diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index bbff661490e..7a7ceab8a60 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -68,7 +68,7 @@ public: virtual int get_available_bytes() const; - void set_socket(int p_sockfd, IP_Address p_host, int p_port); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type); virtual IP_Address get_connected_host() const; virtual uint16_t get_connected_port() const; diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index 38a6b041000..eed03c9b8d2 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -63,13 +63,13 @@ void TCPServerWinsock::cleanup() { }; -Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,const List *p_accepted_hosts) { +Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_hosts) { int sockfd; - sockfd = _socket_create(p_type, SOCK_STREAM, IPPROTO_TCP); + sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED); - if(p_type == IP_Address::TYPE_IPV6) { + if(ip_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) { @@ -85,7 +85,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,cons }; struct sockaddr_storage my_addr; - size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); + size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, ip_type, p_accepted_hosts); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -158,7 +158,7 @@ Ref TCPServerWinsock::take_connection() { int port; _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, port); + conn->set_socket(fd, ip, port, ip_type); return conn; }; @@ -176,6 +176,7 @@ void TCPServerWinsock::stop() { TCPServerWinsock::TCPServerWinsock() { listen_sockfd = INVALID_SOCKET; + ip_type = IP_Address::TYPE_ANY; }; TCPServerWinsock::~TCPServerWinsock() { diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h index 115fdb42346..bd6a05c74de 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -39,7 +39,7 @@ class TCPServerWinsock : public TCP_Server { public: - virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type,const List *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port,const List *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref take_connection(); From 9200da58e4c2498c833d9f2505600c7049e80940 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 1 Dec 2016 04:23:57 +0100 Subject: [PATCH 05/12] Automatically map IPv4 address to IPv6 when needed --- drivers/unix/packet_peer_udp_posix.cpp | 2 +- drivers/unix/socket_helpers.h | 20 ++++++++++++++++---- drivers/unix/stream_peer_tcp_posix.cpp | 4 ++-- platform/windows/packet_peer_udp_winsock.cpp | 2 +- platform/windows/stream_peer_winsock.cpp | 4 ++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 52f2c07134b..b1049582c4f 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -99,7 +99,7 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; - size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type); errno = 0; int err; diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 84b1ca57409..a860c2f80e0 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -16,18 +16,30 @@ // 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) { +static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port, IP_Address::AddrType p_sock_type = IP_Address::TYPE_ANY) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); - if (p_ip.type == IP_Address::TYPE_IPV6) { + + // Dual stack (ANY) or matching ip type is required + ERR_FAIL_COND_V(p_sock_type != IP_Address::TYPE_ANY && p_sock_type != p_ip.type,0); + + // IPv6 socket + if (p_sock_type == IP_Address::TYPE_IPV6 || p_sock_type == IP_Address::TYPE_ANY) { struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(p_port); - copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + if(p_ip.type == IP_Address::TYPE_IPV4) { + // Remapping needed + uint16_t base[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, p_ip.field16[0], p_ip.field16[1]}; + copymem(&addr6->sin6_addr.s6_addr, base, 16); + + } else { + copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + } return sizeof(sockaddr_in6); - } else { + } else { // IPv4 socket struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; addr4->sin_family = AF_INET; // host byte order diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 95e56aa40bd..8aae1e77a80 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -98,7 +98,7 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { }; struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, ip_type); if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) { @@ -159,7 +159,7 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { #endif struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, ip_type); errno = 0; if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1 && errno != EINPROGRESS) { diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 595f1edd8b5..9a5f6c6a342 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -74,7 +74,7 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; - size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type); _set_blocking(true); diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index d11724eb8e2..f03ecca22aa 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -88,7 +88,7 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { }; struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, ip_type); if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { @@ -318,7 +318,7 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { }; struct sockaddr_storage their_addr; - size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, ip_type); if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { From 4d90a4fcd5fcdca42df47062f94a1fa4e5635a94 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 1 Dec 2016 05:05:44 +0100 Subject: [PATCH 06/12] Move V6ONLY flag selection inside helpers --- drivers/unix/packet_peer_udp_posix.cpp | 8 -------- drivers/unix/socket_helpers.h | 8 ++++---- drivers/unix/tcp_server_posix.cpp | 7 ------- platform/windows/packet_peer_udp_winsock.cpp | 8 -------- platform/windows/tcp_server_winsock.cpp | 8 -------- 5 files changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index b1049582c4f..44a3e65e002 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -127,14 +127,6 @@ Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) { if (sock == -1 ) return ERR_CANT_CREATE; - if(ip_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, ip_type, NULL); diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index a860c2f80e0..aec4ec88438 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -78,10 +78,10 @@ static int _socket_create(IP_Address::AddrType p_type, int type, int 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"); + // Select IPv4 over IPv6 mapping + int opt = p_type != IP_Address::TYPE_ANY; + if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&opt, sizeof(opt)) != 0) { + WARN_PRINT("Unable to set/unset IPv4 address mapping over IPv6"); } } diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index e6f3614cb56..bf3b7369ebd 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -75,13 +75,6 @@ Error TCPServerPosix::listen(uint16_t p_port,const List *p_accepted_host ERR_FAIL_COND_V(sockfd == -1, FAILED); - if(ip_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/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 9a5f6c6a342..4201a3e8658 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -119,14 +119,6 @@ Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) { if (sock == -1 ) return ERR_CANT_CREATE; - if(ip_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"); - } - } - struct sockaddr_storage addr = {0}; size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL); diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index eed03c9b8d2..89460eeaa56 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -69,14 +69,6 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_ho sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED); - if(ip_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"); - } - } - unsigned long par = 1; if (ioctlsocket(sockfd, FIONBIO, &par)) { perror("setting non-block mode"); From c18c5013f837ea7d4de2f022d36f84e0abce6439 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 1 Dec 2016 06:34:05 +0100 Subject: [PATCH 07/12] Migrate int.IP_TYPE_ constants to IP.TYPE_ --- core/io/http_client.cpp | 6 ++-- core/io/http_client.h | 2 +- core/io/ip.cpp | 17 ++++++----- core/io/ip.h | 18 ++++++------ core/io/packet_peer_udp.cpp | 4 +-- core/io/packet_peer_udp.h | 3 +- core/io/stream_peer_tcp.cpp | 4 +-- core/io/stream_peer_tcp.h | 2 +- core/io/tcp_server.cpp | 4 +-- core/io/tcp_server.h | 2 +- core/variant_call.cpp | 4 --- doc/base/classes.xml | 30 ++++++-------------- drivers/unix/ip_unix.cpp | 6 ++-- drivers/unix/ip_unix.h | 2 +- drivers/unix/packet_peer_udp_posix.cpp | 2 +- drivers/unix/socket_helpers.h | 18 ++++++------ drivers/unix/stream_peer_tcp_posix.cpp | 4 +-- drivers/unix/stream_peer_tcp_posix.h | 2 +- drivers/unix/tcp_server_posix.cpp | 2 +- platform/windows/packet_peer_udp_winsock.cpp | 2 +- platform/windows/stream_peer_winsock.cpp | 4 +-- platform/windows/stream_peer_winsock.h | 2 +- platform/windows/tcp_server_winsock.cpp | 2 +- 23 files changed, 61 insertions(+), 81 deletions(-) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index e3289b452c5..c9c674d4f02 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,9 +29,7 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" -VARIANT_ENUM_CAST(IP_Address::AddrType); - -Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP_Address::AddrType p_addr_type){ +Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP::Type p_addr_type){ close(); conn_port=p_port; @@ -636,7 +634,7 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP_Address::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP::TYPE_ANY)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); diff --git a/core/io/http_client.h b/core/io/http_client.h index ba464c34c75..34812616dd9 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -165,7 +165,7 @@ public: //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request - Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP_Address::AddrType p_addr_type = IP_Address::TYPE_ANY); + Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP::Type p_addr_type = IP::TYPE_ANY); void set_connection(const Ref& p_connection); Ref get_connection() const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index f0f273af1ad..00835c26d57 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -32,7 +32,6 @@ #include "hash_map.h" VARIANT_ENUM_CAST(IP::ResolverStatus); -VARIANT_ENUM_CAST(IP_Address::AddrType); /************* RESOLVER ******************/ @@ -44,12 +43,12 @@ struct _IP_ResolverPrivate { volatile IP::ResolverStatus status; IP_Address response; String hostname; - IP_Address::AddrType type; + IP::Type type; void clear() { status = IP::RESOLVER_STATUS_NONE; response = IP_Address(); - type = IP_Address::TYPE_NONE; + type = IP::TYPE_NONE; hostname=""; }; @@ -112,7 +111,7 @@ struct _IP_ResolverPrivate { -IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { +IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) { GLOBAL_LOCK_FUNCTION; @@ -126,7 +125,7 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p return res; } -IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type) { +IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Type p_type) { GLOBAL_LOCK_FUNCTION; @@ -212,8 +211,8 @@ Array IP::_get_local_addresses() const { void IP::_bind_methods() { - ObjectTypeDB::bind_method(_MD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP_Address::TYPE_ANY)); - ObjectTypeDB::bind_method(_MD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP_Address::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP::TYPE_ANY)); ObjectTypeDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status); ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address); ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item); @@ -228,6 +227,10 @@ void IP::_bind_methods() { BIND_CONSTANT( RESOLVER_MAX_QUERIES ); BIND_CONSTANT( RESOLVER_INVALID_ID ); + BIND_CONSTANT( TYPE_NONE ); + BIND_CONSTANT( TYPE_IPV4 ); + BIND_CONSTANT( TYPE_IPV6 ); + BIND_CONSTANT( TYPE_ANY ); } diff --git a/core/io/ip.h b/core/io/ip.h index 742dd0e740f..64360b9a760 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -48,12 +48,12 @@ public: RESOLVER_STATUS_ERROR, }; - enum AddressType { + enum Type { - ADDRESS_IPV4 = 1, - ADDRESS_IPV6 = 2, - - ADDRESS_ANY = 3, + TYPE_NONE = 0, + TYPE_IPV4 = 1, + TYPE_IPV6 = 2, + TYPE_ANY = 3, }; enum { @@ -73,7 +73,7 @@ protected: static IP*singleton; static void _bind_methods(); - virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY)=0; + virtual IP_Address _resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY)=0; Array _get_local_addresses() const; static IP* (*_create)(); @@ -81,9 +81,9 @@ public: - IP_Address resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); + IP_Address resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY); // async resolver hostname - ResolverID resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY); + ResolverID resolve_hostname_queue_item(const String& p_hostname, Type p_type = TYPE_ANY); ResolverStatus get_resolve_item_status(ResolverID p_id) const; IP_Address get_resolve_item_address(ResolverID p_id) const; virtual void get_local_addresses(List *r_addresses) const=0; @@ -101,4 +101,6 @@ public: }; +VARIANT_ENUM_CAST(IP::Type); + #endif // IP_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 81066479103..dadef8a6f49 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -31,8 +31,6 @@ PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL; -VARIANT_ENUM_CAST(IP_Address::AddrType); - String PacketPeerUDP::_get_packet_ip() const { return get_packet_address(); @@ -83,5 +81,5 @@ PacketPeerUDP* PacketPeerUDP::create() { PacketPeerUDP::PacketPeerUDP() { - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; } diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 011e8dd9aac..821007a6286 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -30,6 +30,7 @@ #define PACKET_PEER_UDP_H +#include "io/ip.h" #include "io/packet_peer.h" class PacketPeerUDP : public PacketPeer { @@ -37,7 +38,7 @@ class PacketPeerUDP : public PacketPeer { protected: - IP_Address::AddrType ip_type; + IP::Type ip_type; static PacketPeerUDP* (*_create)(); static void _bind_methods(); diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index b18bba4d2ea..d374f54a8ab 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -30,8 +30,6 @@ StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL; -VARIANT_ENUM_CAST(IP_Address::AddrType); - Error StreamPeerTCP::_connect(const String& p_address,int p_port) { IP_Address ip; @@ -79,7 +77,7 @@ StreamPeerTCP* StreamPeerTCP::create() { StreamPeerTCP::StreamPeerTCP() { - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; } StreamPeerTCP::~StreamPeerTCP() { diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 10e061972bd..f44784d2b5c 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -51,7 +51,7 @@ public: protected: - IP_Address::AddrType ip_type; + IP::Type ip_type; virtual Error _connect(const String& p_address, int p_port); static StreamPeerTCP* (*_create)(); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 29e8bd0c02b..0dcec8001ef 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -30,8 +30,6 @@ TCP_Server* (*TCP_Server::_create)()=NULL; -VARIANT_ENUM_CAST(IP_Address::AddrType); - Ref TCP_Server::create_ref() { if (!_create) @@ -68,5 +66,5 @@ void TCP_Server::_bind_methods() { TCP_Server::TCP_Server() { - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index c380db52d06..aef62eb7151 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -38,7 +38,7 @@ class TCP_Server : public Reference { OBJ_TYPE( TCP_Server, Reference ); protected: - IP_Address::AddrType ip_type; + IP::Type ip_type; static TCP_Server* (*_create)(); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 0379ae019b7..99d5d1065e0 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1825,10 +1825,6 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_BILINEAR",Image::INTERPOLATE_BILINEAR); _VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_CUBIC",Image::INTERPOLATE_CUBIC); - _VariantCall::add_constant(Variant::INT, "IP_TYPE_NONE", IP_Address::TYPE_NONE); - _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV4", IP_Address::TYPE_IPV4); - _VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV6", IP_Address::TYPE_IPV6); - _VariantCall::add_constant(Variant::INT, "IP_TYPE_ANY", IP_Address::TYPE_ANY); } void unregister_variant_methods() { diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 07e2f719f9f..f1809d9e257 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -16082,7 +16082,7 @@ - + Resolve a given hostname, blocking. Resolved hostname is returned as an IPv4 or IPv6 depending on "ip_type". @@ -16093,7 +16093,7 @@ - + Create a queue item for resolving a given hostname to an IPv4 or IPv6 depending on "ip_type". The queue ID is returned, or RESOLVER_INVALID_ID on error. @@ -25375,15 +25375,10 @@ - - - + - Make this [PacketPeerUDP] listen on the "port" using protocol "ip_type" and a buffer size "recv_buf_size". Listens on all available adresses. - IP_TYPE_IPV4 = IPv4 only - IP_TYPE_IPV6 = IPv6 only - IP_TYPE_ANY = Dual stack (supports both IPv6 and IPv4 connections). + Make this [PacketPeerUDP] listen on the "port" with a buffer size "recv_buf_size". Listens on all available addresses. @@ -25393,10 +25388,8 @@ - - - Set the destination address and port for sending packets and variables, a hostname will be resolved using "ip_type" (v4/v6/any) if valid. + Set the destination address and port for sending packets and variables, a hostname will be resolved using if valid. @@ -39206,10 +39199,8 @@ - - - Connect to the specified host:port pair. A hostname will be resolved using "ip_type" (v4/v6/any) if valid. Returns [OK] on success or [FAILED] on failure. + Connect to the specified host:port pair. A hostname will be resolved if valid. Returns [OK] on success or [FAILED] on failure. @@ -40532,15 +40523,10 @@ - - - + - Listen on a port using protocol "ip_type", alternatively give a white-list of accepted hosts. - IP_TYPE_IPV4 = IPv4 only - IP_TYPE_IPV6 = IPv6 only - IP_TYPE_ANY = Dual stack (supports both IPv6 and IPv4 connections). + Listen on a port using protocol, alternatively give a white-list of accepted hosts. diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 8b8e09c9126..ad49d0dca4b 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -87,15 +87,15 @@ static IP_Address _sockaddr2ip(struct sockaddr* p_addr) { return ip; }; -IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) { +IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, Type p_type) { struct addrinfo hints; struct addrinfo* result; memset(&hints, 0, sizeof(struct addrinfo)); - if (p_type == IP_Address::TYPE_IPV4) { + if (p_type == TYPE_IPV4) { hints.ai_family = AF_INET; - } else if (p_type == IP_Address::TYPE_IPV6) { + } else if (p_type == TYPE_IPV6) { hints.ai_family = AF_INET6; hints.ai_flags = 0; } else { diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h index d198a330e72..9959d45a1a9 100644 --- a/drivers/unix/ip_unix.h +++ b/drivers/unix/ip_unix.h @@ -36,7 +36,7 @@ class IP_Unix : public IP { OBJ_TYPE(IP_Unix, IP); - virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type); + virtual IP_Address _resolve_hostname(const String& p_hostname, IP::Type p_type); static IP* _create_unix(); public: diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 44a3e65e002..2b007f546fd 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -251,7 +251,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { packet_port=0; queue_count=0; peer_port=0; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; } PacketPeerUDPPosix::~PacketPeerUDPPosix() { diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index aec4ec88438..ffe20159478 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -16,15 +16,15 @@ // 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, IP_Address::AddrType p_sock_type = IP_Address::TYPE_ANY) { +static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port, IP::Type p_sock_type = IP::TYPE_ANY) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); // Dual stack (ANY) or matching ip type is required - ERR_FAIL_COND_V(p_sock_type != IP_Address::TYPE_ANY && p_sock_type != p_ip.type,0); + ERR_FAIL_COND_V(p_sock_type != IP::TYPE_ANY && p_sock_type != p_ip.type,0); // IPv6 socket - if (p_sock_type == IP_Address::TYPE_IPV6 || p_sock_type == IP_Address::TYPE_ANY) { + if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) { struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; addr6->sin6_family = AF_INET6; @@ -49,10 +49,10 @@ static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p }; }; -static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List *p_accepted_hosts) { +static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP::Type p_sock_type, const List *p_accepted_hosts) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); - if (p_address_type == IP_Address::TYPE_IPV4) { + if (p_sock_type == IP::TYPE_IPV4) { struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; addr4->sin_family = AF_INET; addr4->sin_port = htons(p_port); @@ -68,18 +68,18 @@ 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) { +static int _socket_create(IP::Type 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); + ERR_FAIL_COND_V(p_type > IP::TYPE_ANY || p_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER); - int family = p_type == IP_Address::TYPE_IPV4 ? AF_INET : AF_INET6; + int family = p_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6; int sockfd = socket(family, type, protocol); ERR_FAIL_COND_V( sockfd == -1, -1 ); if(family == AF_INET6) { // Select IPv4 over IPv6 mapping - int opt = p_type != IP_Address::TYPE_ANY; + int opt = p_type != IP::TYPE_ANY; if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&opt, sizeof(opt)) != 0) { WARN_PRINT("Unable to set/unset IPv4 address mapping over IPv6"); } diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 8aae1e77a80..fc6b08e64db 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -122,7 +122,7 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { return OK; }; -void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type) { +void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) { ip_type = p_ip_type; sockfd = p_sockfd; @@ -393,7 +393,7 @@ StreamPeerTCPPosix::StreamPeerTCPPosix() { sockfd = -1; status = STATUS_NONE; peer_port = 0; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; }; StreamPeerTCPPosix::~StreamPeerTCPPosix() { diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 1d3e94c7c2b..e4e912117fe 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -69,7 +69,7 @@ public: virtual int get_available_bytes() const; - void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type); virtual IP_Address get_connected_host() const; virtual uint16_t get_connected_port() const; diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index bf3b7369ebd..dd00e0bf7e8 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -176,7 +176,7 @@ void TCPServerPosix::stop() { TCPServerPosix::TCPServerPosix() { listen_sockfd = -1; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; }; TCPServerPosix::~TCPServerPosix() { diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 4201a3e8658..53524f807f6 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -269,7 +269,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { packet_port=0; queue_count=0; peer_port=0; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index f03ecca22aa..d40504b2d46 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -289,7 +289,7 @@ void StreamPeerWinsock::disconnect() { peer_port = 0; }; -void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type) { +void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) { ip_type = p_ip_type; sockfd = p_sockfd; @@ -368,7 +368,7 @@ StreamPeerWinsock::StreamPeerWinsock() { sockfd = INVALID_SOCKET; status = STATUS_NONE; peer_port = 0; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; }; StreamPeerWinsock::~StreamPeerWinsock() { diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index 7a7ceab8a60..c2b63e1ffb3 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -68,7 +68,7 @@ public: virtual int get_available_bytes() const; - void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP_Address::AddrType p_ip_type); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type); virtual IP_Address get_connected_host() const; virtual uint16_t get_connected_port() const; diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index 89460eeaa56..ac37f80e7a2 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -168,7 +168,7 @@ void TCPServerWinsock::stop() { TCPServerWinsock::TCPServerWinsock() { listen_sockfd = INVALID_SOCKET; - ip_type = IP_Address::TYPE_ANY; + ip_type = IP::TYPE_ANY; }; TCPServerWinsock::~TCPServerWinsock() { From a77a0118f6b0d0878a53e2c963d91763b311163d Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 1 Dec 2016 09:01:09 +0100 Subject: [PATCH 08/12] Allow setting ip_type for TCP/UDP and HTTP classes --- core/io/http_client.cpp | 4 ++++ core/io/http_client.h | 1 + core/io/packet_peer_udp.cpp | 6 ++++++ core/io/packet_peer_udp.h | 1 + core/io/stream_peer_tcp.cpp | 6 ++++++ core/io/stream_peer_tcp.h | 1 + core/io/tcp_server.cpp | 6 ++++++ core/io/tcp_server.h | 1 + scene/main/http_request.cpp | 4 ++++ scene/main/http_request.h | 1 + 10 files changed, 31 insertions(+) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index c9c674d4f02..24314e3a1a8 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,6 +29,10 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" +void HTTPClient::set_ip_type(IP::Type p_type) { + tcp_connection->set_ip_type(p_type); +} + Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP::Type p_addr_type){ close(); diff --git a/core/io/http_client.h b/core/io/http_client.h index 34812616dd9..7ec418fd237 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -164,6 +164,7 @@ private: public: + virtual void set_ip_type(IP::Type p_type); //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP::Type p_addr_type = IP::TYPE_ANY); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index dadef8a6f49..d04371f4fc1 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -51,8 +51,14 @@ Error PacketPeerUDP::_set_send_address(const String& p_address, int p_port) { return OK; } +void PacketPeerUDP::set_ip_type(IP::Type p_type) { + close(); + ip_type = p_type; +} + void PacketPeerUDP::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&PacketPeerUDP::set_ip_type); ObjectTypeDB::bind_method(_MD("listen:Error","port", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536)); ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close); ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 821007a6286..600d4c46822 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -49,6 +49,7 @@ protected: public: + virtual void set_ip_type(IP::Type p_type); virtual Error listen(int p_port, int p_recv_buffer_size=65536)=0; virtual void close()=0; virtual Error wait()=0; diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index d374f54a8ab..6c26dbb89ea 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -45,8 +45,14 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) { return OK; } +void StreamPeerTCP::set_ip_type(IP::Type p_type) { + disconnect(); + ip_type = p_type; +} + void StreamPeerTCP::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&StreamPeerTCP::set_ip_type); ObjectTypeDB::bind_method(_MD("connect","host","port"),&StreamPeerTCP::_connect); ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected); ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status); diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index f44784d2b5c..2408f4cdf53 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -59,6 +59,7 @@ protected: public: + virtual void set_ip_type(IP::Type p_type); virtual Error connect(const IP_Address& p_host, uint16_t p_port)=0; //read/write from streampeer diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 0dcec8001ef..5f3f74131d1 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -54,8 +54,14 @@ Error TCP_Server::_listen(uint16_t p_port, DVector p_accepted_hosts) { } +void TCP_Server::set_ip_type(IP::Type p_type) { + stop(); + ip_type = p_type; +} + void TCP_Server::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&TCP_Server::set_ip_type); ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector())); ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index aef62eb7151..5b8b40b704e 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -47,6 +47,7 @@ protected: static void _bind_methods(); public: + virtual void set_ip_type(IP::Type p_type); virtual Error listen(uint16_t p_port, const List *p_accepted_hosts=NULL)=0; virtual bool is_connection_available() const=0; virtual Ref take_connection()=0; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 4b6cbde859f..46678123126 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -28,6 +28,10 @@ /*************************************************************************/ #include "http_request.h" +void HTTPRequest::set_ip_type(IP::Type p_type) { + client->set_ip_type(p_type); +} + void HTTPRequest::_redirect_request(const String& p_new_url) { diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 705799f0447..4dd79234b0b 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -116,6 +116,7 @@ protected: static void _bind_methods(); public: + virtual void set_ip_type(IP::Type p_type); Error request(const String& p_url, const Vector& p_custom_headers=Vector(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; From 1aff508dd9713abf0db0d0436fa7f7c4788c5a4a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 5 Dec 2016 16:32:38 +0100 Subject: [PATCH 09/12] IP_Address now handle IPv4 and IPv6 transparently IP_Address changes: - Converts to and from String transparently while handling IPv4 as IPv6 mapped (::ffff:[IP]) address internally. - Completely remove AddrType enum. - Setting/Getting of ip array is now only possible through dedicated functions (ie. set_ipv4, get_ipv4, set_ipv6, get_ipv6) - Add function to know if the address is a valid IPv4 (for IP implementation and enet) --- bin/tests/test_string.cpp | 2 +- core/io/ip.cpp | 9 ++- core/io/ip_address.cpp | 82 ++++++++++++-------- core/io/ip_address.h | 21 +++-- drivers/unix/ip_unix.cpp | 16 ++-- drivers/unix/packet_peer_udp_posix.cpp | 20 ++--- drivers/unix/socket_helpers.h | 30 ++++--- drivers/unix/stream_peer_tcp_posix.cpp | 2 +- modules/enet/networked_multiplayer_enet.cpp | 11 ++- platform/windows/packet_peer_udp_winsock.cpp | 18 +++-- platform/windows/stream_peer_winsock.cpp | 2 +- 11 files changed, 112 insertions(+), 101 deletions(-) diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp index 4990c58896c..d99ad4476f5 100644 --- a/bin/tests/test_string.cpp +++ b/bin/tests/test_string.cpp @@ -842,7 +842,7 @@ bool test_29() { IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); OS::get_singleton()->print("ip0 is %ls\n", String(ip0).c_str()); - IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, IP_Address::TYPE_IPV6); + IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); OS::get_singleton()->print("ip6 is %ls\n", String(ip).c_str()); IP_Address ip2("fe80::52e5:49ff:fe93:1baf"); diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 00835c26d57..113be976ac2 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -82,7 +82,7 @@ struct _IP_ResolverPrivate { continue; queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); - if (queue[i].response.type==IP_Address::TYPE_NONE) + if (queue[i].response==IP_Address()) queue[i].status=IP::RESOLVER_STATUS_ERROR; else queue[i].status=IP::RESOLVER_STATUS_DONE; @@ -116,7 +116,8 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) { GLOBAL_LOCK_FUNCTION; if (resolver->cache.has(p_hostname)) - if (resolver->cache[p_hostname].type & p_type != 0) + if ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) || + (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4)) return resolver->cache[p_hostname]; // requested type is different from type in cache. continue resolution, if successful it'll overwrite cache @@ -138,7 +139,9 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Typ resolver->queue[id].hostname=p_hostname; resolver->queue[id].type = p_type; - if (resolver->cache.has(p_hostname) && (resolver->cache[p_hostname].type & p_type) != 0) { + if (resolver->cache.has(p_hostname) && + ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) || + (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4))) { resolver->queue[id].response=resolver->cache[p_hostname]; resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; } else { diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 9887cd132ba..7df5fe79ece 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -38,21 +38,18 @@ IP_Address::operator Variant() const { IP_Address::operator String() const { - if (type == TYPE_NONE) - return "0.0.0.0"; - if (type == TYPE_IPV4) - return itos(field8[0])+"."+itos(field8[1])+"."+itos(field8[2])+"."+itos(field8[3]); - else { - String ret; - for (int i=0; i<8; i++) { - if (i > 0) - ret = ret + ":"; - uint16_t num = (field8[i*2] << 8) + field8[i*2+1]; - ret = ret + String::num_int64(num, 16); - }; - - return ret; + if(is_ipv4()) + // IPv4 address mapped to IPv6 + return itos(field8[12])+"."+itos(field8[13])+"."+itos(field8[14])+"."+itos(field8[15]); + String ret; + for (int i=0; i<8; i++) { + if (i > 0) + ret = ret + ":"; + uint16_t num = (field8[i*2] << 8) + field8[i*2+1]; + ret = ret + String::num_int64(num, 16); }; + + return ret; } static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) { @@ -176,17 +173,41 @@ void IP_Address::clear() { memset(&field8[0], 0, sizeof(field8)); }; +bool IP_Address::is_ipv4() const{ + return (field32[0]==0 && field32[1]==0 && field16[4]==0 && field16[5]==0xffff); +} + +const uint8_t *IP_Address::get_ipv4() const{ + ERR_FAIL_COND_V(!is_ipv4(),0); + return &(field8[12]); +} + +void IP_Address::set_ipv4(const uint8_t *p_ip) { + clear(); + field16[5]=0xffff; + field32[3]=*((const uint32_t *)p_ip); +} + +const uint8_t *IP_Address::get_ipv6() const{ + return field8; +} + +void IP_Address::set_ipv6(const uint8_t *p_buf) { + clear(); + for (int i=0; i<16; i++) + field8[i] = p_buf[i]; +} + IP_Address::IP_Address(const String& p_string) { clear(); if (p_string.find(":") >= 0) { _parse_ipv6(p_string); - type = TYPE_IPV6; } else { - - _parse_ipv4(p_string, 0, &field8[0]); - type = TYPE_IPV4; + // Mapped to IPv6 + field16[5] = 0xffff; + _parse_ipv4(p_string, 0, &field8[12]); }; } @@ -198,25 +219,22 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { p_dst[3] = (p_n >> 0) & 0xff; }; -IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, IP_Address::AddrType p_type) { +IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6) { - type = p_type; - memset(&field8[0], 0, sizeof(field8)); - if (p_type == TYPE_IPV4) { - field8[0]=p_a; - field8[1]=p_b; - field8[2]=p_c; - field8[3]=p_d; - } else if (type == TYPE_IPV6) { + clear(); + if (!is_v6) { + // Mapped to IPv6 + field16[5]=0xffff; + field8[12]=p_a; + field8[13]=p_b; + field8[14]=p_c; + field8[15]=p_d; + } else { _32_to_buf(&field8[0], p_a); _32_to_buf(&field8[4], p_b); _32_to_buf(&field8[8], p_c); _32_to_buf(&field8[12], p_d); - } else { - type = TYPE_NONE; - ERR_EXPLAIN("Invalid type specified for IP_Address (use TYPE_IPV4 or TYPE_IPV6"); - ERR_FAIL(); - }; + } } diff --git a/core/io/ip_address.h b/core/io/ip_address.h index fe13d70611e..b7c1649547d 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -33,16 +33,7 @@ struct IP_Address { -public: - enum AddrType { - TYPE_NONE = 0, - TYPE_IPV4 = 1, - TYPE_IPV6 = 2, - - TYPE_ANY = 3, - }; - - AddrType type; +private: union { uint8_t field8[16]; @@ -70,11 +61,17 @@ public: } void clear(); + bool is_ipv4() const; + const uint8_t *get_ipv4() const; + void set_ipv4(const uint8_t *p_ip); + + const uint8_t *get_ipv6() const; + void set_ipv6(const uint8_t *buf); operator String() const; IP_Address(const String& p_string); - IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, AddrType p_type=TYPE_IPV4); - IP_Address() { clear(); type=TYPE_NONE; } + IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6=false); + IP_Address() { clear(); } }; diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index ad49d0dca4b..42c93c35175 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -75,13 +75,10 @@ static IP_Address _sockaddr2ip(struct sockaddr* p_addr) { IP_Address ip; if (p_addr->sa_family == AF_INET) { struct sockaddr_in* addr = (struct sockaddr_in*)p_addr; - ip.field32[0] = *((unsigned long*)&addr->sin_addr); - ip.type = IP_Address::TYPE_IPV4; + ip.set_ipv4((uint8_t *)&(addr->sin_addr)); } else { struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; - for (int i=0; i<16; i++) - ip.field8[i] = addr6->sin6_addr.s6_addr[i]; - ip.type = IP_Address::TYPE_IPV6; + ip.set_ipv6(addr6->sin6_addr.s6_addr); }; return ip; @@ -189,15 +186,12 @@ void IP_Unix::get_local_addresses(List *r_addresses) const { SOCKADDR_IN* ipv4 = reinterpret_cast(address->Address.lpSockaddr); - ip.field32[0] = *((unsigned long*)&ipv4->sin_addr); - ip.type = IP_Address::TYPE_IPV4; + ip.set_ipv4((uint8_t *)&(ipv4->sin_addr)); } else { // ipv6 SOCKADDR_IN6* ipv6 = reinterpret_cast(address->Address.lpSockaddr); - for (int i=0; i<16; i++) { - ip.field8[i] = ipv6->sin6_addr.s6_addr[i]; - }; - ip.type = IP_Address::TYPE_IPV6; + + ip.set_ipv6(ipv6->sin6_addr.s6_addr); }; diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 2b007f546fd..62290c41721 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -76,12 +76,14 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size uint32_t size; uint8_t type; rb.read(&type, 1, true); - if (type == IP_Address::TYPE_IPV4) { - rb.read((uint8_t*)&packet_ip.field8,4,true); - packet_ip.type = IP_Address::TYPE_IPV4; + if (type == IP::TYPE_IPV4) { + uint8_t ip[4]; + rb.read(ip,4,true); + packet_ip.set_ipv4(ip); } else { - rb.read((uint8_t*)&packet_ip.field8,16,true); - packet_ip.type = IP_Address::TYPE_IPV6; + uint8_t ipv6[16]; + rb.read(ipv6,16,true); + packet_ip.set_ipv6(ipv6); }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); @@ -94,7 +96,7 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size } Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED); + ERR_FAIL_COND_V(peer_addr == IP_Address(), ERR_UNCONFIGURED); int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); @@ -163,7 +165,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { uint32_t port = 0; if (from.ss_family == AF_INET) { - uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + uint8_t type = (uint8_t)IP::TYPE_IPV4; rb.write(&type, 1); struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; rb.write((uint8_t*)&sin_from->sin_addr, 4); @@ -171,7 +173,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { } else if (from.ss_family == AF_INET6) { - uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + uint8_t type = (uint8_t)IP::TYPE_IPV6; rb.write(&type, 1); struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; @@ -181,7 +183,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { } else { // WARN_PRINT("Ignoring packet with unknown address family"); - uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + uint8_t type = (uint8_t)IP::TYPE_NONE; rb.write(&type, 1); }; diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index ffe20159478..962f228c3c6 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -20,31 +20,30 @@ static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p memset(p_addr, 0, sizeof(struct sockaddr_storage)); - // Dual stack (ANY) or matching ip type is required - ERR_FAIL_COND_V(p_sock_type != IP::TYPE_ANY && p_sock_type != p_ip.type,0); + ERR_FAIL_COND_V(p_ip==IP_Address(),0); // IPv6 socket if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) { + // IPv6 only socket with IPv4 address + ERR_FAIL_COND_V(p_sock_type == IP::TYPE_IPV6 && p_ip.is_ipv4(),0); + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(p_port); - if(p_ip.type == IP_Address::TYPE_IPV4) { - // Remapping needed - uint16_t base[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0xffff, p_ip.field16[0], p_ip.field16[1]}; - copymem(&addr6->sin6_addr.s6_addr, base, 16); - - } else { - copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); - } + copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16); return sizeof(sockaddr_in6); } else { // IPv4 socket + // IPv4 socket with IPv6 address + ERR_FAIL_COND_V(!p_ip.is_ipv4(),0); + + uint32_t ipv4 = *((uint32_t *)p_ip.get_ipv4()); struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; - addr4->sin_family = AF_INET; // host byte order + addr4->sin_family = AF_INET; addr4->sin_port = htons(p_port); // short, network byte order - addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]); + copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 16); return sizeof(sockaddr_in); }; }; @@ -92,19 +91,16 @@ static int _socket_create(IP::Type p_type, int type, int protocol) { 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) { - r_ip.type = IP_Address::TYPE_IPV4; struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; - r_ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; + r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr)); r_port = ntohs(addr4->sin_port); } else if (p_addr->ss_family == AF_INET6) { - r_ip.type = IP_Address::TYPE_IPV6; - struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; - copymem(&r_ip.field8, addr6->sin6_addr.s6_addr, 16); + r_ip.set_ipv6(addr6->sin6_addr.s6_addr); r_port = ntohs(addr6->sin6_port); }; diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index fc6b08e64db..8889f997fdc 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -141,7 +141,7 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, 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); + ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER); sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == -1) { diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index a82283591d9..7a28f59ab29 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -77,7 +77,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port, int p_in_bandwidth, int p_out_bandwidth){ ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE); - ERR_FAIL_COND_V(p_ip.type != IP_Address::TYPE_IPV4, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!p_ip.is_ipv4(), ERR_INVALID_PARAMETER); host = enet_host_create (NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, @@ -91,7 +91,7 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port _setup_compressor(); ENetAddress address; - address.host=p_ip.field32[0]; + address.host=*((uint32_t *)p_ip.get_ipv4()); address.port=p_port; //enet_address_set_host (& address, "localhost"); @@ -150,8 +150,7 @@ void NetworkedMultiplayerENet::poll(){ } IP_Address ip; - ip.type = IP_Address::TYPE_IPV4; - ip.field32[0]=event.peer -> address.host; + ip.set_ipv4((uint8_t *)&(event.peer -> address.host)); int *new_id = memnew( int ); *new_id = event.data; @@ -685,6 +684,6 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){ // sets IP for ENet to bind when using create_server // if no IP is set, then ENet bind to ENET_HOST_ANY void NetworkedMultiplayerENet::set_bind_ip(const IP_Address& p_ip){ - ERR_FAIL_COND(p_ip.type != IP_Address::TYPE_IPV4); - bind_ip=p_ip.field32[0]; + ERR_FAIL_COND(!p_ip.is_ipv4()); + bind_ip=*(uint32_t *)p_ip.get_ipv4(); } diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 53524f807f6..bad967eedd9 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -53,12 +53,14 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si uint32_t size; uint8_t type; rb.read(&type, 1, true); - if (type == IP_Address::TYPE_IPV4) { - rb.read((uint8_t*)&packet_ip.field8,4,true); - packet_ip.type = IP_Address::TYPE_IPV4; + if (type == IP::TYPE_IPV4) { + uint8_t ip[4]; + rb.read(ip,4,true); + packet_ip.set_ipv4(ip); } else { - rb.read((uint8_t*)&packet_ip.field8,16,true); - packet_ip.type = IP_Address::TYPE_IPV6; + uint8_t ip[16]; + rb.read(ip,16,true); + packet_ip.set_ipv6(ip); }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); @@ -162,7 +164,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { uint32_t port = 0; if (from.ss_family == AF_INET) { - uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + uint8_t type = (uint8_t)IP::TYPE_IPV4; rb.write(&type, 1); struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; rb.write((uint8_t*)&sin_from->sin_addr, 4); @@ -170,7 +172,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { } else if (from.ss_family == AF_INET6) { - uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + uint8_t type = (uint8_t)IP::TYPE_IPV6; rb.write(&type, 1); struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; @@ -180,7 +182,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { } else { // WARN_PRINT("Ignoring packet with unknown address family"); - uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + uint8_t type = (uint8_t)IP::TYPE_NONE; rb.write(&type, 1); }; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index d40504b2d46..e9a017a0fad 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -300,7 +300,7 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER); sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == INVALID_SOCKET) { From c1c1ec690e66c09178b6883e332a38fc9d8ad890 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 8 Dec 2016 12:18:18 +0100 Subject: [PATCH 10/12] Separate hostname resolve cache based on ip_type --- core/io/ip.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 113be976ac2..0b607624221 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -107,6 +107,10 @@ struct _IP_ResolverPrivate { HashMap cache; + static String get_cache_key(String p_hostname, IP::Type p_type) { + return itos(p_type) + p_hostname; + } + }; @@ -115,14 +119,12 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) { GLOBAL_LOCK_FUNCTION; - if (resolver->cache.has(p_hostname)) - if ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) || - (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4)) - return resolver->cache[p_hostname]; - // requested type is different from type in cache. continue resolution, if successful it'll overwrite cache + String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); + if (resolver->cache.has(key)) + return resolver->cache[key]; IP_Address res = _resolve_hostname(p_hostname, p_type); - resolver->cache[p_hostname]=res; + resolver->cache[key]=res; return res; } @@ -137,12 +139,11 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Typ return id; } + String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); resolver->queue[id].hostname=p_hostname; resolver->queue[id].type = p_type; - if (resolver->cache.has(p_hostname) && - ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) || - (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4))) { - resolver->queue[id].response=resolver->cache[p_hostname]; + if (resolver->cache.has(key)) { + resolver->queue[id].response=resolver->cache[key]; resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; } else { resolver->queue[id].response=IP_Address(); @@ -196,7 +197,10 @@ void IP::clear_cache(const String &p_hostname) { if (p_hostname.empty()) { resolver->cache.clear(); } else { - resolver->cache.erase(p_hostname); + resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_NONE)); + resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV4)); + resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV6)); + resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_ANY)); } }; From de23ce11b51847b7b8bfc10ecf5926827516ac5a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Fri, 9 Dec 2016 23:38:14 +0100 Subject: [PATCH 11/12] Remove old unused AI_V4MAPPED flag to getaddrinfo --- drivers/unix/ip_unix.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 42c93c35175..e4860dc6d84 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -37,9 +37,6 @@ #ifndef AI_ADDRCONFIG #define AI_ADDRCONFIG 0x00000400 #endif - #ifndef AI_V4MAPPED - #define AI_V4MAPPED 0x00000800 - #endif #ifdef UWP_ENABLED #include #include @@ -97,12 +94,7 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, Type p_type) { hints.ai_flags = 0; } else { hints.ai_family = AF_UNSPEC; -#ifdef ANDROID_ENABLED - // AI_V4MAPPED is not supported by android getaadrinfo hints.ai_flags = AI_ADDRCONFIG; -#else - hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); -#endif }; int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result); From d194e1c48e5d161f0310ee17e63f1951e2c50de6 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 13 Dec 2016 10:57:05 +0100 Subject: [PATCH 12/12] Expose HTTP classes' set_ip_type to scripting --- core/io/http_client.cpp | 11 +++++++---- core/io/http_client.h | 5 +++-- scene/main/http_request.cpp | 1 + scene/main/http_request.h | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 24314e3a1a8..5420521f811 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -30,12 +30,13 @@ #include "io/stream_peer_ssl.h" void HTTPClient::set_ip_type(IP::Type p_type) { - tcp_connection->set_ip_type(p_type); + ip_type = p_type; } -Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP::Type p_addr_type){ +Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){ close(); + tcp_connection->set_ip_type(ip_type); conn_port=p_port; conn_host=p_host; @@ -65,7 +66,7 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_ve status=STATUS_CONNECTING; } else { //is hostname - resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, p_addr_type); + resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, ip_type); status=STATUS_RESOLVING; } @@ -638,7 +639,8 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP::TYPE_ANY)); + ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPClient::set_ip_type); + ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); @@ -764,6 +766,7 @@ String HTTPClient::query_string_from_dict(const Dictionary& p_dict) { HTTPClient::HTTPClient(){ + ip_type = IP::TYPE_ANY; tcp_connection = StreamPeerTCP::create_ref(); resolving = IP::RESOLVER_INVALID_ID; status=STATUS_DISCONNECTED; diff --git a/core/io/http_client.h b/core/io/http_client.h index 7ec418fd237..fdbf47b9cc9 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -132,6 +132,7 @@ public: private: + IP::Type ip_type; Status status; IP::ResolverID resolving; int conn_port; @@ -164,9 +165,9 @@ private: public: - virtual void set_ip_type(IP::Type p_type); + void set_ip_type(IP::Type p_type); //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request - Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP::Type p_addr_type = IP::TYPE_ANY); + Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); void set_connection(const Ref& p_connection); Ref get_connection() const; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 46678123126..46ab3859546 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -539,6 +539,7 @@ int HTTPRequest::get_body_size() const{ void HTTPRequest::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPRequest::set_ip_type); ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String())); ObjectTypeDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 4dd79234b0b..978ad3428b3 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -116,7 +116,7 @@ protected: static void _bind_methods(); public: - virtual void set_ip_type(IP::Type p_type); + void set_ip_type(IP::Type p_type); Error request(const String& p_url, const Vector& p_custom_headers=Vector(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const;