diff options
author | Pierre Ossman <ossman@cendio.se> | 2015-09-29 15:40:49 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2015-09-29 15:40:49 +0200 |
commit | f7aa3f9bd315ba52d6ee1e7236a580102c8d20b8 (patch) | |
tree | 45d4adcd35e59ec11233d1f6a65b78fad811701f /common | |
parent | 7ebce759122eeda383d7d299ee577c75c0f9ac6e (diff) | |
download | tigervnc-f7aa3f9bd315ba52d6ee1e7236a580102c8d20b8.tar.gz tigervnc-f7aa3f9bd315ba52d6ee1e7236a580102c8d20b8.zip |
Return TcpListener pointers rather than objects
It is easier to control object life time and avoid magical socket
duplication by having a single TcpListener object to pass around.
We have to be more careful about deleting the object though.
Diffstat (limited to 'common')
-rw-r--r-- | common/network/TcpSocket.cxx | 124 | ||||
-rw-r--r-- | common/network/TcpSocket.h | 8 |
2 files changed, 50 insertions, 82 deletions
diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx index a25ee244..5a8f75d1 100644 --- a/common/network/TcpSocket.cxx +++ b/common/network/TcpSocket.cxx @@ -118,23 +118,6 @@ static void initSockets() { } -// -=- Socket duplication help for Windows -static int dupsocket(int fd) -{ -#ifdef WIN32 - int ret; - WSAPROTOCOL_INFO info; - ret = WSADuplicateSocket(fd, GetCurrentProcessId(), &info); - if (ret != 0) - throw SocketException("unable to duplicate socket", errorNumber); - return WSASocket(info.iAddressFamily, info.iSocketType, info.iProtocol, - &info, 0, 0); -#else - return dup(fd); -#endif -} - - // -=- TcpSocket TcpSocket::TcpSocket(int sock, bool close) @@ -411,23 +394,6 @@ TcpListener::TcpListener(int sock) fd = sock; } -TcpListener::TcpListener(const TcpListener& other) -{ - fd = dupsocket (other.fd); - // Hope TcpListener::shutdown(other) doesn't get called... -} - -TcpListener& TcpListener::operator= (const TcpListener& other) -{ - if (this != &other) - { - closesocket (fd); - fd = dupsocket (other.fd); - // Hope TcpListener::shutdown(other) doesn't get called... - } - return *this; -} - TcpListener::TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen) { @@ -570,57 +536,41 @@ int TcpListener::getMyPort() { } -void network::createLocalTcpListeners(std::list<TcpListener> *listeners, +void network::createLocalTcpListeners(std::list<TcpListener*> *listeners, int port) { - std::list<TcpListener> new_listeners; - vnc_sockaddr_t sa; + struct addrinfo ai[2]; + vnc_sockaddr_t sa[2]; - initSockets(); + memset(ai, 0, sizeof(ai)); + memset(sa, 0, sizeof(sa)); - if (UseIPv6) { - sa.u.sin6.sin6_family = AF_INET6; - sa.u.sin6.sin6_port = htons (port); - sa.u.sin6.sin6_addr = in6addr_loopback; - try { - new_listeners.push_back (TcpListener (&sa.u.sa, sizeof (sa.u.sin6))); - } catch (SocketException& e) { - // Ignore this if it is due to lack of address family support on - // the interface or on the system - if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) - // Otherwise, report the error - throw; - } - } - if (UseIPv4) { - sa.u.sin.sin_family = AF_INET; - sa.u.sin.sin_port = htons (port); - sa.u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - try { - new_listeners.push_back (TcpListener (&sa.u.sa, sizeof (sa.u.sin))); - } catch (SocketException& e) { - // Ignore this if it is due to lack of address family support on - // the interface or on the system - if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) - // Otherwise, report the error - throw; - } - } + sa[0].u.sin.sin_family = AF_INET; + sa[0].u.sin.sin_port = htons (port); + sa[0].u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - if (new_listeners.empty ()) - throw SocketException("createLocalTcpListeners: no addresses available", - EADDRNOTAVAIL); + ai[0].ai_family = sa[0].u.sin.sin_family; + ai[0].ai_addr = &sa[0].u.sa; + ai[0].ai_addrlen = sizeof(sa[0].u.sin); + ai[0].ai_next = &ai[1]; - listeners->splice (listeners->end(), new_listeners); + sa[1].u.sin6.sin6_family = AF_INET6; + sa[1].u.sin6.sin6_port = htons (port); + sa[1].u.sin6.sin6_addr = in6addr_loopback; + + ai[1].ai_family = sa[1].u.sin6.sin6_family; + ai[1].ai_addr = &sa[1].u.sa; + ai[1].ai_addrlen = sizeof(sa[1].u.sin6); + ai[1].ai_next = NULL; + + createTcpListeners(listeners, ai); } -void network::createTcpListeners(std::list<TcpListener> *listeners, +void network::createTcpListeners(std::list<TcpListener*> *listeners, const char *addr, int port) { - std::list<TcpListener> new_listeners; - - struct addrinfo *ai, *current, hints; + struct addrinfo *ai, hints; char service[16]; int result; @@ -640,6 +590,22 @@ void network::createTcpListeners(std::list<TcpListener> *listeners, throw rdr::Exception("unable to resolve listening address: %s", gai_strerror(result)); + try { + createTcpListeners(listeners, ai); + } catch(...) { + freeaddrinfo(ai); + throw; + } +} + +void network::createTcpListeners(std::list<TcpListener*> *listeners, + const struct addrinfo *ai) +{ + const struct addrinfo *current; + std::list<TcpListener*> new_listeners; + + initSockets(); + for (current = ai; current != NULL; current = current->ai_next) { switch (current->ai_family) { case AF_INET: @@ -657,19 +623,21 @@ void network::createTcpListeners(std::list<TcpListener> *listeners, } try { - new_listeners.push_back(TcpListener (current->ai_addr, - current->ai_addrlen)); + new_listeners.push_back(new TcpListener(current->ai_addr, + current->ai_addrlen)); } catch (SocketException& e) { // Ignore this if it is due to lack of address family support on // the interface or on the system if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) { // Otherwise, report the error - freeaddrinfo(ai); + while (!new_listeners.empty()) { + delete new_listeners.back(); + new_listeners.pop_back(); + } throw; } } } - freeaddrinfo(ai); if (new_listeners.empty ()) throw SocketException("createTcpListeners: no addresses available", diff --git a/common/network/TcpSocket.h b/common/network/TcpSocket.h index 979cd4bd..02f04c91 100644 --- a/common/network/TcpSocket.h +++ b/common/network/TcpSocket.h @@ -76,8 +76,6 @@ namespace network { public: TcpListener(const struct sockaddr *listenaddr, socklen_t listenaddrlen); TcpListener(int sock); - TcpListener(const TcpListener& other); - TcpListener& operator= (const TcpListener& other); virtual ~TcpListener(); virtual void shutdown(); @@ -87,11 +85,13 @@ namespace network { int getMyPort(); }; - void createLocalTcpListeners(std::list<TcpListener> *listeners, + void createLocalTcpListeners(std::list<TcpListener*> *listeners, int port); - void createTcpListeners(std::list<TcpListener> *listeners, + void createTcpListeners(std::list<TcpListener*> *listeners, const char *addr, int port); + void createTcpListeners(std::list<TcpListener*> *listeners, + const struct addrinfo *ai); typedef struct vnc_sockaddr { union { |