From ccf37c4ca2aabb212ef82bee7162401280f59e4d Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 20 Dec 2016 15:13:16 +0100 Subject: [PATCH 01/13] TCP connect always opens correct socket type TCP client connections does not need to rely on ipv6 dual stack sockets (cherry picked from commit 55b4f3686d8f51958132a1a1745cc4e128fd118d) --- drivers/unix/stream_peer_tcp_posix.cpp | 11 ++++++++--- drivers/unix/stream_peer_tcp_posix.h | 3 +-- platform/windows/stream_peer_winsock.cpp | 10 +++++++--- platform/windows/stream_peer_winsock.h | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 58c78b638d2..7ebcc34c00b 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, ip_type); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1) { @@ -125,6 +125,7 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) { ip_type = p_ip_type; + sock_type = p_ip_type; sockfd = p_sockfd; #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -143,7 +144,8 @@ Error StreamPeerTCPPosix::connect(const IP_Address &p_host, uint16_t p_port) { ERR_FAIL_COND_V(p_host == IP_Address(), ERR_INVALID_PARAMETER); - sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); + sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == -1) { ERR_PRINT("Socket creation failed!"); disconnect(); @@ -159,7 +161,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, ip_type); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type); errno = 0; if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == -1 && errno != EINPROGRESS) { @@ -339,6 +341,8 @@ void StreamPeerTCPPosix::disconnect() { if (sockfd != -1) close(sockfd); + + sock_type = IP::TYPE_NONE; sockfd = -1; status = STATUS_NONE; @@ -387,6 +391,7 @@ uint16_t StreamPeerTCPPosix::get_connected_port() const { StreamPeerTCPPosix::StreamPeerTCPPosix() { + sock_type = IP::TYPE_NONE; sockfd = -1; status = STATUS_NONE; peer_port = 0; diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h index f071d3919a9..c0ce62a7da0 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -35,13 +35,12 @@ #include "core/io/stream_peer_tcp.h" #include "error_list.h" -#include "core/io/ip_address.h" - class StreamPeerTCPPosix : public StreamPeerTCP { protected: mutable Status status; + IP::Type sock_type; int sockfd; Error _block(int p_sockfd, bool p_read, bool p_write) const; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index c16fa73bd5d..99ee5ef4748 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -87,7 +87,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, ip_type); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type); if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) { @@ -277,6 +277,7 @@ void StreamPeerWinsock::disconnect() { if (sockfd != INVALID_SOCKET) closesocket(sockfd); sockfd = INVALID_SOCKET; + sock_type = IP::TYPE_NONE; status = STATUS_NONE; @@ -288,6 +289,7 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, ip_type = p_ip_type; sockfd = p_sockfd; + sock_type = p_ip_type; status = STATUS_CONNECTING; peer_host = p_host; peer_port = p_port; @@ -297,7 +299,8 @@ Error StreamPeerWinsock::connect(const IP_Address &p_host, uint16_t p_port) { ERR_FAIL_COND_V(p_host == IP_Address(), ERR_INVALID_PARAMETER); - sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP); + sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP); if (sockfd == INVALID_SOCKET) { ERR_PRINT("Socket creation failed!"); disconnect(); @@ -313,7 +316,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, ip_type); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, sock_type); if (::connect(sockfd, (struct sockaddr *)&their_addr, addr_size) == SOCKET_ERROR) { @@ -359,6 +362,7 @@ uint16_t StreamPeerWinsock::get_connected_port() const { StreamPeerWinsock::StreamPeerWinsock() { + sock_type = IP::TYPE_NONE; sockfd = INVALID_SOCKET; status = STATUS_NONE; peer_port = 0; diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h index de5faf981e0..7bea3c56490 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -40,6 +40,7 @@ class StreamPeerWinsock : public StreamPeerTCP { protected: mutable Status status; + IP::Type sock_type; int sockfd; From aeffe74a27fbe83f9f3da2672e2b62efe1255bf0 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 10:48:50 +0100 Subject: [PATCH 02/13] Avoid calling close when polling a UDP peer without socket (cherry picked from commit e4b9b37ccf8495be674bc15cf0bf9d76fe94e6be) --- drivers/unix/packet_peer_udp_posix.cpp | 4 ++++ platform/windows/packet_peer_udp_winsock.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 04be55d6c6a..faabe902f9c 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -154,6 +154,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 d8707709f52..1dc23fcab95 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -149,6 +149,10 @@ Error PacketPeerUDPWinsock::wait() { } Error PacketPeerUDPWinsock::_poll(bool p_wait) { + if (sockfd == -1) { + return FAILED; + } + _set_blocking(p_wait); struct sockaddr_storage from = { 0 }; From 603105df189699c62b9462839302dae7d9a090de Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 17 Jan 2017 09:22:56 +0100 Subject: [PATCH 03/13] Convert validity checks of IP_Address to is_valid method. (cherry picked from commit 98a7e2b4e09791705cd9dfd4d13611bc02fe47d4) --- core/io/ip.cpp | 2 +- core/io/ip_address.cpp | 20 ++++++++++++++++---- 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, 30 insertions(+), 11 deletions(-) diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 963e8a612ee..0d92961591e 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -81,7 +81,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 e03dac8d342..594edbf8e27 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]); @@ -170,6 +173,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 { @@ -183,6 +187,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); } @@ -193,6 +198,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,13 +207,18 @@ IP_Address::IP_Address(const String &p_string) { clear(); 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) { @@ -221,6 +232,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 200df57aafb..2ed77cc3b40 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -40,6 +40,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); @@ -47,12 +49,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; @@ -60,6 +66,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 eb51a4207cd..8e5e46fd9cb 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -43,7 +43,7 @@ Error PacketPeerUDP::_set_send_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 753d66734b1..f303d8fd181 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 faabe902f9c..13fef59218c 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -94,7 +94,7 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer, int &r_buffer_siz } 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 c7828ae94fa..80f02f623cd 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 7ebcc34c00b..779d9e427e2 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(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 99ee5ef4748..6723a6d0f8a 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -297,7 +297,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 == 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 90a747a52dac1214a1ff1c6b7c65228bf41a6e1f Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 04:03:51 +0100 Subject: [PATCH 04/13] IP_Address can now be a wildcard (not a valid IP, used for binding) (cherry picked from commit 4198291cd45da7fce278d21cd5ef4a506086d5f8) --- core/io/ip_address.cpp | 9 ++++++++- core/io/ip_address.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 594edbf8e27..fa0eab4f0d3 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -174,6 +174,7 @@ void IP_Address::clear() { memset(&field8[0], 0, sizeof(field8)); valid = false; + wildcard = false; }; bool IP_Address::is_ipv4() const { @@ -206,10 +207,16 @@ 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 == "*") { + // Wildcard (not a vaild IP) + wildcard = true; + + } else if (p_string.find(":") >= 0) { // IPv6 _parse_ipv6(p_string); valid = true; + } else if (p_string.get_slice_count(".") == 4) { // IPv4 (mapped to IPv6 internally) field16[5] = 0xffff; diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 2ed77cc3b40..52d6974d5eb 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -41,6 +41,7 @@ private: }; bool valid; + bool wildcard; protected: void _parse_ipv6(const String &p_string); @@ -66,6 +67,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 43d992fc3413af7a0fea54eeded8609e4ebd0f16 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 08:37:24 +0100 Subject: [PATCH 05/13] Implement TCP Server bind address (cherry picked from commit b2839343cab66880f647c77da7b2e1826761776a) --- core/io/tcp_server.cpp | 11 +--------- 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 | 19 ++++++++++++++---- platform/windows/tcp_server_winsock.h | 3 ++- 9 files changed, 49 insertions(+), 29 deletions(-) diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 2b4206ba388..393dd363aad 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -44,15 +44,6 @@ TCP_Server *TCP_Server::create() { return _create(); } -Error TCP_Server::_listen(uint16_t p_port, DVector p_accepted_hosts) { - - List hosts; - for (int i = 0; i < p_accepted_hosts.size(); i++) - hosts.push_back(p_accepted_hosts.get(i)); - - return listen(p_port, hosts.size() ? &hosts : NULL); -} - void TCP_Server::set_ip_type(IP::Type p_type) { stop(); ip_type = p_type; @@ -61,7 +52,7 @@ void TCP_Server::set_ip_type(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("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); 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); diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index 481945b6db9..671b033083d 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, DVector p_accepted_hosts = DVector()); 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 13fef59218c..c5daba4d27b 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -128,7 +128,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 80f02f623cd..b3b0d4e5315 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 cdd451062d8..79ebf18730e 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_hos } 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) { @@ -156,7 +163,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; }; @@ -169,12 +176,14 @@ void TCPServerPosix::stop() { }; listen_sockfd = -1; + sock_type = IP::TYPE_NONE; }; 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 aa02b4c46e4..408179c197d 100644 --- a/drivers/unix/tcp_server_posix.h +++ b/drivers/unix/tcp_server_posix.h @@ -35,11 +35,12 @@ 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 1dc23fcab95..92cc720f437 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -120,7 +120,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 b65eee30a0e..0f117bc6b2a 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -62,10 +62,19 @@ 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; @@ -76,7 +85,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, const List *p_accepted_h }; 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) { @@ -146,7 +155,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; }; @@ -158,12 +167,14 @@ void TCPServerWinsock::stop() { }; listen_sockfd = -1; + sock_type = IP::TYPE_NONE; }; 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 22a504a41b2..d7b1aee054f 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -34,11 +34,12 @@ 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 0b9684a085f244210f166070a9589bdd70876196 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 10:24:26 +0100 Subject: [PATCH 06/13] Implement UDP listen bind address (cherry picked from commit 2fe4ef66991b483640f59873c22b3af671626ccc) --- 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 8e5e46fd9cb..0c008b6dcf7 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() { 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("listen:Error", "port", "bind_address", "recv_buf_size"), &PacketPeerUDP::listen, DEFVAL("*"), 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); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index e17f9b505e7..e20863045f4 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -43,11 +43,11 @@ protected: String _get_packet_ip() const; - virtual Error _set_send_address(const String &p_address, int p_port); + Error _set_send_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 c5daba4d27b..ea900062f6f 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -96,10 +96,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; @@ -119,16 +122,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(); @@ -143,6 +153,7 @@ void PacketPeerUDPPosix::close() { if (sockfd != -1) ::close(sockfd); sockfd = -1; + sock_type = IP::TYPE_NONE; rb.resize(8); queue_count = 0; } @@ -221,10 +232,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; } @@ -251,6 +264,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 ee0cd2dbdee..027ec3be705 100644 --- a/drivers/unix/packet_peer_udp_posix.h +++ b/drivers/unix/packet_peer_udp_posix.h @@ -47,6 +47,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; @@ -63,7 +64,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 92cc720f437..4ee94c264d8 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -72,10 +72,15 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer, int &r_buffer_s } 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); @@ -112,15 +117,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(); @@ -139,6 +151,7 @@ void PacketPeerUDPWinsock::close() { if (sockfd != -1) ::closesocket(sockfd); sockfd = -1; + sock_type = IP::TYPE_NONE; rb.resize(8); queue_count = 0; } @@ -232,10 +245,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; } @@ -263,6 +278,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 d24bb839772..47e926600a3 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -45,6 +45,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; @@ -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; From d9525082feb6165944082fb80ae7785b23a2250c Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 12:47:12 +0100 Subject: [PATCH 07/13] 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) (cherry picked from commit 88a56ba783d36d52a1023759e69f026b1ae255b4) --- core/io/http_client.cpp | 9 +-------- core/io/http_client.h | 2 -- core/io/packet_peer_udp.cpp | 9 +-------- core/io/packet_peer_udp.h | 3 --- core/io/stream_peer_tcp.cpp | 10 +--------- core/io/stream_peer_tcp.h | 1 - core/io/tcp_server.cpp | 7 ------- 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, 13 insertions(+), 65 deletions(-) diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index adc95e96210..dc541a5133a 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(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; @@ -63,7 +58,7 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl, bool p_v 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; } @@ -618,7 +613,6 @@ Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received void HTTPClient::_bind_methods() { - 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); @@ -742,7 +736,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 43d6dc721e7..ac2bd74174a 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -130,7 +130,6 @@ public: }; private: - IP::Type ip_type; Status status; IP::ResolverID resolving; int conn_port; @@ -161,7 +160,6 @@ private: Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received); 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(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 0c008b6dcf7..067c1c1bd75 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -42,7 +42,7 @@ Error PacketPeerUDP::_set_send_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_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", "bind_address", "recv_buf_size"), &PacketPeerUDP::listen, DEFVAL("*"), DEFVAL(65536)); ObjectTypeDB::bind_method(_MD("close"), &PacketPeerUDP::close); ObjectTypeDB::bind_method(_MD("wait:Error"), &PacketPeerUDP::wait); @@ -84,5 +78,4 @@ 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 e20863045f4..8fcbc9472f6 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -36,8 +36,6 @@ class PacketPeerUDP : public PacketPeer { OBJ_TYPE(PacketPeerUDP, PacketPeer); protected: - IP::Type ip_type; - static PacketPeerUDP *(*_create)(); static void _bind_methods(); @@ -46,7 +44,6 @@ protected: Error _set_send_address(const String &p_address, int p_port); 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 f303d8fd181..032f58a4c6c 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(); - 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); @@ -81,8 +75,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 a97f4293771..36ed9d1d783 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -56,7 +56,6 @@ protected: static void _bind_methods(); 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 393dd363aad..4514a028954 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() { - ObjectTypeDB::bind_method(_MD("set_ip_type", "ip_type"), &TCP_Server::set_ip_type); ObjectTypeDB::bind_method(_MD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); ObjectTypeDB::bind_method(_MD("is_connection_available"), &TCP_Server::is_connection_available); ObjectTypeDB::bind_method(_MD("take_connection"), &TCP_Server::take_connection); @@ -59,5 +53,4 @@ 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 671b033083d..13cc590ed12 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -38,15 +38,12 @@ class TCP_Server : public Reference { OBJ_TYPE(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 ea900062f6f..bfbbf6cce79 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -127,7 +127,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; @@ -265,7 +265,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 779d9e427e2..9f551a8f440 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); @@ -395,7 +394,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 c0ce62a7da0..cd50d4167a2 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -66,7 +66,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 79ebf18730e..6aec5ad31d6 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()) @@ -182,7 +182,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 4ee94c264d8..e326a5a6fb5 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, 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; @@ -277,7 +277,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 6723a6d0f8a..de79941e23d 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -285,11 +285,10 @@ void StreamPeerWinsock::disconnect() { 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; @@ -366,7 +365,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 7bea3c56490..db27001c622 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.h @@ -67,7 +67,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 0f117bc6b2a..67713f5d1c2 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -68,7 +68,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()) @@ -173,7 +173,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 d977548d6fa..97832521c7a 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) { } @@ -519,7 +515,6 @@ 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 6a63fa66af4..e7da0e1e35c 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -113,7 +113,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 86de0bd081669c40578b408e2f38fea76b0416ce Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 17:17:44 +0100 Subject: [PATCH 08/13] Bind to IPv4 on OpenBSD when using wildcard OpenBSD does not support binding on both IPv4 and IPv6 using the same socket (cherry picked from commit 619e7a2c8ba19d0dc45467e29d9d9aa8b3506ac8) --- 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 bfbbf6cce79..4040aaaf4b1 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -127,7 +127,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 6aec5ad31d6..9049faebb86 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 9f41c0a356c016a86418a44c35ad1fb3f5978fd2 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 19:04:37 +0100 Subject: [PATCH 09/13] 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. (cherry picked from commit fa0cb7da0e096e01476eabef37c225404c7f6f26) --- 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 9f551a8f440..4063eb3a38f 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, if (status == STATUS_CONNECTING) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -330,7 +325,7 @@ bool StreamPeerTCPPosix::is_connected() 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 cd50d4167a2..3a53e5b2647 100644 --- a/drivers/unix/stream_peer_tcp_posix.h +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -45,7 +45,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 de79941e23d..7bf43e52f22 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -77,15 +77,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); @@ -121,7 +116,7 @@ Error StreamPeerWinsock::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; }; @@ -179,7 +174,7 @@ Error StreamPeerWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received, b if (status != STATUS_CONNECTED) { - if (_poll_connection(p_block) != OK) { + if (_poll_connection() != OK) { return FAILED; }; @@ -253,7 +248,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 db27001c622..04a820e7f86 100644 --- a/platform/windows/stream_peer_winsock.h +++ b/platform/windows/stream_peer_winsock.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; From cab9ad76570760f170ae15026b57b2dcfe6431ff Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 20:14:51 +0100 Subject: [PATCH 10/13] Update docs reference for TCP_Server::listen and UDPPacketPeer::listen (cherry picked from commit e5e4e7b6a9be36bb9bf75da996c348ae2476010c) --- 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 b2724811a27..aad217b8eb1 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -24710,10 +24710,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). @@ -39827,10 +39832,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 7dbccc9a57c7579be7f3edcf99b35cf4804b4723 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 18 Jan 2017 21:33:55 +0100 Subject: [PATCH 11/13] 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 (cherry picked from commit 68dc969f8ca242d0c4f927a417557288e4b1b75f) --- 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 4040aaaf4b1..4e48e835099 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -269,6 +269,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 e326a5a6fb5..5290eebc4a7 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -278,6 +278,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { queue_count = 0; peer_port = 0; sock_type = IP::TYPE_NONE; + rb.resize(8); } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { From 994df5df5c1a0062582d39f944ac1857a4881c00 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Jan 2017 13:33:10 +0100 Subject: [PATCH 12/13] 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. (cherry picked from commit 93368571326e3472522669b76998f58aed78864f) --- 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 4e48e835099..f7ca6f83404 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -158,7 +158,7 @@ void PacketPeerUDPPosix::close() { ::close(sockfd); sockfd = -1; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); queue_count = 0; } @@ -269,7 +269,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 5290eebc4a7..00c317183a5 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -152,7 +152,7 @@ void PacketPeerUDPWinsock::close() { ::closesocket(sockfd); sockfd = -1; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); queue_count = 0; } @@ -278,7 +278,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() { queue_count = 0; peer_port = 0; sock_type = IP::TYPE_NONE; - rb.resize(8); + rb.resize(16); } PacketPeerUDPWinsock::~PacketPeerUDPWinsock() { From 15ecdb5f00da2f19974d70ddd8f2658d9f2f4903 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Jan 2017 17:00:01 +0100 Subject: [PATCH 13/13] 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) (cherry picked from commit 5dc7c920bf1c4bb160d39e13ad6136d80badd7ae) --- 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 f7ca6f83404..6dc762f04cf 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -176,7 +176,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 00c317183a5..38c9d322e2c 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -171,7 +171,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;