From 887a897c02144f2d01896d3112bdae5ce7d6df5c Mon Sep 17 00:00:00 2001 From: Ariel Manzur Date: Tue, 18 Oct 2016 18:53:18 -0300 Subject: adding ipv6 --- drivers/unix/tcp_server_posix.cpp | 52 +++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers/unix/tcp_server_posix.cpp') diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index c67bb5133..03312a753 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -55,6 +55,7 @@ #include #include #include + TCP_Server* TCPServerPosix::_create() { return memnew(TCPServerPosix); @@ -65,10 +66,11 @@ 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, IP_Address::AddrType p_type, const List *p_accepted_hosts) { int sockfd; - sockfd = socket(AF_INET, SOCK_STREAM, 0); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + sockfd = socket(family, SOCK_STREAM, 0); ERR_FAIL_COND_V(sockfd == -1, FAILED); #ifndef NO_FCNTL fcntl(sockfd, F_SETFL, O_NONBLOCK); @@ -82,13 +84,22 @@ Error TCPServerPosix::listen(uint16_t p_port,const List *p_accepted_host WARN_PRINT("REUSEADDR failed!") } - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + sockaddr_storage addr = {0}; + if (p_type == IP_Address::TYPE_IPV4) { + struct sockaddr_in* addr4 = (struct sockaddr_in*)&addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(p_port); + addr4->sin_addr.s_addr = INADDR_ANY; + } else { + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + addr6->sin6_addr = in6addr_any; + }; + // automatically fill with my IP TODO: use p_accepted_hosts - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) { + if (bind(sockfd, (struct sockaddr *)&addr, sizeof addr) != -1) { if (::listen(sockfd, 1) == -1) { @@ -136,9 +147,9 @@ Ref TCPServerPosix::take_connection() { return Ref(); }; - struct sockaddr_in their_addr; - socklen_t sin_size = sizeof(their_addr); - int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); + struct sockaddr_storage their_addr; + socklen_t size = sizeof(their_addr); + int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &size); ERR_FAIL_COND_V(fd == -1, Ref()); #ifndef NO_FCNTL fcntl(fd, F_SETFL, O_NONBLOCK); @@ -149,8 +160,23 @@ Ref TCPServerPosix::take_connection() { Ref conn = memnew(StreamPeerTCPPosix); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + + if (their_addr.ss_family == AF_INET) { + ip.type = IP_Address::TYPE_IPV4; + + struct sockaddr_in* addr4 = (struct sockaddr_in*)&their_addr; + ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; + conn->set_socket(fd, ip, ntohs(addr4->sin_port)); + + } else if (their_addr.ss_family == AF_INET6) { + + ip.type = IP_Address::TYPE_IPV6; + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&their_addr; + copymem(&addr6->sin6_addr.s6_addr, ip.field8, 16); + + conn->set_socket(fd, ip, ntohs(addr6->sin6_port)); + }; return conn; }; -- cgit v1.2.3-70-g09d2 From 672225b710815865449e7930255468d1c085b137 Mon Sep 17 00:00:00 2001 From: Ariel Manzur Date: Thu, 20 Oct 2016 07:04:10 -0300 Subject: added windows support for ipv6, cleaned up unix code --- core/io/ip.cpp | 15 +++++- core/io/ip.h | 2 + drivers/unix/packet_peer_udp_posix.cpp | 29 ++--------- drivers/unix/socket_helpers.h | 66 +++++++++++++++++++++++++ drivers/unix/stream_peer_tcp_posix.cpp | 24 ++------- drivers/unix/tcp_server_posix.cpp | 36 +++----------- platform/windows/packet_peer_udp_winsock.cpp | 74 ++++++++++++++++++++-------- platform/windows/packet_peer_udp_winsock.h | 8 +-- platform/windows/stream_peer_winsock.cpp | 24 ++++----- platform/windows/tcp_server_winsock.cpp | 19 +++---- platform/windows/tcp_server_winsock.h | 2 +- 11 files changed, 176 insertions(+), 123 deletions(-) create mode 100644 drivers/unix/socket_helpers.h (limited to 'drivers/unix/tcp_server_posix.cpp') diff --git a/core/io/ip.cpp b/core/io/ip.cpp index aba55687a..4ee1b281c 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -117,7 +117,9 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p GLOBAL_LOCK_FUNCTION; if (resolver->cache.has(p_hostname)) - return resolver->cache[p_hostname]; + if (resolver->cache[p_hostname].type & p_type != 0) + return resolver->cache[p_hostname]; + // requested type is different from type in cache. continue resolution, if successful it'll overwrite cache IP_Address res = _resolve_hostname(p_hostname, p_type); resolver->cache[p_hostname]=res; @@ -137,7 +139,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Addr resolver->queue[id].hostname=p_hostname; resolver->queue[id].type = p_type; - if (resolver->cache.has(p_hostname)) { + if (resolver->cache.has(p_hostname) && (resolver->cache[p_hostname].type & p_type) != 0) { resolver->queue[id].response=resolver->cache[p_hostname]; resolver->queue[id].status=IP::RESOLVER_STATUS_DONE; } else { @@ -187,6 +189,14 @@ void IP::erase_resolve_item(ResolverID p_id) { } +void IP::clear_cache(const String &p_hostname) { + + if (p_hostname.empty()) { + resolver->cache.clear(); + } else { + resolver->cache.erase(p_hostname); + } +}; Array IP::_get_local_addresses() const { @@ -208,6 +218,7 @@ void IP::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address); ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item); ObjectTypeDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses); + ObjectTypeDB::bind_method(_MD("clear_cache"),&IP::clear_cache, DEFVAL("")); BIND_CONSTANT( RESOLVER_STATUS_NONE ); BIND_CONSTANT( RESOLVER_STATUS_WAITING ); diff --git a/core/io/ip.h b/core/io/ip.h index 9ffe01b1a..742dd0e74 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -89,6 +89,8 @@ public: virtual void get_local_addresses(List *r_addresses) const=0; void erase_resolve_item(ResolverID p_id); + void clear_cache(const String& p_hostname = ""); + static IP* get_singleton(); static IP* create(); diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index cab2b2bbb..cdc3bfce2 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -54,6 +54,7 @@ #include #endif +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPPosix::get_available_packet_count() const { @@ -98,17 +99,7 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; - if (peer_addr.type == IP_Address::TYPE_IPV4) { - struct sockaddr_in* addr_in = (struct sockaddr_in*)&addr; - addr_in->sin_family = AF_INET; - addr_in->sin_port = htons(peer_port); - addr_in->sin_addr = *((struct in_addr*)&peer_addr.field32[0]); - } else { - struct sockaddr_in6* addr_in6 = (struct sockaddr_in6*)&addr; - addr_in6->sin6_family = AF_INET; - addr_in6->sin6_port = htons(peer_port); - copymem(&addr_in6->sin6_addr.s6_addr, peer_addr.field8, 16); - }; + _set_sockaddr(&addr, peer_addr, peer_port); errno = 0; int err; @@ -138,20 +129,7 @@ Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_address_type return ERR_CANT_CREATE; sockaddr_storage addr = {0}; - - if (p_address_type == IP_Address::TYPE_IPV4) { - struct sockaddr_in* addr4 = (struct sockaddr_in*)&addr; - addr4->sin_family = AF_INET; - addr4->sin_port = htons(p_port); - addr4->sin_addr.s_addr = INADDR_ANY; - } else { - - struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&addr; - - addr6->sin6_family = AF_INET6; - addr6->sin6_port = htons(p_port); - addr6->sin6_addr = in6addr_any; - }; + _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_storage)) == -1 ) { close(); @@ -212,6 +190,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) { rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); + len = sizeof(struct sockaddr_storage); ++queue_count; }; diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h new file mode 100644 index 000000000..622b45c50 --- /dev/null +++ b/drivers/unix/socket_helpers.h @@ -0,0 +1,66 @@ +#ifndef SOCKET_HELPERS_H +#define SOCKET_HELPERS_H + +#include + +// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this + +static void _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_ip.type == IP_Address::TYPE_IPV6) { + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(p_port); + copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + + } else { + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + addr4->sin_family = AF_INET; // host byte order + addr4->sin_port = htons(p_port); // short, network byte order + addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]); + }; +}; + +static void _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List *p_accepted_hosts) { + + memset(p_addr, 0, sizeof(struct sockaddr_storage)); + if (p_address_type == IP_Address::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 + } 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 + }; +}; + +static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_storage* p_addr) { + + if (p_addr->ss_family == AF_INET) { + r_ip.type = IP_Address::TYPE_IPV4; + + struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr; + r_ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; + + r_port = ntohs(addr4->sin_port); + + } else if (p_addr->ss_family == AF_INET6) { + + r_ip.type = IP_Address::TYPE_IPV6; + + struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr; + copymem(&addr6->sin6_addr.s6_addr, r_ip.field8, 16); + + r_port = ntohs(addr6->sin6_port); + }; +}; + + +#endif diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index bb672cef3..5a63a512e 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -61,24 +61,7 @@ #define MSG_NOSIGNAL SO_NOSIGPIPE #endif -static void set_addr_in(struct sockaddr_storage& their_addr, const IP_Address& p_host, uint16_t p_port) { - - memset(&their_addr, 0, sizeof(struct sockaddr_storage)); - if (p_host.type == IP_Address::TYPE_IPV6) { - - struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&their_addr; - addr6->sin6_family = AF_INET6; - addr6->sin6_port = htons(p_port); - copymem(&addr6->sin6_addr.s6_addr, p_host.field8, 16); - - } else { - - struct sockaddr_in* addr4 = (struct sockaddr_in*)&their_addr; - addr4->sin_family = AF_INET; // host byte order - addr4->sin_port = htons(p_port); // short, network byte order - addr4->sin_addr = *((struct in_addr*)&p_host.field32[0]); - }; -}; +#include "drivers/unix/socket_helpers.h" StreamPeerTCP* StreamPeerTCPPosix::_create() { @@ -115,7 +98,8 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { }; struct sockaddr_storage their_addr; - set_addr_in(their_addr, peer_host, peer_port); + _set_sockaddr(&their_addr, peer_host, peer_port); + if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(their_addr)) == -1) { if (errno == EISCONN) { @@ -169,7 +153,7 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { #endif struct sockaddr_storage their_addr; - set_addr_in(their_addr, p_host, p_port); + _set_sockaddr(&their_addr, p_host, p_port); errno = 0; if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(their_addr)) == -1 && errno != EINPROGRESS) { diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 03312a753..27c561847 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -56,6 +56,8 @@ #include #include +#include "drivers/unix/socket_helpers.h" + TCP_Server* TCPServerPosix::_create() { return memnew(TCPServerPosix); @@ -84,19 +86,9 @@ Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const WARN_PRINT("REUSEADDR failed!") } - sockaddr_storage addr = {0}; - if (p_type == IP_Address::TYPE_IPV4) { - struct sockaddr_in* addr4 = (struct sockaddr_in*)&addr; - addr4->sin_family = AF_INET; - addr4->sin_port = htons(p_port); - addr4->sin_addr.s_addr = INADDR_ANY; - } else { - - struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&addr; - addr6->sin6_family = AF_INET6; - addr6->sin6_port = htons(p_port); - addr6->sin6_addr = in6addr_any; - }; + struct sockaddr_storage addr; + _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); + // automatically fill with my IP TODO: use p_accepted_hosts if (bind(sockfd, (struct sockaddr *)&addr, sizeof addr) != -1) { @@ -161,22 +153,10 @@ Ref TCPServerPosix::take_connection() { Ref conn = memnew(StreamPeerTCPPosix); IP_Address ip; - if (their_addr.ss_family == AF_INET) { - ip.type = IP_Address::TYPE_IPV4; - - struct sockaddr_in* addr4 = (struct sockaddr_in*)&their_addr; - ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr; - conn->set_socket(fd, ip, ntohs(addr4->sin_port)); + int port; + _set_ip_addr_port(ip, port, &their_addr); - } else if (their_addr.ss_family == AF_INET6) { - - ip.type = IP_Address::TYPE_IPV6; - - struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&their_addr; - copymem(&addr6->sin6_addr.s6_addr, ip.field8, 16); - - conn->set_socket(fd, ip, ntohs(addr6->sin6_port)); - }; + conn->set_socket(fd, ip, port); return conn; }; diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index 2c79365c0..cd4e85fd8 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -29,6 +29,9 @@ #include "packet_peer_udp_winsock.h" #include +#include + +#include "drivers/unix/socket_helpers.h" int PacketPeerUDPWinsock::get_available_packet_count() const { @@ -48,7 +51,15 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si return ERR_UNAVAILABLE; uint32_t size; - rb.read((uint8_t*)&packet_ip.host,4,true); + uint8_t type; + rb.read(&type, 1, true); + if (type == IP_Address::TYPE_IPV4) { + rb.read((uint8_t*)&packet_ip.field8,4,true); + packet_ip.type = IP_Address::TYPE_IPV4; + } else { + rb.read((uint8_t*)&packet_ip.field8,16,true); + packet_ip.type = IP_Address::TYPE_IPV6; + }; rb.read((uint8_t*)&packet_port,4,true); rb.read((uint8_t*)&size,4,true); rb.read(packet_buffer,size,true); @@ -60,13 +71,10 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si } Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){ - int sock = _get_socket(); + int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(peer_port); - addr.sin_addr = *((struct in_addr*)&peer_addr.host); - + struct sockaddr_storage addr; + _set_sockaddr(&addr, peer_addr, peer_port); _set_blocking(true); @@ -104,16 +112,16 @@ 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::AddrType p_address_type, int p_recv_buffer_size) { close(); - int sock = _get_socket(); + int sock = _get_socket(p_address_type); if (sock == -1 ) return ERR_CANT_CREATE; - sockaddr_in addr = {0}; - addr.sin_family = AF_INET; - addr.sin_port = htons(p_port); - addr.sin_addr.s_addr = INADDR_ANY; + + struct sockaddr_storage addr = {0}; + _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { close(); return ERR_UNAVAILABLE; @@ -146,17 +154,41 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) { _set_blocking(p_wait); - struct sockaddr_in from = {0}; - int len = sizeof(struct sockaddr_in); + 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) { - rb.write((uint8_t*)&from.sin_addr, 4); - uint32_t port = ntohs(from.sin_port); + + uint32_t port = 0; + + if (from.ss_family == AF_INET) { + uint8_t type = (uint8_t)IP_Address::TYPE_IPV4; + rb.write(&type, 1); + struct sockaddr_in* sin_from = (struct sockaddr_in*)&from; + rb.write((uint8_t*)&sin_from->sin_addr, 4); + port = sin_from->sin_port; + + } else if (from.ss_family == AF_INET6) { + + uint8_t type = (uint8_t)IP_Address::TYPE_IPV6; + rb.write(&type, 1); + + struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from; + rb.write((uint8_t*)&s6_from->sin6_addr, 16); + + port = s6_from->sin6_port; + + } else { + // WARN_PRINT("Ignoring packet with unknown address family"); + uint8_t type = (uint8_t)IP_Address::TYPE_NONE; + rb.write(&type, 1); + }; + rb.write((uint8_t*)&port, 4); rb.write((uint8_t*)&ret, 4); rb.write(recv_buffer, ret); - len = sizeof(struct sockaddr_in); + len = sizeof(struct sockaddr_storage); ++queue_count; }; @@ -202,12 +234,14 @@ int PacketPeerUDPWinsock::get_packet_port() const{ return packet_port; } -int PacketPeerUDPWinsock::_get_socket() { +int PacketPeerUDPWinsock::_get_socket(IP_Address::AddrType p_type) { if (sockfd != -1) return sockfd; - sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int family = p_type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + + sockfd = socket(family, SOCK_DGRAM, IPPROTO_UDP); ERR_FAIL_COND_V( sockfd == -1, -1 ); //fcntl(sockfd, F_SETFL, O_NONBLOCK); diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h index b24dbac59..9837ef662 100644 --- a/platform/windows/packet_peer_udp_winsock.h +++ b/platform/windows/packet_peer_udp_winsock.h @@ -42,15 +42,15 @@ class PacketPeerUDPWinsock : public PacketPeerUDP { mutable RingBuffer rb; uint8_t recv_buffer[PACKET_BUFFER_SIZE]; mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; - IP_Address packet_ip; - int packet_port; + mutable IP_Address packet_ip; + mutable int packet_port; mutable int queue_count; int sockfd; IP_Address peer_addr; int peer_port; - _FORCE_INLINE_ int _get_socket(); + _FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type); static PacketPeerUDP* _create(); @@ -67,7 +67,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::AddrType p_address_type, int p_recv_buffer_size=65536); virtual void close(); virtual Error wait(); virtual bool is_listening() const; diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index fcf0cb164..cd9cc9902 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -31,16 +31,11 @@ #include "stream_peer_winsock.h" #include +#include -int winsock_refcount = 0; - -static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { +#include "drivers/unix/socket_helpers.h" - their_addr.sin_family = AF_INET; // host byte order - their_addr.sin_port = htons(p_port); // short, network byte order - their_addr.sin_addr = *((struct in_addr*)&p_host.host); - memset(&(their_addr.sin_zero), '\0', 8); -}; +int winsock_refcount = 0; StreamPeerTCP* StreamPeerWinsock::_create() { @@ -92,8 +87,8 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { _block(sockfd, false, true); }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, peer_host, peer_port); + struct sockaddr_storage their_addr; + _set_sockaddr(&their_addr, peer_host, peer_port); if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { @@ -299,9 +294,10 @@ 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.host == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER); - if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET; + if ((sockfd = socket(family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { ERR_PRINT("Socket creation failed!"); disconnect(); //perror("socket"); @@ -315,8 +311,8 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { return FAILED; }; - struct sockaddr_in their_addr; - set_addr_in(their_addr, p_host, p_port); + struct sockaddr_storage their_addr; + _set_sockaddr(&their_addr, p_host, p_port); if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index dd1cf43f3..049e609d6 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -31,6 +31,9 @@ #include "stream_peer_winsock.h" #include +#include + +#include "drivers/unix/socket_helpers.h" extern int winsock_refcount; @@ -60,7 +63,7 @@ void TCPServerWinsock::cleanup() { }; -Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_hosts) { +Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,const List *p_accepted_hosts) { int sockfd; sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -73,11 +76,8 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List *p_accepted_ho return FAILED; }; - struct sockaddr_in my_addr; - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(p_port); // short, network byte order - my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts - memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + struct sockaddr_storage my_addr; + _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -140,16 +140,17 @@ Ref TCPServerWinsock::take_connection() { return NULL; }; - struct sockaddr_in their_addr; + struct sockaddr_storage their_addr; int sin_size = sizeof(their_addr); int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL); Ref conn = memnew(StreamPeerWinsock); IP_Address ip; - ip.host = (uint32_t)their_addr.sin_addr.s_addr; + int port; + _set_ip_addr_port(ip, port, &their_addr); - conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + conn->set_socket(fd, ip, port); return conn; }; diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h index bd6a05c74..94601a2e1 100644 --- a/platform/windows/tcp_server_winsock.h +++ b/platform/windows/tcp_server_winsock.h @@ -39,7 +39,7 @@ class TCPServerWinsock : public TCP_Server { public: - virtual Error listen(uint16_t p_port,const List *p_accepted_hosts=NULL); + virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4,const List *p_accepted_hosts=NULL); virtual bool is_connection_available() const; virtual Ref take_connection(); -- cgit v1.2.3-70-g09d2 From 80e911647c5df21c5b6a06876f1d48e21cd1f5fc Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sat, 22 Oct 2016 07:23:07 +0200 Subject: Pass correct address size (ipv4,ipv6) to socket connect, bind, sendto The address size passed to network system calls now reflects the the actual IP type (v4 or v6). Fix Windows and OSX ipv6 sockets --- drivers/unix/packet_peer_udp_posix.cpp | 8 ++++---- drivers/unix/socket_helpers.h | 8 ++++++-- drivers/unix/stream_peer_tcp_posix.cpp | 8 ++++---- drivers/unix/tcp_server_posix.cpp | 4 ++-- platform/windows/packet_peer_udp_winsock.cpp | 8 ++++---- platform/windows/stream_peer_winsock.cpp | 8 ++++---- platform/windows/tcp_server_winsock.cpp | 4 ++-- 7 files changed, 26 insertions(+), 22 deletions(-) (limited to 'drivers/unix/tcp_server_posix.cpp') diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp index cdc3bfce2..d6fc697c6 100644 --- a/drivers/unix/packet_peer_udp_posix.cpp +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -99,12 +99,12 @@ Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; - _set_sockaddr(&addr, peer_addr, peer_port); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); errno = 0; int err; - while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (errno != EAGAIN) { return FAILED; @@ -129,9 +129,9 @@ Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_address_type return ERR_CANT_CREATE; sockaddr_storage addr = {0}; - _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_storage)) == -1 ) { + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h index 622b45c50..4ee40e3d3 100644 --- a/drivers/unix/socket_helpers.h +++ b/drivers/unix/socket_helpers.h @@ -5,7 +5,7 @@ // helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this -static void _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { +static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); if (p_ip.type == IP_Address::TYPE_IPV6) { @@ -14,6 +14,7 @@ static void _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_i addr6->sin6_family = AF_INET6; addr6->sin6_port = htons(p_port); copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16); + return sizeof(sockaddr_in6); } else { @@ -21,10 +22,11 @@ static void _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_i addr4->sin_family = AF_INET; // host byte order addr4->sin_port = htons(p_port); // short, network byte order addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]); + return sizeof(sockaddr_in); }; }; -static void _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List *p_accepted_hosts) { +static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List *p_accepted_hosts) { memset(p_addr, 0, sizeof(struct sockaddr_storage)); if (p_address_type == IP_Address::TYPE_IPV4) { @@ -32,12 +34,14 @@ static void _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP addr4->sin_family = AF_INET; addr4->sin_port = htons(p_port); addr4->sin_addr.s_addr = INADDR_ANY; // TODO: use accepted hosts list + 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 + return sizeof(sockaddr_in6); }; }; diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 5a63a512e..f2915b0a1 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -98,9 +98,9 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { }; struct sockaddr_storage their_addr; - _set_sockaddr(&their_addr, peer_host, peer_port); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(their_addr)) == -1) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) { if (errno == EISCONN) { status = STATUS_CONNECTED; @@ -153,10 +153,10 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { #endif struct sockaddr_storage their_addr; - _set_sockaddr(&their_addr, p_host, p_port); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); errno = 0; - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(their_addr)) == -1 && errno != EINPROGRESS) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1 && errno != EINPROGRESS) { ERR_PRINT("Connection to remote host failed!"); disconnect(); diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp index 27c561847..05b739804 100644 --- a/drivers/unix/tcp_server_posix.cpp +++ b/drivers/unix/tcp_server_posix.cpp @@ -87,11 +87,11 @@ Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const } struct sockaddr_storage addr; - _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); // automatically fill with my IP TODO: use p_accepted_hosts - if (bind(sockfd, (struct sockaddr *)&addr, sizeof addr) != -1) { + if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) { if (::listen(sockfd, 1) == -1) { diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index cd4e85fd8..0408a303f 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -74,13 +74,13 @@ Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size int sock = _get_socket(peer_addr.type); ERR_FAIL_COND_V( sock == -1, FAILED ); struct sockaddr_storage addr; - _set_sockaddr(&addr, peer_addr, peer_port); + size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port); _set_blocking(true); errno = 0; int err; - while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, addr_size)) != p_buffer_size) { if (WSAGetLastError() != WSAEWOULDBLOCK) { return FAILED; @@ -120,9 +120,9 @@ Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_address_ty return ERR_CANT_CREATE; struct sockaddr_storage addr = {0}; - _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); + size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL); - if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) { close(); return ERR_UNAVAILABLE; } diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp index cd9cc9902..b511e38ec 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -88,9 +88,9 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const { }; struct sockaddr_storage their_addr; - _set_sockaddr(&their_addr, peer_host, peer_port); + size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEISCONN) { @@ -312,9 +312,9 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { }; struct sockaddr_storage their_addr; - _set_sockaddr(&their_addr, p_host, p_port); + size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port); - if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { ERR_PRINT("Connection to remote host failed!"); diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp index 049e609d6..1aedc52bb 100644 --- a/platform/windows/tcp_server_winsock.cpp +++ b/platform/windows/tcp_server_winsock.cpp @@ -77,7 +77,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,cons }; struct sockaddr_storage my_addr; - _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); + size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts); int reuse=1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { @@ -86,7 +86,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,cons } - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != SOCKET_ERROR) { + if (bind(sockfd, (struct sockaddr *)&my_addr, addr_size) != SOCKET_ERROR) { if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) { -- cgit v1.2.3-70-g09d2