summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--common/network/TcpSocket.cxx124
-rw-r--r--common/network/TcpSocket.h8
-rw-r--r--unix/x0vncserver/x0vncserver.cxx16
-rw-r--r--unix/xserver/hw/vnc/RFBGlue.cc7
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.cc38
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.h8
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.cc6
-rw-r--r--vncviewer/vncviewer.cxx16
-rw-r--r--win/winvnc/ManagedListener.cxx16
-rw-r--r--win/winvnc/ManagedListener.h2
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;