summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2015-09-29 15:40:49 +0200
committerPierre Ossman <ossman@cendio.se>2015-09-29 15:40:49 +0200
commitf7aa3f9bd315ba52d6ee1e7236a580102c8d20b8 (patch)
tree45d4adcd35e59ec11233d1f6a65b78fad811701f /common
parent7ebce759122eeda383d7d299ee577c75c0f9ac6e (diff)
downloadtigervnc-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.cxx124
-rw-r--r--common/network/TcpSocket.h8
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 {