summaryrefslogtreecommitdiff
path: root/drivers/unix
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <remi@verschelde.fr>2016-10-26 14:32:51 +0200
committerGitHub <noreply@github.com>2016-10-26 14:32:51 +0200
commitc67e3a485dedae96b82c3356d5f45ab0509d7759 (patch)
tree748ab44c8ec645a8eee950991210bf6c620651d1 /drivers/unix
parentc7f9d853e206c15981330af46cfd0a0fc43fc5ef (diff)
parent80e911647c5df21c5b6a06876f1d48e21cd1f5fc (diff)
Merge pull request #6925 from godotengine/ipv6
Adding IPv6 support
Diffstat (limited to 'drivers/unix')
-rw-r--r--drivers/unix/ip_unix.cpp89
-rw-r--r--drivers/unix/ip_unix.h2
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp80
-rw-r--r--drivers/unix/packet_peer_udp_posix.h8
-rw-r--r--drivers/unix/socket_helpers.h70
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp26
-rw-r--r--drivers/unix/tcp_server_posix.cpp32
-rw-r--r--drivers/unix/tcp_server_posix.h2
8 files changed, 226 insertions, 83 deletions
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 08a8c19583..d6d1be3395 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -30,6 +30,7 @@
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
+#include <string.h>
#ifdef WINDOWS_ENABLED
#ifdef WINRT_ENABLED
@@ -62,16 +63,51 @@
#endif
#endif
-IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
+static IP_Address _sockaddr2ip(struct sockaddr* p_addr) {
- struct hostent *he;
- if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info
- ERR_PRINT("gethostbyname failed!");
- return IP_Address();
- }
IP_Address ip;
+ if (p_addr->sa_family == AF_INET) {
+ struct sockaddr_in* addr = (struct sockaddr_in*)p_addr;
+ ip.field32[0] = *((unsigned long*)&addr->sin_addr);
+ ip.type = IP_Address::TYPE_IPV4;
+ } else {
+ struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
+ for (int i=0; i<16; i++)
+ ip.field8[i] = addr6->sin6_addr.s6_addr[i];
+ ip.type = IP_Address::TYPE_IPV6;
+ };
+
+ return ip;
+};
+
+IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) {
- ip.host= *((unsigned long*)he->h_addr);
+ struct addrinfo hints;
+ struct addrinfo* result;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ if (p_type == IP_Address::TYPE_IPV4) {
+ hints.ai_family = AF_INET;
+ } else if (p_type == IP_Address::TYPE_IPV6) {
+ hints.ai_family = AF_INET6;
+ } else {
+ hints.ai_family = AF_UNSPEC;
+ };
+
+ int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result);
+ if (s != 0) {
+ ERR_PRINT("getaddrinfo failed!");
+ return IP_Address();
+ };
+
+ if (result == NULL || result->ai_addr == NULL) {
+ ERR_PRINT("Invalid response from getaddrinfo");
+ return IP_Address();
+ };
+
+ IP_Address ip = _sockaddr2ip(result->ai_addr);
+
+ freeaddrinfo(result);
return ip;
@@ -90,10 +126,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
for (int i = 0; i < hostnames->Size; i++) {
- if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 && hostnames->GetAt(i)->IPInformation != nullptr) {
+ if (hostnames->GetAt(i)->Type == HostNameType::Ipv4 || hostnames->GetAt(i)->Type == HostNameType::Ipv6 && hostnames->GetAt(i)->IPInformation != nullptr) {
r_addresses->push_back(IP_Address(String(hostnames->GetAt(i)->CanonicalName->Data())));
-
}
}
@@ -108,7 +143,7 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
while (true) {
addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size);
- int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST |
+ int err = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME,
@@ -134,14 +169,23 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
while (address != NULL) {
- char addr_chr[INET_ADDRSTRLEN];
- SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
-
IP_Address ip;
- ip.host= *((unsigned long*)&ipv4->sin_addr);
+ if (address->Address.lpSockaddr->sa_family == AF_INET) {
+
+ SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
+
+ ip.field32[0] = *((unsigned long*)&ipv4->sin_addr);
+ ip.type = IP_Address::TYPE_IPV4;
+ } else { // ipv6
+
+ SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
+ for (int i=0; i<16; i++) {
+ ip.field8[i] = ipv6->sin6_addr.s6_addr[i];
+ };
+ ip.type = IP_Address::TYPE_IPV6;
+ };
- //inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN);
r_addresses->push_back(ip);
@@ -167,20 +211,9 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
- if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
- // is a valid IP4 Address
- IP_Address ip;
- ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
-
- r_addresses->push_back(ip);
- }/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6
- // is a valid IP6 Address
- tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
- char addressBuffer[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
- printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
- } */
+ IP_Address ip = _sockaddr2ip(ifa->ifa_addr);
+ r_addresses->push_back(ip);
}
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index c0034c9a3a..d198a330e7 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -36,7 +36,7 @@
class IP_Unix : public IP {
OBJ_TYPE(IP_Unix, IP);
- virtual IP_Address _resolve_hostname(const String& p_hostname);
+ virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type);
static IP* _create_unix();
public:
diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp
index 0201a85651..d6fc697c6d 100644
--- a/drivers/unix/packet_peer_udp_posix.cpp
+++ b/drivers/unix/packet_peer_udp_posix.cpp
@@ -54,6 +54,7 @@
#include <arpa/inet.h>
#endif
+#include "drivers/unix/socket_helpers.h"
int PacketPeerUDPPosix::get_available_packet_count() const {
@@ -73,7 +74,15 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size
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);
@@ -85,17 +94,17 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size
}
Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){
- int sock = _get_socket();
+ ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED);
+
+ 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;
+ 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;
@@ -110,17 +119,19 @@ 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::AddrType p_address_type, int p_recv_buffer_size) {
+
+ ERR_FAIL_COND_V(p_address_type != IP_Address::TYPE_IPV4 && p_address_type != IP_Address::TYPE_IPV6, ERR_INVALID_PARAMETER);
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;
- if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) {
+
+ sockaddr_storage addr = {0};
+ size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_address_type, NULL);
+
+ if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) {
close();
return ERR_UNAVAILABLE;
}
@@ -145,16 +156,41 @@ Error PacketPeerUDPPosix::wait() {
Error PacketPeerUDPPosix::_poll(bool p_wait) {
- struct sockaddr_in from = {0};
- socklen_t len = sizeof(struct sockaddr_in);
+ 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) {
- 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;
};
@@ -182,12 +218,14 @@ int PacketPeerUDPPosix::get_packet_port() const{
return packet_port;
}
-int PacketPeerUDPPosix::_get_socket() {
+int PacketPeerUDPPosix::_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/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h
index a11282e5d6..13b6969e53 100644
--- a/drivers/unix/packet_peer_udp_posix.h
+++ b/drivers/unix/packet_peer_udp_posix.h
@@ -44,15 +44,15 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
mutable RingBuffer<uint8_t> 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();
virtual Error _poll(bool p_block);
@@ -65,7 +65,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/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h
new file mode 100644
index 0000000000..4ee40e3d3d
--- /dev/null
+++ b/drivers/unix/socket_helpers.h
@@ -0,0 +1,70 @@
+#ifndef SOCKET_HELPERS_H
+#define SOCKET_HELPERS_H
+
+#include <string.h>
+
+// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this
+
+static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) {
+
+ 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);
+ return sizeof(sockaddr_in6);
+
+ } 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]);
+ return sizeof(sockaddr_in);
+ };
+};
+
+static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List<String> *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
+ 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);
+ };
+};
+
+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 45a4b934c1..f2915b0a16 100644
--- a/drivers/unix/stream_peer_tcp_posix.cpp
+++ b/drivers/unix/stream_peer_tcp_posix.cpp
@@ -61,13 +61,7 @@
#define MSG_NOSIGNAL SO_NOSIGPIPE
#endif
-static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) {
-
- 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);
-};
+#include "drivers/unix/socket_helpers.h"
StreamPeerTCP* StreamPeerTCPPosix::_create() {
@@ -103,9 +97,10 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
_block(sockfd, false, true);
};
- struct sockaddr_in their_addr;
- set_addr_in(their_addr, peer_host, peer_port);
- if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) {
+ struct sockaddr_storage their_addr;
+ size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port);
+
+ if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) {
if (errno == EISCONN) {
status = STATUS_CONNECTED;
@@ -140,9 +135,10 @@ 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.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, 0)) == -1) {
+ int family = p_host.type == IP_Address::TYPE_IPV6 ? AF_INET6 : AF_INET;
+ if ((sockfd = socket(family, SOCK_STREAM, 0)) == -1) {
ERR_PRINT("Socket creation failed!");
disconnect();
//perror("socket");
@@ -156,11 +152,11 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) {
ioctl(sockfd, FIONBIO, &bval);
#endif
- struct sockaddr_in their_addr;
- set_addr_in(their_addr, p_host, p_port);
+ struct sockaddr_storage their_addr;
+ size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port);
errno = 0;
- if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -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 c67bb51334..05b739804c 100644
--- a/drivers/unix/tcp_server_posix.cpp
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -55,6 +55,9 @@
#include <netinet/in.h>
#include <sys/socket.h>
#include <assert.h>
+
+#include "drivers/unix/socket_helpers.h"
+
TCP_Server* TCPServerPosix::_create() {
return memnew(TCPServerPosix);
@@ -65,10 +68,11 @@ void TCPServerPosix::make_default() {
TCP_Server::_create = TCPServerPosix::_create;
};
-Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
+Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *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 +86,12 @@ Error TCPServerPosix::listen(uint16_t p_port,const List<String> *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);
+ struct sockaddr_storage addr;
+ 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 *)&my_addr, sizeof my_addr) != -1) {
+ if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) {
if (::listen(sockfd, 1) == -1) {
@@ -136,9 +139,9 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
return Ref<StreamPeerTCP>();
};
- 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<StreamPeerTCP>());
#ifndef NO_FCNTL
fcntl(fd, F_SETFL, O_NONBLOCK);
@@ -149,8 +152,11 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
Ref<StreamPeerTCPPosix> 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));
+
+ int port;
+ _set_ip_addr_port(ip, port, &their_addr);
+
+ conn->set_socket(fd, ip, port);
return conn;
};
diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h
index 570bcaab12..134ec494cb 100644
--- a/drivers/unix/tcp_server_posix.h
+++ b/drivers/unix/tcp_server_posix.h
@@ -40,7 +40,7 @@ class TCPServerPosix : public TCP_Server {
public:
- virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
+ virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_IPV4, const List<String> *p_accepted_hosts=NULL);
virtual bool is_connection_available() const;
virtual Ref<StreamPeerTCP> take_connection();