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 | |
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.
-rw-r--r-- | common/network/TcpSocket.cxx | 124 | ||||
-rw-r--r-- | common/network/TcpSocket.h | 8 | ||||
-rw-r--r-- | unix/x0vncserver/x0vncserver.cxx | 16 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/RFBGlue.cc | 7 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.cc | 38 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.h | 8 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.cc | 6 | ||||
-rw-r--r-- | vncviewer/vncviewer.cxx | 16 | ||||
-rw-r--r-- | win/winvnc/ManagedListener.cxx | 16 | ||||
-rw-r--r-- | win/winvnc/ManagedListener.h | 2 |
10 files changed, 112 insertions, 129 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 { diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx index 2d9a0665..6b5d479d 100644 --- a/unix/x0vncserver/x0vncserver.cxx +++ b/unix/x0vncserver/x0vncserver.cxx @@ -477,7 +477,7 @@ int main(int argc, char** argv) signal(SIGINT, CleanupSignalHandler); signal(SIGTERM, CleanupSignalHandler); - std::list<TcpListener> listeners; + std::list<TcpListener*> listeners; try { TXWindow::init(dpy,"x0vncserver"); @@ -499,10 +499,10 @@ int main(int argc, char** argv) const char *hostsData = hostsFile.getData(); FileTcpFilter fileTcpFilter(hostsData); if (strlen(hostsData) != 0) - for (std::list<TcpListener>::iterator i = listeners.begin(); + for (std::list<TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) - (*i).setFilter(&fileTcpFilter); + (*i)->setFilter(&fileTcpFilter); delete[] hostsData; PollingScheduler sched((int)pollingCycle, (int)maxProcessorUsage); @@ -518,10 +518,10 @@ int main(int argc, char** argv) FD_ZERO(&rfds); FD_SET(ConnectionNumber(dpy), &rfds); - for (std::list<TcpListener>::iterator i = listeners.begin(); + for (std::list<TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) - FD_SET((*i).getFd(), &rfds); + FD_SET((*i)->getFd(), &rfds); server.getSockets(&sockets); int clients_connected = 0; @@ -567,11 +567,11 @@ int main(int argc, char** argv) } // Accept new VNC connections - for (std::list<TcpListener>::iterator i = listeners.begin(); + for (std::list<TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) { - if (FD_ISSET((*i).getFd(), &rfds)) { - Socket* sock = (*i).accept(); + if (FD_ISSET((*i)->getFd(), &rfds)) { + Socket* sock = (*i)->accept(); if (sock) { server.addSocket(sock); } else { diff --git a/unix/xserver/hw/vnc/RFBGlue.cc b/unix/xserver/hw/vnc/RFBGlue.cc index a1507924..9a014f17 100644 --- a/unix/xserver/hw/vnc/RFBGlue.cc +++ b/unix/xserver/hw/vnc/RFBGlue.cc @@ -190,9 +190,12 @@ int vncIsTCPPortUsed(int port) { try { // Attempt to create TCPListeners on that port. - // They go out of scope immediately and are destroyed. - std::list<network::TcpListener> dummy; + std::list<network::TcpListener*> dummy; network::createTcpListeners (&dummy, 0, port); + while (!dummy.empty()) { + delete dummy.back(); + dummy.pop_back(); + } } catch (rdr::Exception& e) { return 1; } diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 165afbb6..9b91d9a4 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -91,8 +91,8 @@ public: XserverDesktop::XserverDesktop(int screenIndex_, - std::list<network::TcpListener> listeners_, - std::list<network::TcpListener> httpListeners_, + std::list<network::TcpListener*> listeners_, + std::list<network::TcpListener*> httpListeners_, const char* name, const rfb::PixelFormat &pf, int width, int height, void* fbptr, int stride) @@ -114,6 +114,14 @@ XserverDesktop::XserverDesktop(int screenIndex_, XserverDesktop::~XserverDesktop() { + while (!listeners.empty()) { + delete listeners.back(); + listeners.pop_back(); + } + while (!httpListeners.empty()) { + delete httpListeners.back(); + httpListeners.pop_back(); + } if (!directFbptr) delete [] data; delete httpServer; @@ -222,7 +230,7 @@ char* XserverDesktop::substitute(const char* varName) } if (strcmp(varName, "$PORT") == 0) { char* str = new char[10]; - sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ()).getMyPort()); + sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ())->getMyPort()); return str; } if (strcmp(varName, "$WIDTH") == 0) { @@ -393,14 +401,14 @@ void XserverDesktop::readBlockHandler(fd_set* fds, struct timeval ** timeout) // Add all sockets we want read events for, after purging // any closed sockets. - for (std::list<network::TcpListener>::iterator i = listeners.begin(); + for (std::list<network::TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) - FD_SET((*i).getFd(), fds); - for (std::list<network::TcpListener>::iterator i = httpListeners.begin(); + FD_SET((*i)->getFd(), fds); + for (std::list<network::TcpListener*>::iterator i = httpListeners.begin(); i != httpListeners.end(); i++) - FD_SET((*i).getFd(), fds); + FD_SET((*i)->getFd(), fds); std::list<Socket*> sockets; std::list<Socket*>::iterator i; @@ -456,24 +464,24 @@ void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds) // First check for file descriptors with something to do if (nfds >= 1) { - for (std::list<network::TcpListener>::iterator i = listeners.begin(); + for (std::list<network::TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) { - if (FD_ISSET((*i).getFd(), fds)) { - FD_CLR((*i).getFd(), fds); - Socket* sock = (*i).accept(); + if (FD_ISSET((*i)->getFd(), fds)) { + FD_CLR((*i)->getFd(), fds); + Socket* sock = (*i)->accept(); sock->outStream().setBlocking(false); server->addSocket(sock); vlog.debug("new client, sock %d",sock->getFd()); } } - for (std::list<network::TcpListener>::iterator i = httpListeners.begin(); + for (std::list<network::TcpListener*>::iterator i = httpListeners.begin(); i != httpListeners.end(); i++) { - if (FD_ISSET((*i).getFd(), fds)) { - FD_CLR((*i).getFd(), fds); - Socket* sock = (*i).accept(); + if (FD_ISSET((*i)->getFd(), fds)) { + FD_CLR((*i)->getFd(), fds); + Socket* sock = (*i)->accept(); sock->outStream().setBlocking(false); httpServer->addSocket(sock); vlog.debug("new http client, sock %d",sock->getFd()); diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index 6909a766..c0690286 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -51,8 +51,8 @@ class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, public: XserverDesktop(int screenIndex, - std::list<network::TcpListener> listeners_, - std::list<network::TcpListener> httpListeners_, + std::list<network::TcpListener*> listeners_, + std::list<network::TcpListener*> httpListeners_, const char* name, const rfb::PixelFormat &pf, int width, int height, void* fbptr, int stride); virtual ~XserverDesktop(); @@ -113,8 +113,8 @@ private: int screenIndex; rfb::VNCServerST* server; rfb::HTTPServer* httpServer; - std::list<network::TcpListener> listeners; - std::list<network::TcpListener> httpListeners; + std::list<network::TcpListener*> listeners; + std::list<network::TcpListener*> httpListeners; bool deferredUpdateTimerSet; bool directFbptr; struct timeval dixTimeout; diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index d9f989a9..0ae55b6f 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -134,13 +134,13 @@ void vncExtensionInit(void) for (int scr = 0; scr < vncGetScreenCount(); scr++) { if (!desktop[scr]) { - std::list<network::TcpListener> listeners; - std::list<network::TcpListener> httpListeners; + std::list<network::TcpListener*> listeners; + std::list<network::TcpListener*> httpListeners; if (scr == 0 && vncInetdSock != -1) { if (network::TcpSocket::isSocket(vncInetdSock) && !network::TcpSocket::isConnected(vncInetdSock)) { - listeners.push_back (network::TcpListener(vncInetdSock)); + listeners.push_back(new network::TcpListener(vncInetdSock)); vlog.info("inetd wait"); } } else { diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx index 230cc25a..a2bc0297 100644 --- a/vncviewer/vncviewer.cxx +++ b/vncviewer/vncviewer.cxx @@ -525,7 +525,7 @@ int main(int argc, char** argv) #endif if (listenMode) { - std::list<TcpListener> listeners; + std::list<TcpListener*> listeners; try { int port = 5500; if (isdigit(vncServerName[0])) @@ -539,10 +539,10 @@ int main(int argc, char** argv) while (sock == NULL) { fd_set rfds; FD_ZERO(&rfds); - for (std::list<TcpListener>::iterator i = listeners.begin(); + for (std::list<TcpListener*>::iterator i = listeners.begin(); i != listeners.end(); i++) - FD_SET((*i).getFd(), &rfds); + FD_SET((*i)->getFd(), &rfds); int n = select(FD_SETSIZE, &rfds, 0, 0, 0); if (n < 0) { @@ -554,11 +554,11 @@ int main(int argc, char** argv) } } - for (std::list<TcpListener>::iterator i = listeners.begin (); + for (std::list<TcpListener*>::iterator i = listeners.begin (); i != listeners.end(); i++) - if (FD_ISSET((*i).getFd(), &rfds)) { - sock = (*i).accept(); + if (FD_ISSET((*i)->getFd(), &rfds)) { + sock = (*i)->accept(); if (sock) /* Got a connection */ break; @@ -571,6 +571,10 @@ int main(int argc, char** argv) return 1; } + while (!listeners.empty()) { + delete listeners.back(); + listeners.pop_back(); + } } else { if (vncServerName[0] == '\0') { ServerDialog::run(defaultServerName, vncServerName); diff --git a/win/winvnc/ManagedListener.cxx b/win/winvnc/ManagedListener.cxx index 25d8dc0f..b80f5a16 100644 --- a/win/winvnc/ManagedListener.cxx +++ b/win/winvnc/ManagedListener.cxx @@ -31,9 +31,9 @@ ManagedListener::ManagedListener(SocketManager* mgr) ManagedListener::~ManagedListener() { if (!sockets.empty()) { - std::list<network::TcpListener>::iterator iter; + std::list<network::TcpListener*>::iterator iter; for (iter = sockets.begin(); iter != sockets.end(); ++iter) - manager->remListener(&*iter); + manager->remListener(*iter); sockets.clear(); } delete filter; @@ -62,9 +62,9 @@ void ManagedListener::setFilter(const char* filterStr) { delete filter; filter = new network::TcpFilter(filterStr); if (!sockets.empty() && !localOnly) { - std::list<network::TcpListener>::iterator iter; + std::list<network::TcpListener*>::iterator iter; for (iter = sockets.begin(); iter != sockets.end(); ++iter) - iter->setFilter(filter); + (*iter)->setFilter(filter); } } @@ -80,10 +80,10 @@ bool ManagedListener::isListening() { } void ManagedListener::refresh() { - std::list<network::TcpListener>::iterator iter; + std::list<network::TcpListener*>::iterator iter; if (!sockets.empty()) { for (iter = sockets.begin(); iter != sockets.end(); ++iter) - manager->remListener(&*iter); + manager->remListener(*iter); sockets.clear(); } if (!server) @@ -101,11 +101,11 @@ void ManagedListener::refresh() { if (!sockets.empty()) { if (!localOnly) { for (iter = sockets.begin(); iter != sockets.end(); ++iter) - iter->setFilter(filter); + (*iter)->setFilter(filter); } try { for (iter = sockets.begin(); iter != sockets.end(); ++iter) - manager->addListener(&*iter, server, addrChangeNotifier); + manager->addListener(*iter, server, addrChangeNotifier); } catch (...) { // FIXME: Should unwind what we've added sockets.clear(); diff --git a/win/winvnc/ManagedListener.h b/win/winvnc/ManagedListener.h index 1c7099fe..e8d3c892 100644 --- a/win/winvnc/ManagedListener.h +++ b/win/winvnc/ManagedListener.h @@ -45,7 +45,7 @@ namespace winvnc { protected: void refresh(); - std::list<network::TcpListener> sockets; + std::list<network::TcpListener*> sockets; network::TcpFilter* filter; rfb::win32::SocketManager* manager; rfb::win32::SocketManager::AddressChangeNotifier* addrChangeNotifier; |