From e4b9b37ccf8495be674bc15cf0bf9d76fe94e6be Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 10:48:50 +0100 Subject: [PATCH 01/12] Avoid calling close when polling a UDP peer without socket --- drivers/unix/packet_peer_udp_posix.cpp | 4 ++++ platform/windows/packet_peer_udp_winsock.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 6adb3eea702..8cdfa035958 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -157,6 +157,10 @@ Error PacketPeerUDPPosix::wait() { Error PacketPeerUDPPosix::_poll(bool p_wait) { + if (sockfd==-1) { + return FAILED; + } + struct sockaddr_storage from = {0}; socklen_t len = sizeof(struct sockaddr_storage); int ret; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 5baa01c289a..e091df6d009 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -152,6 +152,9 @@ Error PacketPeerUDPWinsock::wait() { } Error PacketPeerUDPWinsock::_poll(bool p_wait) { + if (sockfd==-1) { + return FAILED; + } _set_blocking(p_wait); From 98a7e2b4e09791705cd9dfd4d13611bc02fe47d4 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 17 Jan 2017 09:22:56 +0100 Subject: [PATCH 02/12] Convert validity checks of IP_Address to is_valid method. --- core/io/ip.cpp | 2 +- core/io/ip_address.cpp | 22 ++++++++++++++++++---- core/io/ip_address.h | 7 +++++++ core/io/packet_peer_udp.cpp | 2 +- core/io/stream_peer_tcp.cpp | 2 +- drivers/unix/packet_peer_udp_posix.cpp | 2 +- drivers/unix/socket_helpers.h | 2 +- drivers/unix/stream_peer_tcp_posix.cpp | 2 +- platform/windows/stream_peer_winsock.cpp | 2 +- 9 files changed, 32 insertions(+), 11 deletions(-) diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 0eb1f221c9a..13e5494dd4c 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==IP_Address()) + if (!queue[i].response.is_valid()) queue[i].status=IP::RESOLVER_STATUS_ERROR; else queue[i].status=IP::RESOLVER_STATUS_DONE; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 1fda7fed7b9..2d9708f5e55 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -38,6 +38,9 @@ IP_Address::operator Variant() const { IP_Address::operator String() const { + if(!valid) + return ""; + if(is_ipv4()) // IPv4 address mapped to IPv6 return itos(field8[12])+"."+itos(field8[13])+"."+itos(field8[14])+"."+itos(field8[15]); @@ -171,6 +174,7 @@ void IP_Address::_parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret void IP_Address::clear() { memset(&field8[0], 0, sizeof(field8)); + valid = false; }; bool IP_Address::is_ipv4() const{ @@ -184,6 +188,7 @@ const uint8_t *IP_Address::get_ipv4() const{ void IP_Address::set_ipv4(const uint8_t *p_ip) { clear(); + valid = true; field16[5]=0xffff; field32[3]=*((const uint32_t *)p_ip); } @@ -194,6 +199,7 @@ const uint8_t *IP_Address::get_ipv6() const{ void IP_Address::set_ipv6(const uint8_t *p_buf) { clear(); + valid = true; for (int i=0; i<16; i++) field8[i] = p_buf[i]; } @@ -201,14 +207,21 @@ void IP_Address::set_ipv6(const uint8_t *p_buf) { IP_Address::IP_Address(const String& p_string) { clear(); - if (p_string.find(":") >= 0) { + if (p_string.find(":") >= 0) { + // IPv6 _parse_ipv6(p_string); - } else { - // Mapped to IPv6 + valid = true; + + } else if (p_string.get_slice_count(".") == 4) { + // IPv4 (mapped to IPv6 internally) field16[5] = 0xffff; _parse_ipv4(p_string, 0, &field8[12]); - }; + valid = true; + + } else { + ERR_PRINT("Invalid IP address"); + } } _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { @@ -222,6 +235,7 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) { IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6) { clear(); + valid = true; if (!is_v6) { // Mapped to IPv6 field16[5]=0xffff; diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 87f32b0ac2b..3e86e0bcba0 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -41,6 +41,8 @@ private: uint32_t field32[4]; }; + bool valid; + protected: void _parse_ipv6(const String& p_string); void _parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret); @@ -48,12 +50,16 @@ protected: public: //operator Variant() const; bool operator==(const IP_Address& p_ip) const { + if (p_ip.valid != valid) return false; + if (!valid) return false; for (int i=0; i<4; i++) if (field32[i] != p_ip.field32[i]) return false; return true; } bool operator!=(const IP_Address& p_ip) const { + if (p_ip.valid != valid) return true; + if (!valid) return true; for (int i=0; i<4; i++) if (field32[i] != p_ip.field32[i]) return true; @@ -61,6 +67,7 @@ public: } void clear(); + bool is_valid() const {return valid;} bool is_ipv4() const; const uint8_t *get_ipv4() const; void set_ipv4(const uint8_t *p_ip); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 9fec807bfb0..4756d1699bc 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -43,7 +43,7 @@ Error PacketPeerUDP::_set_dest_address(const String& p_address, int p_port) { ip=p_address; } else { ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); - if (ip==IP_Address()) + if (!ip.is_valid()) return ERR_CANT_RESOLVE; } diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 0a59c329953..1cf7842af7b 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -37,7 +37,7 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) { ip=p_address; } else { ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); - if (ip==IP_Address()) + if (!ip.is_valid()) return ERR_CANT_RESOLVE; } diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 8cdfa035958..3d01a23f948 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -96,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 == IP_Address(), ERR_UNCONFIGURED); + ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED); int sock = _get_socket(); ERR_FAIL_COND_V( sock == -1, FAILED ); diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 6d4f7e7519e..7dc34811db5 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -16,7 +16,7 @@ static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p memset(p_addr, 0, sizeof(struct sockaddr_storage)); - ERR_FAIL_COND_V(p_ip==IP_Address(),0); + ERR_FAIL_COND_V(!p_ip.is_valid(),0); // IPv6 socket if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) { diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index ae4bf77c365..96258e63f65 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -142,7 +142,7 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, Error StreamPeerTCPPosix::connect_to_host(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( !p_host.is_valid(), ERR_INVALID_PARAMETER); sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index 9d3e3623dad..6edd9c62fea 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -299,7 +299,7 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, Error StreamPeerWinsock::connect_to_host(const IP_Address& p_host, uint16_t p_port) { - ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( !p_host.is_valid(), ERR_INVALID_PARAMETER); sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); From 4198291cd45da7fce278d21cd5ef4a506086d5f8 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 04:03:51 +0100 Subject: [PATCH 03/12] IP_Address can now be a wildcard (not a valid IP, used for binding) --- core/io/ip_address.cpp | 7 ++++++- core/io/ip_address.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 2d9708f5e55..69c7df619da 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -175,6 +175,7 @@ void IP_Address::clear() { memset(&field8[0], 0, sizeof(field8)); valid = false; + wildcard = false; }; bool IP_Address::is_ipv4() const{ @@ -208,7 +209,11 @@ IP_Address::IP_Address(const String& p_string) { clear(); - if (p_string.find(":") >= 0) { + if (p_string == "*") { + // Wildcard (not a vaild IP) + wildcard = true; + + } else if (p_string.find(":") >= 0) { // IPv6 _parse_ipv6(p_string); valid = true; diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 3e86e0bcba0..257836601a5 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -42,6 +42,7 @@ private: }; bool valid; + bool wildcard; protected: void _parse_ipv6(const String& p_string); @@ -67,6 +68,7 @@ public: } void clear(); + bool is_wildcard() const {return wildcard;} bool is_valid() const {return valid;} bool is_ipv4() const; const uint8_t *get_ipv4() const; From b2839343cab66880f647c77da7b2e1826761776a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 08:37:24 +0100 Subject: [PATCH 04/12] Implement TCP Server bind address --- core/io/tcp_server.cpp | 12 +---------- core/io/tcp_server.h | 3 +-- drivers/unix/packet_peer_udp_posix.cpp | 2 +- drivers/unix/socket_helpers.h | 14 ++++++++++--- drivers/unix/tcp_server_posix.cpp | 21 ++++++++++++++------ drivers/unix/tcp_server_posix.h | 3 ++- platform/windows/packet_peer_udp_winsock.cpp | 2 +- platform/windows/tcp_server_winsock.cpp | 20 +++++++++++++++---- platform/windows/tcp_server_winsock.h | 3 ++- 9 files changed, 50 insertions(+), 30 deletions(-) diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index bfa5dce58f0..b8a783152ad 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -44,16 +44,6 @@ TCP_Server* TCP_Server::create() { return _create(); } -Error TCP_Server::_listen(uint16_t p_port, PoolVector p_accepted_hosts) { - - List hosts; - for(int i=0;i())); + ClassDB::bind_method(_MD("listen","port","bind_address"),&TCP_Server::listen,DEFVAL("*")); ClassDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ClassDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); ClassDB::bind_method(_MD("stop"),&TCP_Server::stop); diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 3d7b3ddd8d4..cf9a1e4a932 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -43,12 +43,11 @@ protected: static TCP_Server* (*_create)(); //bind helper - Error _listen(uint16_t p_port, PoolVector p_accepted_hosts=PoolVector()); 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 Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*"))=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 3d01a23f948..f8a0f556b44 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -130,7 +130,7 @@ Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) { return ERR_CANT_CREATE; sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, IP_Address()); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 7dc34811db5..bb1a8665525 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -44,21 +44,29 @@ 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::Type p_sock_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 IP_Address p_bind_address) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); 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); - addr4->sin_addr.s_addr = INADDR_ANY; // TODO: use accepted hosts list + if(p_bind_address.is_valid()) { + copymem(&addr4->sin_addr.s_addr, p_bind_address.get_ipv4(), 4); + } else { + addr4->sin_addr.s_addr = INADDR_ANY; + } return sizeof(sockaddr_in); } else { struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(p_port); - addr6->sin6_addr = in6addr_any; // TODO: use accepted hosts list + if(p_bind_address.is_valid()) { + copymem(&addr6->sin6_addr.s6_addr, p_bind_address.get_ipv6(), 16); + } else { + addr6->sin6_addr = in6addr_any; + } return sizeof(sockaddr_in6); }; }; diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 0178f08b8cf..5f3c46451ae 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -68,10 +68,19 @@ void TCPServerPosix::make_default() { TCP_Server::_create = TCPServerPosix::_create; }; -Error TCPServerPosix::listen(uint16_t p_port,const List *p_accepted_hosts) { +Error TCPServerPosix::listen(uint16_t p_port,const IP_Address p_bind_address) { + + ERR_FAIL_COND_V(listen_sockfd!=-1,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); int sockfd; - sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); + sock_type = ip_type; + + // If the bind address is valid use its type as the socket type + if (p_bind_address.is_valid()) + sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); ERR_FAIL_COND_V(sockfd == -1, FAILED); @@ -88,9 +97,7 @@ Error TCPServerPosix::listen(uint16_t p_port,const List *p_accepted_host } struct sockaddr_storage addr; - 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 + size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, p_bind_address); if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) { @@ -157,7 +164,7 @@ Ref TCPServerPosix::take_connection() { int port; _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, port, ip_type); + conn->set_socket(fd, ip, port, sock_type); return conn; }; @@ -170,6 +177,7 @@ void TCPServerPosix::stop() { }; listen_sockfd = -1; + sock_type = IP::TYPE_NONE; }; @@ -177,6 +185,7 @@ TCPServerPosix::TCPServerPosix() { listen_sockfd = -1; ip_type = IP::TYPE_ANY; + sock_type = IP::TYPE_NONE; }; TCPServerPosix::~TCPServerPosix() { diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h index 6f9fa8cb5bb..ea42d0fc0c1 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -35,12 +35,13 @@ class TCPServerPosix : public TCP_Server { int listen_sockfd; + IP::Type sock_type; static TCP_Server* _create(); public: - virtual Error listen(uint16_t p_port,const List *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address p_bind_address=IP_Address("*")); 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 e091df6d009..14c181a897c 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -122,7 +122,7 @@ Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) { return ERR_CANT_CREATE; struct sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, IP_Address()); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index 1c3682adfac..c29645cef7f 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -63,10 +63,20 @@ void TCPServerWinsock::cleanup() { }; -Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_hosts) { +Error TCPServerWinsock::listen(uint16_t p_port,const IP_Address p_bind_address) { + + ERR_FAIL_COND_V(listen_sockfd!=-1,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); int sockfd; - sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); + sock_type = ip_type; + + // If the bind address is valid use its type as the socket type + if (p_bind_address.is_valid()) + sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + + sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED); unsigned long par = 1; @@ -77,7 +87,7 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_ho }; struct sockaddr_storage my_addr; - size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, ip_type, p_accepted_hosts); + size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, sock_type, p_bind_address); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -150,7 +160,7 @@ Ref TCPServerWinsock::take_connection() { int port; _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, port, ip_type); + conn->set_socket(fd, ip, port, sock_type); return conn; }; @@ -162,6 +172,7 @@ void TCPServerWinsock::stop() { }; listen_sockfd = -1; + sock_type = IP::TYPE_NONE; }; @@ -169,6 +180,7 @@ TCPServerWinsock::TCPServerWinsock() { listen_sockfd = INVALID_SOCKET; ip_type = IP::TYPE_ANY; + sock_type = IP::TYPE_NONE; }; TCPServerWinsock::~TCPServerWinsock() { diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h index 5c544436a7b..afbd1e9c873 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -34,12 +34,13 @@ class TCPServerWinsock : public TCP_Server { int listen_sockfd; + IP::Type sock_type; static TCP_Server* _create(); public: - virtual Error listen(uint16_t p_port,const List *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*")); virtual bool is_connection_available() const; virtual Ref take_connection(); From 2fe4ef66991b483640f59873c22b3af671626ccc Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 10:24:26 +0100 Subject: [PATCH 05/12] Implement UDP listen bind address --- core/io/packet_peer_udp.cpp | 2 +- core/io/packet_peer_udp.h | 4 +-- drivers/unix/packet_peer_udp_posix.cpp | 24 ++++++++++++++---- drivers/unix/packet_peer_udp_posix.h | 3 ++- platform/windows/packet_peer_udp_winsock.cpp | 26 ++++++++++++++++---- platform/windows/packet_peer_udp_winsock.h | 3 ++- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 4756d1699bc..3ea5e878f62 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -59,7 +59,7 @@ void PacketPeerUDP::set_ip_type(IP::Type p_type) { void PacketPeerUDP::_bind_methods() { ClassDB::bind_method(_MD("set_ip_type","ip_type"),&PacketPeerUDP::set_ip_type); - ClassDB::bind_method(_MD("listen:Error","port", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536)); + ClassDB::bind_method(_MD("listen:Error","port", "bind_address", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL("*"),DEFVAL(65536)); ClassDB::bind_method(_MD("close"),&PacketPeerUDP::close); ClassDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); ClassDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 17952b4ac11..e0e560de1ed 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -45,12 +45,12 @@ protected: String _get_packet_ip() const; - virtual Error _set_dest_address(const String& p_address,int p_port); + Error _set_dest_address(const String& p_address,int p_port); public: virtual void set_ip_type(IP::Type p_type); - virtual Error listen(int p_port, int p_recv_buffer_size=65536)=0; + virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536)=0; virtual void close()=0; virtual Error wait()=0; virtual bool is_listening() const=0; diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index f8a0f556b44..15c3b7dfe9d 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -98,10 +98,13 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED); + if (sock_type==IP::TYPE_NONE) + sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + 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, ip_type); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type); errno = 0; int err; @@ -121,16 +124,23 @@ int PacketPeerUDPPosix::get_max_packet_size() const{ return 512; // uhm maybe not } -Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) { +Error PacketPeerUDPPosix::listen(int p_port, IP_Address p_bind_address, int p_recv_buffer_size) { + + ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER); + + sock_type = ip_type; + + if(p_bind_address.is_valid()) + sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - close(); int sock = _get_socket(); if (sock == -1 ) return ERR_CANT_CREATE; sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, IP_Address()); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address()); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); @@ -145,6 +155,7 @@ void PacketPeerUDPPosix::close(){ if (sockfd != -1) ::close(sockfd); sockfd=-1; + sock_type = IP::TYPE_NONE; rb.resize(8); queue_count=0; } @@ -225,10 +236,12 @@ int PacketPeerUDPPosix::get_packet_port() const{ int PacketPeerUDPPosix::_get_socket() { + ERR_FAIL_COND_V(sock_type==IP::TYPE_NONE, -1); + if (sockfd != -1) return sockfd; - sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP); + sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP); return sockfd; } @@ -257,6 +270,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { packet_port=0; queue_count=0; peer_port=0; + sock_type = IP::TYPE_NONE; ip_type = IP::TYPE_ANY; } diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h index ead7174a9d5..ac68344d782 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -48,6 +48,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP { mutable int packet_port; mutable int queue_count; int sockfd; + IP::Type sock_type; IP_Address peer_addr; int peer_port; @@ -65,7 +66,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port, int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 14c181a897c..9759f15195e 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -73,10 +73,15 @@ 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){ + ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED); + + if(sock_type==IP::TYPE_NONE) + sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + 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, ip_type); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type); _set_blocking(true); @@ -114,15 +119,22 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { }; } -Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) { +Error PacketPeerUDPWinsock::listen(int p_port, IP_Address p_bind_address, int p_recv_buffer_size) { + + ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER); + + sock_type = ip_type; + + if(p_bind_address.is_valid()) + sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; - close(); int sock = _get_socket(); if (sock == -1 ) return ERR_CANT_CREATE; struct sockaddr_storage addr = {0}; - size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, IP_Address()); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address()); if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); @@ -141,6 +153,7 @@ void PacketPeerUDPWinsock::close(){ if (sockfd != -1) ::closesocket(sockfd); sockfd=-1; + sock_type = IP::TYPE_NONE; rb.resize(8); queue_count=0; } @@ -241,10 +254,12 @@ int PacketPeerUDPWinsock::get_packet_port() const{ int PacketPeerUDPWinsock::_get_socket() { + ERR_FAIL_COND_V(sock_type==IP::TYPE_NONE,-1); + if (sockfd != -1) return sockfd; - sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP); + sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP); return sockfd; } @@ -275,6 +290,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { queue_count=0; peer_port=0; ip_type = IP::TYPE_ANY; + sock_type = IP::TYPE_NONE; } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h index 18e6bd8f3d5..dcd9da9a79e 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -46,6 +46,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP { mutable int packet_port; mutable int queue_count; int sockfd; + IP::Type sock_type; IP_Address peer_addr; int peer_port; @@ -67,7 +68,7 @@ public: virtual int get_max_packet_size() const; - virtual Error listen(int p_port, int p_recv_buffer_size=65536); + virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; From 88a56ba783d36d52a1023759e69f026b1ae255b4 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 12:47:12 +0100 Subject: [PATCH 06/12] Remove set_ip_type from network classes (no longer needed) - TCP: - `listen` bind to wildcard "*" -> dual stack socket - `listen` bind to address -> socket from address type - `connect` -> resolve using best protocol (UNSPEC), socket from address type - UDP: - `listen` bind to wildcard "*" -> dual stack socket - `listen` bind to address -> socket from address type - `put_packet`/`put_var` -> resolve using TYPE_ANY (UNSPEC), socket from address type (to change socket type you must first call `close` it) --- core/io/http_client.cpp | 9 +-------- core/io/http_client.h | 2 -- core/io/packet_peer_udp.cpp | 10 ++-------- core/io/packet_peer_udp.h | 3 --- core/io/stream_peer_tcp.cpp | 9 +-------- core/io/stream_peer_tcp.h | 3 --- core/io/tcp_server.cpp | 8 +------- core/io/tcp_server.h | 3 --- drivers/unix/packet_peer_udp_posix.cpp | 3 +-- drivers/unix/stream_peer_tcp_posix.cpp | 6 ++---- drivers/unix/stream_peer_tcp_posix.h | 2 +- drivers/unix/tcp_server_posix.cpp | 3 +-- platform/windows/packet_peer_udp_winsock.cpp | 3 +-- platform/windows/stream_peer_winsock.cpp | 6 ++---- platform/windows/stream_peer_winsock.h | 2 +- platform/windows/tcp_server_winsock.cpp | 3 +-- scene/main/http_request.cpp | 5 ----- scene/main/http_request.h | 1 - 18 files changed, 15 insertions(+), 66 deletions(-) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 63c8abbbadf..6a16552b3c3 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -29,14 +29,9 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" -void HTTPClient::set_ip_type(IP::Type p_type) { - ip_type = p_type; -} - Error HTTPClient::connect_to_host(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; @@ -66,7 +61,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,b status=STATUS_CONNECTING; } else { //is hostname - resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, ip_type); + resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host); status=STATUS_RESOLVING; } @@ -639,7 +634,6 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received) void HTTPClient::_bind_methods() { - ClassDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPClient::set_ip_type); ClassDB::bind_method(_MD("connect_to_host:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect_to_host,DEFVAL(false),DEFVAL(true)); ClassDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); ClassDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); @@ -766,7 +760,6 @@ 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 496d22530b2..4b0c1b730fd 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -132,7 +132,6 @@ public: private: - IP::Type ip_type; Status status; IP::ResolverID resolving; int conn_port; @@ -165,7 +164,6 @@ private: public: - 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_to_host(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index 3ea5e878f62..769a513bb3c 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -42,7 +42,7 @@ Error PacketPeerUDP::_set_dest_address(const String& p_address, int p_port) { if (p_address.is_valid_ip_address()) { ip=p_address; } else { - ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); + ip=IP::get_singleton()->resolve_hostname(p_address); if (!ip.is_valid()) return ERR_CANT_RESOLVE; } @@ -51,14 +51,8 @@ Error PacketPeerUDP::_set_dest_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() { - ClassDB::bind_method(_MD("set_ip_type","ip_type"),&PacketPeerUDP::set_ip_type); ClassDB::bind_method(_MD("listen:Error","port", "bind_address", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL("*"),DEFVAL(65536)); ClassDB::bind_method(_MD("close"),&PacketPeerUDP::close); ClassDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait); @@ -87,5 +81,5 @@ PacketPeerUDP* PacketPeerUDP::create() { PacketPeerUDP::PacketPeerUDP() { - ip_type = IP::TYPE_ANY; + } diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index e0e560de1ed..726406887c5 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -38,8 +38,6 @@ class PacketPeerUDP : public PacketPeer { protected: - IP::Type ip_type; - static PacketPeerUDP* (*_create)(); static void _bind_methods(); @@ -49,7 +47,6 @@ protected: public: - virtual void set_ip_type(IP::Type p_type); virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), 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 1cf7842af7b..96594ef65a5 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -36,7 +36,7 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) { if (p_address.is_valid_ip_address()) { ip=p_address; } else { - ip=IP::get_singleton()->resolve_hostname(p_address, ip_type); + ip=IP::get_singleton()->resolve_hostname(p_address); if (!ip.is_valid()) return ERR_CANT_RESOLVE; } @@ -45,14 +45,8 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) { return OK; } -void StreamPeerTCP::set_ip_type(IP::Type p_type) { - disconnect_from_host(); - ip_type = p_type; -} - void StreamPeerTCP::_bind_methods() { - ClassDB::bind_method(_MD("set_ip_type","ip_type"),&StreamPeerTCP::set_ip_type); ClassDB::bind_method(_MD("connect_to_host","host","port"),&StreamPeerTCP::_connect); ClassDB::bind_method(_MD("is_connected_to_host"),&StreamPeerTCP::is_connected_to_host); ClassDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status); @@ -83,7 +77,6 @@ StreamPeerTCP* StreamPeerTCP::create() { StreamPeerTCP::StreamPeerTCP() { - ip_type = IP::TYPE_ANY; } StreamPeerTCP::~StreamPeerTCP() { diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 2b25f317395..44013787435 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -51,15 +51,12 @@ public: protected: - IP::Type ip_type; - virtual Error _connect(const String& p_address, int p_port); static StreamPeerTCP* (*_create)(); static void _bind_methods(); public: - virtual void set_ip_type(IP::Type p_type); virtual Error connect_to_host(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 b8a783152ad..cb82b3fc553 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -44,14 +44,8 @@ TCP_Server* TCP_Server::create() { return _create(); } -void TCP_Server::set_ip_type(IP::Type p_type) { - stop(); - ip_type = p_type; -} - void TCP_Server::_bind_methods() { - ClassDB::bind_method(_MD("set_ip_type","ip_type"),&TCP_Server::set_ip_type); ClassDB::bind_method(_MD("listen","port","bind_address"),&TCP_Server::listen,DEFVAL("*")); ClassDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available); ClassDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection); @@ -62,5 +56,5 @@ void TCP_Server::_bind_methods() { TCP_Server::TCP_Server() { - ip_type = IP::TYPE_ANY; + } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index cf9a1e4a932..3cbd8c58cf2 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -38,15 +38,12 @@ class TCP_Server : public Reference { GDCLASS( TCP_Server, Reference ); protected: - IP::Type ip_type; - static TCP_Server* (*_create)(); //bind helper static void _bind_methods(); public: - virtual void set_ip_type(IP::Type p_type); virtual Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*"))=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 15c3b7dfe9d..fdd1164fbe9 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -129,7 +129,7 @@ Error PacketPeerUDPPosix::listen(int p_port, IP_Address p_bind_address, int p_re ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER); - sock_type = ip_type; + sock_type = IP::TYPE_ANY; if(p_bind_address.is_valid()) sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; @@ -271,7 +271,6 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { queue_count=0; peer_port=0; sock_type = IP::TYPE_NONE; - ip_type = IP::TYPE_ANY; } PacketPeerUDPPosix::~PacketPeerUDPPosix() { diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 96258e63f65..3e514db245b 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -122,10 +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, IP::Type p_ip_type) { +void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) { - ip_type = p_ip_type; - sock_type = p_ip_type; + sock_type = p_sock_type; sockfd = p_sockfd; #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -398,7 +397,6 @@ StreamPeerTCPPosix::StreamPeerTCPPosix() { sockfd = -1; status = STATUS_NONE; peer_port = 0; - 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 d33883b159e..0eaa7dff3e8 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.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::Type p_ip_type); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_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 5f3c46451ae..24de7a68b11 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -74,7 +74,7 @@ Error TCPServerPosix::listen(uint16_t p_port,const IP_Address p_bind_address) { ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); int sockfd; - sock_type = ip_type; + sock_type = IP::TYPE_ANY; // If the bind address is valid use its type as the socket type if (p_bind_address.is_valid()) @@ -184,7 +184,6 @@ void TCPServerPosix::stop() { TCPServerPosix::TCPServerPosix() { listen_sockfd = -1; - ip_type = IP::TYPE_ANY; sock_type = IP::TYPE_NONE; }; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 9759f15195e..ddcfa9cdf86 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -124,7 +124,7 @@ Error PacketPeerUDPWinsock::listen(int p_port, IP_Address p_bind_address, int p_ ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER); - sock_type = ip_type; + sock_type = IP::TYPE_ANY; if(p_bind_address.is_valid()) sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; @@ -289,7 +289,6 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { packet_port=0; queue_count=0; peer_port=0; - ip_type = IP::TYPE_ANY; sock_type = IP::TYPE_NONE; } diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index 6edd9c62fea..69a6fc177a8 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -287,11 +287,10 @@ void StreamPeerWinsock::disconnect_from_host() { peer_port = 0; }; -void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) { +void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) { - ip_type = p_ip_type; sockfd = p_sockfd; - sock_type = p_ip_type; + sock_type = p_sock_type; status = STATUS_CONNECTING; peer_host = p_host; peer_port = p_port; @@ -369,7 +368,6 @@ StreamPeerWinsock::StreamPeerWinsock() { sockfd = INVALID_SOCKET; status = STATUS_NONE; peer_port = 0; - ip_type = IP::TYPE_ANY; }; StreamPeerWinsock::~StreamPeerWinsock() { diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index 59e4dc0d09d..780f45f47c1 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.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::Type p_ip_type); + void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_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 c29645cef7f..883741b1157 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -69,7 +69,7 @@ Error TCPServerWinsock::listen(uint16_t p_port,const IP_Address p_bind_address) ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); int sockfd; - sock_type = ip_type; + sock_type = IP::TYPE_ANY; // If the bind address is valid use its type as the socket type if (p_bind_address.is_valid()) @@ -179,7 +179,6 @@ void TCPServerWinsock::stop() { TCPServerWinsock::TCPServerWinsock() { listen_sockfd = INVALID_SOCKET; - ip_type = IP::TYPE_ANY; sock_type = IP::TYPE_NONE; }; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 63a81a139df..436bf3e9721 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -28,10 +28,6 @@ /*************************************************************************/ #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) { @@ -539,7 +535,6 @@ int HTTPRequest::get_body_size() const{ void HTTPRequest::_bind_methods() { - ClassDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPRequest::set_ip_type); ClassDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(PoolStringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String())); ClassDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 51c5ddeb69c..a9c495fd816 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -116,7 +116,6 @@ protected: static void _bind_methods(); public: - 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 619e7a2c8ba19d0dc45467e29d9d9aa8b3506ac8 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 17:17:44 +0100 Subject: [PATCH 07/12] Bind to IPv4 on OpenBSD when using wildcard OpenBSD does not support binding on both IPv4 and IPv6 using the same socket --- drivers/unix/packet_peer_udp_posix.cpp | 4 ++++ drivers/unix/tcp_server_posix.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index fdd1164fbe9..88293fc5136 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -129,7 +129,11 @@ Error PacketPeerUDPPosix::listen(int p_port, IP_Address p_bind_address, int p_re ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER); +#ifdef __OpenBSD__ + sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only. +#else sock_type = IP::TYPE_ANY; +#endif if(p_bind_address.is_valid()) sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 24de7a68b11..7e9970453f1 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -74,7 +74,11 @@ Error TCPServerPosix::listen(uint16_t p_port,const IP_Address p_bind_address) { ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); int sockfd; +#ifdef __OpenBSD__ + sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only. +#else sock_type = IP::TYPE_ANY; +#endif // If the bind address is valid use its type as the socket type if (p_bind_address.is_valid()) From e5e4e7b6a9be36bb9bf75da996c348ae2476010c Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 20:14:51 +0100 Subject: [PATCH 08/12] Update docs reference for TCP_Server::listen and UDPPacketPeer::listen --- doc/base/classes.xml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 0b8c5cc11ce..f9a10b13d80 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -25394,10 +25394,15 @@ - + + + - Make this [PacketPeerUDP] listen on the "port" with a buffer size "recv_buf_size". Listens on all available addresses. + Make this [PacketPeerUDP] listen on the "port" binding to "bind_address" with a buffer size "recv_buf_size". + If "bind_address" is set as "*" (default), the peer will listen on all available addresses (both IPv4 and IPv6). + If "bind_address" is set as "0.0.0.0" (for IPv4) or "::" (for IPv6), the peer will listen on all available addresses matching that IP type. + If "bind_address" is set to any valid address (e.g. "192.168.1.101", "::1", etc), the peer will only listen on the interface with that addresses (or fail if no interface with the given address exists). @@ -40576,10 +40581,13 @@ - + - Listen on a port using protocol, alternatively give a white-list of accepted hosts. + Listen on the "port" binding to "bind_address". + If "bind_address" is set as "*" (default), the server will listen on all available addresses (both IPv4 and IPv6). + If "bind_address" is set as "0.0.0.0" (for IPv4) or "::" (for IPv6), the server will listen on all available addresses matching that IP type. + If "bind_address" is set to any valid address (e.g. "192.168.1.101", "::1", etc), the server will only listen on the interface with that addresses (or fail if no interface with the given address exists). From fa0cb7da0e096e01476eabef37c225404c7f6f26 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 19:04:37 +0100 Subject: [PATCH 09/12] Avoid deadlock when writing/reading data on a connecting TCP socket TCP status polling is always performed as non blocking. Trying to put a packet on a connecting socket will fail immediately. --- drivers/unix/stream_peer_tcp_posix.cpp | 13 ++++--------- drivers/unix/stream_peer_tcp_posix.h | 2 +- platform/windows/stream_peer_winsock.cpp | 13 ++++--------- platform/windows/stream_peer_winsock.h | 2 +- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 3e514db245b..08a29546173 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -88,15 +88,10 @@ Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const return ret < 0 ? FAILED : OK; }; -Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { +Error StreamPeerTCPPosix::_poll_connection() const { ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED); - if (p_block) { - - _block(sockfd, false, true); - }; - struct sockaddr_storage their_addr; size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); @@ -191,7 +186,7 @@ Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent, if (status != STATUS_CONNECTED) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -251,7 +246,7 @@ Error StreamPeerTCPPosix::read(uint8_t* p_buffer, int p_bytes,int &r_received, b if (status == STATUS_CONNECTING) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -330,7 +325,7 @@ bool StreamPeerTCPPosix::is_connected_to_host() const { StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const { if (status == STATUS_CONNECTING) { - _poll_connection(false); + _poll_connection(); }; return status; diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index 0eaa7dff3e8..7f8d90a4482 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -46,7 +46,7 @@ protected: Error _block(int p_sockfd, bool p_read, bool p_write) const; - Error _poll_connection(bool p_block) const; + Error _poll_connection() const; IP_Address peer_host; int peer_port; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index 69a6fc177a8..106eb6a5f56 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -78,15 +78,10 @@ Error StreamPeerWinsock::_block(int p_sockfd, bool p_read, bool p_write) const { return ret < 0 ? FAILED : OK; }; -Error StreamPeerWinsock::_poll_connection(bool p_block) const { +Error StreamPeerWinsock::_poll_connection() const { ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED); - if (p_block) { - - _block(sockfd, false, true); - }; - struct sockaddr_storage their_addr; size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); @@ -122,7 +117,7 @@ Error StreamPeerWinsock::write(const uint8_t* p_data,int p_bytes, int &r_sent, b if (status != STATUS_CONNECTED) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -180,7 +175,7 @@ Error StreamPeerWinsock::read(uint8_t* p_buffer, int p_bytes,int &r_received, bo if (status != STATUS_CONNECTED) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -254,7 +249,7 @@ Error StreamPeerWinsock::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_ StreamPeerTCP::Status StreamPeerWinsock::get_status() const { if (status == STATUS_CONNECTING) { - _poll_connection(false); + _poll_connection(); }; return status; diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index 780f45f47c1..7cf60fc10ed 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -47,7 +47,7 @@ protected: Error _block(int p_sockfd, bool p_read, bool p_write) const; - Error _poll_connection(bool p_block) const; + Error _poll_connection() const; IP_Address peer_host; int peer_port; From 68dc969f8ca242d0c4f927a417557288e4b1b75f Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 21:33:55 +0100 Subject: [PATCH 10/12] Fix bug causing UDP socket to close after the first send if not listening The ring buffer for receiving packets was not resized in constructor --- drivers/unix/packet_peer_udp_posix.cpp | 1 + platform/windows/packet_peer_udp_winsock.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 88293fc5136..7de54df043a 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -275,6 +275,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { queue_count=0; peer_port=0; sock_type = IP::TYPE_NONE; + rb.resize(8); } PacketPeerUDPPosix::~PacketPeerUDPPosix() { diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index ddcfa9cdf86..9f1617d5400 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -290,6 +290,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { queue_count=0; peer_port=0; sock_type = IP::TYPE_NONE; + rb.resize(8); } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { From 93368571326e3472522669b76998f58aed78864f Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Jan 2017 13:33:10 +0100 Subject: [PATCH 11/12] Use default UDP ring buffer size of 65536 for clients We should probably create a specific function for setting the recv buffer anyway. UDP sockets does not need to bind (listen) to be able to call recvfrom. This is especially useful for clients who just call set_send_address and start communicating with a server. --- drivers/unix/packet_peer_udp_posix.cpp | 4 ++-- platform/windows/packet_peer_udp_winsock.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index 7de54df043a..a146a4a09ff 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -160,7 +160,7 @@ void PacketPeerUDPPosix::close(){ ::close(sockfd); sockfd=-1; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); queue_count=0; } @@ -275,7 +275,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() { queue_count=0; peer_port=0; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); } PacketPeerUDPPosix::~PacketPeerUDPPosix() { diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 9f1617d5400..e5eb062165b 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -154,7 +154,7 @@ void PacketPeerUDPWinsock::close(){ ::closesocket(sockfd); sockfd=-1; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); queue_count=0; } @@ -290,7 +290,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { queue_count=0; peer_port=0; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { From 5dc7c920bf1c4bb160d39e13ad6136d80badd7ae Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Jan 2017 17:00:01 +0100 Subject: [PATCH 12/12] Fix buffer size check in UDP socket. We were reserving 12 bytes from the buffer for ip, port, and length, but since IPv6 introduction we should be reserving 24 (IPv6 are 16 bytes) --- drivers/unix/packet_peer_udp_posix.cpp | 2 +- platform/windows/packet_peer_udp_winsock.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index a146a4a09ff..7696a5fcb50 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -179,7 +179,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { struct sockaddr_storage from = {0}; socklen_t len = sizeof(struct sockaddr_storage); int ret; - while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { + while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-24, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { uint32_t port = 0; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index e5eb062165b..276b9b66343 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -175,7 +175,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { struct sockaddr_storage from = {0}; int len = sizeof(struct sockaddr_storage); int ret; - while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), 0, (struct sockaddr*)&from, &len)) > 0) { + while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-24, 0)), 0, (struct sockaddr*)&from, &len)) > 0) { uint32_t port = 0;