diff --git a/core/io/ip.cpp b/core/io/ip.cpp index aba55687a5b..4ee1b281c45 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 9ffe01b1af9..742dd0e740f 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 cab2b2bbb9a..cdc3bfce288 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 00000000000..622b45c500e --- /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 bb672cef316..5a63a512e45 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 03312a7538a..27c56184794 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_storage addr; + _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts); - 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 *)&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; + int port; + _set_ip_addr_port(ip, port, &their_addr); - 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)); - }; + 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 2c79365c08d..cd4e85fd873 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 b24dbac592c..9837ef66217 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 fcf0cb16403..cd9cc99024a 100644 --- a/platform/windows/stream_peer_winsock.cpp +++ b/platform/windows/stream_peer_winsock.cpp @@ -31,17 +31,12 @@ #include "stream_peer_winsock.h" #include +#include + +#include "drivers/unix/socket_helpers.h" int winsock_refcount = 0; -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); -}; - StreamPeerTCP* StreamPeerWinsock::_create() { return memnew(StreamPeerWinsock); @@ -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 dd1cf43f3b4..049e609d60e 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 bd6a05c74de..94601a2e12f 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();