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.
diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx
index a25ee24..5a8f75d 100644
--- a/common/network/TcpSocket.cxx
+++ b/common/network/TcpSocket.cxx
@@ -118,23 +118,6 @@
 }
 
 
-// -=- 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 @@
   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 @@
 }
 
 
-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 @@
     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 @@
     }
 
     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",