File U_tigervnc-fixed-ipv6-support.patch of Package tigervnc.1955
Author: Tim Waugh <twaugh@redhat.com>
Subject: Fixed IPv6 support.
Patch-Mainline: Upstream
Git-commit: 892d10a705077083489f0ed4861af123433ff811
Referenes: bnc#952057
Signed-off-by: Michal Srb <msrb@suse.com>
Index: tigervnc-1.4.3/common/network/TcpSocket.cxx
===================================================================
--- tigervnc-1.4.3.orig/common/network/TcpSocket.cxx
+++ tigervnc-1.4.3/common/network/TcpSocket.cxx
@@ -35,7 +35,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
-#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
@@ -43,6 +42,7 @@
#endif
#include <stdlib.h>
+#include <unistd.h>
#include <network/TcpSocket.h>
#include <rfb/util.h>
#include <rfb/LogWriter.h>
@@ -248,16 +248,17 @@ char* TcpSocket::getPeerAddress() {
return rfb::strDup("");
}
-#if defined(HAVE_GETADDRINFO) && defined(HAVE_INET_PTON)
+#if defined(HAVE_GETADDRINFO)
if (sa.u.sa.sa_family == AF_INET6) {
char buffer[INET6_ADDRSTRLEN + 2];
- const char *name;
+ int ret;
buffer[0] = '[';
- name = inet_ntop(sa.u.sa.sa_family, &sa.u.sin6.sin6_addr,
- buffer + 1, sizeof(buffer) - 2);
- if (name == NULL) {
+ ret = getnameinfo(&sa.u.sa, sizeof(sa.u.sin6),
+ buffer + 1, sizeof(buffer) - 2, NULL, 0,
+ NI_NUMERICHOST);
+ if (ret != 0) {
vlog.error("unable to convert peer name to a string");
return rfb::strDup("");
}
@@ -400,136 +401,77 @@ int TcpSocket::getSockPort(int sock)
}
}
+TcpListener::TcpListener(int sock)
+{
+ fd = sock;
+}
+
+TcpListener::TcpListener(const TcpListener& other)
+{
+ fd = dup (other.fd);
+ // Hope TcpListener::shutdown(other) doesn't get called...
+}
-TcpListener::TcpListener(const char *listenaddr, int port, bool localhostOnly,
- int sock, bool close_) : closeFd(close_)
+TcpListener& TcpListener::operator= (const TcpListener& other)
{
- if (sock != -1) {
- fd = sock;
- return;
+ if (this != &other)
+ {
+ closesocket (fd);
+ fd = dup (other.fd);
+ // Hope TcpListener::shutdown(other) doesn't get called...
}
+ return *this;
+}
- bool use_ipv6;
- int af;
-#ifdef HAVE_GETADDRINFO
- use_ipv6 = true;
- af = AF_INET6;
-#else
- use_ipv6 = false;
- af = AF_INET;
-#endif
+TcpListener::TcpListener(const struct sockaddr *listenaddr,
+ socklen_t listenaddrlen)
+{
+ int one = 1;
+ vnc_sockaddr_t sa;
+ int sock;
initSockets();
- if ((fd = socket(af, SOCK_STREAM, 0)) < 0) {
- // - Socket creation failed
- if (use_ipv6) {
- // - Trying to make an IPv6-capable socket failed - try again, IPv4-only
- use_ipv6 = false;
- af = AF_INET;
- fd = socket(af, SOCK_STREAM, 0);
- }
- if (fd < 0)
- throw SocketException("unable to create listening socket", errorNumber);
- } else {
- // - Socket creation succeeded
- if (use_ipv6) {
+
+ if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0)
+ throw SocketException("unable to create listening socket", errorNumber);
+
+ memcpy (&sa, listenaddr, listenaddrlen);
#ifdef IPV6_V6ONLY
- // - We made an IPv6-capable socket, and we need it to do IPv4 too
- int opt = 0;
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
-#else
- vlog.error("IPV6_V6ONLY support is missing. "
- "IPv4 clients may not be able to connect.");
-#endif
- }
+ if (listenaddr->sa_family == AF_INET6) {
+ if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one)))
+ throw SocketException("unable to set IPV6_V6ONLY", errorNumber);
+ }
+#endif /* defined(IPV6_V6ONLY) */
+
+ if (bind(sock, &sa.u.sa, listenaddrlen) == -1) {
+ closesocket(sock);
+ throw SocketException("failed to bind socket", errorNumber);
}
#ifndef WIN32
// - By default, close the socket on exec()
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ fcntl(sock, F_SETFD, FD_CLOEXEC);
- int one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&one, sizeof(one)) < 0) {
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof(one)) < 0) {
int e = errorNumber;
- closesocket(fd);
+ closesocket(sock);
throw SocketException("unable to create listening socket", e);
}
#endif
- // - Bind it to the desired port
- struct sockaddr_in addr;
-#ifdef HAVE_GETADDRINFO
- struct sockaddr_in6 addr6;
-#endif
- struct sockaddr *sa;
- int sa_len;
-
-#ifdef HAVE_GETADDRINFO
- if (use_ipv6) {
- memset(&addr6, 0, (sa_len = sizeof(addr6)));
- addr6.sin6_family = af;
- addr6.sin6_port = htons(port);
-
- if (localhostOnly)
- addr6.sin6_addr = in6addr_loopback;
- else if (listenaddr != NULL) {
-#ifdef HAVE_INET_PTON
- if (inet_pton(AF_INET6, listenaddr, &addr6.sin6_addr) != 1)
- use_ipv6 = false;
-#else
- // Unable to parse without inet_pton
- use_ipv6 = false;
-#endif
- }
-
- if (use_ipv6)
- sa = (struct sockaddr *)&addr6;
- }
-#endif
-
- if (!use_ipv6) {
- memset(&addr, 0, (sa_len = sizeof(addr)));
- addr.sin_family = af;
- addr.sin_port = htons(port);
-
- if (localhostOnly) {
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- } else if (listenaddr != NULL) {
-#ifdef HAVE_INET_ATON
- if (inet_aton(listenaddr, &addr.sin_addr) == 0)
-#else
- /* Some systems (e.g. Windows) do not have inet_aton, sigh */
- if ((addr.sin_addr.s_addr = inet_addr(listenaddr)) == INADDR_NONE)
-#endif
- {
- closesocket(fd);
- throw Exception("invalid network interface address: %s", listenaddr);
- }
- } else
- /* Bind to 0.0.0.0 by default. */
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- sa = (struct sockaddr *)&addr;
- }
-
- addr.sin_port = htons(port);
- if (bind(fd, sa, sa_len) < 0) {
- int e = errorNumber;
- closesocket(fd);
- throw SocketException("unable to bind listening socket", e);
- }
-
// - Set it to be a listening socket
- if (listen(fd, 5) < 0) {
+ if (listen(sock, 5) < 0) {
int e = errorNumber;
- closesocket(fd);
+ closesocket(sock);
throw SocketException("unable to set socket to listening mode", e);
}
+
+ fd = sock;
}
TcpListener::~TcpListener() {
- if (closeFd) closesocket(fd);
+ closesocket(fd);
}
void TcpListener::shutdown()
@@ -567,50 +509,141 @@ TcpListener::accept() {
return s;
}
-void TcpListener::getMyAddresses(std::list<char*>* result) {
-#if defined(HAVE_GETADDRINFO) && defined(HAVE_INET_PTON)
+int TcpListener::getMyPort() {
+ return TcpSocket::getSockPort(getFd());
+}
+
+
+void network::createLocalTcpListeners(std::list<TcpListener> *listeners,
+ int port)
+{
+ std::list<TcpListener> new_listeners;
vnc_sockaddr_t sa;
+#ifdef HAVE_GETADDRINFO
+ 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;
+ }
+#endif /* HAVE_GETADDRINFO */
+ 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;
+ }
+
+ if (new_listeners.empty ())
+ throw SocketException("createLocalTcpListeners: no addresses available",
+ EADDRNOTAVAIL);
+
+ listeners->splice (listeners->end(), new_listeners);
+}
+
+void network::createTcpListeners(std::list<TcpListener> *listeners,
+ const char *addr,
+ int port)
+{
+ std::list<TcpListener> new_listeners;
+
+#ifdef HAVE_GETADDRINFO
struct addrinfo *ai, *current, hints;
+ char service[16];
memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
- if ((getaddrinfo(NULL, NULL, &hints, &ai)) != 0)
- return;
-
- for (current= ai; current != NULL; current = current->ai_next) {
- if (current->ai_family != AF_INET && current->ai_family != AF_INET6)
- continue;
+ snprintf (service, sizeof (service) - 1, "%d", port);
+ service[sizeof (service) - 1] = '\0';
+ if ((getaddrinfo(addr, service, &hints, &ai)) != 0)
+ throw rdr::SystemException("getaddrinfo", errorNumber);
- char *addr = new char[INET6_ADDRSTRLEN];
- inet_ntop(current->ai_family, current->ai_addr, addr, INET6_ADDRSTRLEN);
- result->push_back(addr);
+ for (current = ai; current != NULL; current = current->ai_next) {
+ try {
+ new_listeners.push_back(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);
+ throw;
+ }
+ }
}
freeaddrinfo(ai);
#else
- char hostname[HOST_NAME_MAX];
- if (gethostname(hostname, HOST_NAME_MAX) < 0)
- throw rdr::SystemException("gethostname", errorNumber);
- const hostent* addrs = gethostbyname(hostname);
- if (addrs == 0)
- throw rdr::SystemException("gethostbyname", errorNumber);
- if (addrs->h_addrtype != AF_INET)
- throw rdr::Exception("getMyAddresses: bad family");
- for (int i=0; addrs->h_addr_list[i] != 0; i++) {
- const char* addrC = inet_ntoa(*((struct in_addr*)addrs->h_addr_list[i]));
- char* addr = new char[strlen(addrC)+1];
- strcpy(addr, addrC);
- result->push_back(addr);
+ const hostent* addrs;
+ if (addr) {
+ /* Bind to specific address */
+ addrs = gethostbyname(addr);
+ if (addrs == 0)
+ throw rdr::SystemException("gethostbyname", errorNumber);
+ if (addrs->h_addrtype != AF_INET)
+ throw rdr::Exception("createTcpListeners: bad family");
+ for (int i=0; addrs->h_addr_list[i] != 0; i++) {
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ memcpy (&addr.sin_addr, addrs->h_addr_list[i], addrs->h_length);
+ addr.sin_port = htons(port);
+ try {
+ new_listeners.push_back(TcpListener ((struct sockaddr*)&addr,
+ addrs->h_length));
+ } 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);
+ throw;
+ }
+ }
+ }
+ } else {
+ /* Bind to any address */
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+ try {
+ new_listeners.push_back(TcpListener ((struct sockaddr*)&addr,
+ sizeof (struct sockaddr_in)));
+ } 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);
+ throw;
+ }
+ }
}
-#endif /* defined(HAVE_GETADDRINFO) && defined(HAVE_INET_PTON) */
-}
+#endif /* defined(HAVE_GETADDRINFO) */
-int TcpListener::getMyPort() {
- return TcpSocket::getSockPort(getFd());
+ if (new_listeners.empty ())
+ throw SocketException("createTcpListeners: no addresses available",
+ EADDRNOTAVAIL);
+
+ listeners->splice (listeners->end(), new_listeners);
}
Index: tigervnc-1.4.3/common/network/TcpSocket.h
===================================================================
--- tigervnc-1.4.3.orig/common/network/TcpSocket.h
+++ tigervnc-1.4.3/common/network/TcpSocket.h
@@ -29,6 +29,7 @@
#define __NETWORK_TCP_SOCKET_H__
#include <network/Socket.h>
+#include <sys/socket.h>
#include <list>
@@ -66,18 +67,16 @@ namespace network {
class TcpListener : public SocketListener {
public:
- TcpListener(const char *listenaddr, int port, bool localhostOnly=false,
- int sock=-1, bool close=true);
+ 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();
virtual Socket* accept();
- void getMyAddresses(std::list<char*>* addrs);
int getMyPort();
-
- private:
- bool closeFd;
};
class TcpFilter : public ConnectionFilter {
@@ -99,6 +98,12 @@ namespace network {
std::list<Pattern> filter;
};
+ void createLocalTcpListeners(std::list<TcpListener> *listeners,
+ int port);
+ void createTcpListeners(std::list<TcpListener> *listeners,
+ const char *addr,
+ int port);
+
}
#endif // __NETWORK_TCP_SOCKET_H__
Index: tigervnc-1.4.3/unix/x0vncserver/x0vncserver.cxx
===================================================================
--- tigervnc-1.4.3.orig/unix/x0vncserver/x0vncserver.cxx
+++ tigervnc-1.4.3/unix/x0vncserver/x0vncserver.cxx
@@ -475,6 +475,8 @@ int main(int argc, char** argv)
signal(SIGINT, CleanupSignalHandler);
signal(SIGTERM, CleanupSignalHandler);
+ std::list<TcpListener> listeners;
+
try {
TXWindow::init(dpy,"x0vncserver");
Geometry geo(DisplayWidth(dpy, DefaultScreen(dpy)),
@@ -489,13 +491,16 @@ int main(int argc, char** argv)
QueryConnHandler qcHandler(dpy, &server);
server.setQueryConnectionHandler(&qcHandler);
- TcpListener listener(NULL, (int)rfbport);
+ createTcpListeners(&listeners, 0, (int)rfbport);
vlog.info("Listening on port %d", (int)rfbport);
const char *hostsData = hostsFile.getData();
FileTcpFilter fileTcpFilter(hostsData);
if (strlen(hostsData) != 0)
- listener.setFilter(&fileTcpFilter);
+ for (std::list<TcpListener>::iterator i = listeners.begin();
+ i != listeners.end();
+ i++)
+ (*i).setFilter(&fileTcpFilter);
delete[] hostsData;
PollingScheduler sched((int)pollingCycle, (int)maxProcessorUsage);
@@ -511,7 +516,11 @@ int main(int argc, char** argv)
FD_ZERO(&rfds);
FD_SET(ConnectionNumber(dpy), &rfds);
- FD_SET(listener.getFd(), &rfds);
+ for (std::list<TcpListener>::iterator i = listeners.begin();
+ i != listeners.end();
+ i++)
+ FD_SET((*i).getFd(), &rfds);
+
server.getSockets(&sockets);
int clients_connected = 0;
for (i = sockets.begin(); i != sockets.end(); i++) {
@@ -556,12 +565,16 @@ int main(int argc, char** argv)
}
// Accept new VNC connections
- if (FD_ISSET(listener.getFd(), &rfds)) {
- Socket* sock = listener.accept();
- if (sock) {
- server.addSocket(sock);
- } else {
- vlog.status("Client connection rejected");
+ for (std::list<TcpListener>::iterator i = listeners.begin();
+ i != listeners.end();
+ i++) {
+ if (FD_ISSET((*i).getFd(), &rfds)) {
+ Socket* sock = (*i).accept();
+ if (sock) {
+ server.addSocket(sock);
+ } else {
+ vlog.status("Client connection rejected");
+ }
}
}
Index: tigervnc-1.4.3/unix/xserver/hw/vnc/XserverDesktop.cc
===================================================================
--- tigervnc-1.4.3.orig/unix/xserver/hw/vnc/XserverDesktop.cc
+++ tigervnc-1.4.3/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -133,13 +133,13 @@ public:
XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
- network::TcpListener* listener_,
- network::TcpListener* httpListener_,
+ std::list<network::TcpListener> listeners_,
+ std::list<network::TcpListener> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
void* fbptr, int stride)
: pScreen(pScreen_),
server(0), httpServer(0),
- listener(listener_), httpListener(httpListener_),
+ listeners(listeners_), httpListeners(httpListeners_),
deferredUpdateTimerSet(false),
grabbing(false), ignoreHooks_(false), directFbptr(true),
queryConnectId(0)
@@ -150,7 +150,7 @@ XserverDesktop::XserverDesktop(ScreenPtr
setFramebuffer(pScreen->width, pScreen->height, fbptr, stride);
server->setQueryConnectionHandler(this);
- if (httpListener)
+ if (!httpListeners.empty ())
httpServer = new FileHTTPServer(this);
}
@@ -292,7 +292,7 @@ char* XserverDesktop::substitute(const c
}
if (strcmp(varName, "$PORT") == 0) {
char* str = new char[10];
- sprintf(str, "%d", listener ? listener->getMyPort() : 0);
+ sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ()).getMyPort());
return str;
}
if (strcmp(varName, "$WIDTH") == 0) {
@@ -523,14 +523,18 @@ void XserverDesktop::blockHandler(fd_set
// Add all sockets we want read events for, after purging
// any closed sockets.
- if (listener)
- FD_SET(listener->getFd(), fds);
- if (httpListener)
- FD_SET(httpListener->getFd(), fds);
+ 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();
+ i != httpListeners.end();
+ i++)
+ FD_SET((*i).getFd(), fds);
std::list<Socket*> sockets;
- server->getSockets(&sockets);
std::list<Socket*>::iterator i;
+ server->getSockets(&sockets);
for (i = sockets.begin(); i != sockets.end(); i++) {
int fd = (*i)->getFd();
if ((*i)->isShutdown()) {
@@ -582,20 +586,24 @@ void XserverDesktop::wakeupHandler(fd_se
// First check for file descriptors with something to do
if (nfds >= 1) {
- if (listener) {
- if (FD_ISSET(listener->getFd(), fds)) {
- FD_CLR(listener->getFd(), fds);
- Socket* sock = listener->accept();
+ 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();
sock->outStream().setBlocking(false);
server->addSocket(sock);
vlog.debug("new client, sock %d",sock->getFd());
}
}
- if (httpListener) {
- if (FD_ISSET(httpListener->getFd(), fds)) {
- FD_CLR(httpListener->getFd(), fds);
- Socket* sock = httpListener->accept();
+ 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();
sock->outStream().setBlocking(false);
httpServer->addSocket(sock);
vlog.debug("new http client, sock %d",sock->getFd());
Index: tigervnc-1.4.3/unix/xserver/hw/vnc/XserverDesktop.h
===================================================================
--- tigervnc-1.4.3.orig/unix/xserver/hw/vnc/XserverDesktop.h
+++ tigervnc-1.4.3/unix/xserver/hw/vnc/XserverDesktop.h
@@ -58,8 +58,9 @@ class XserverDesktop : public rfb::SDesk
public rfb::VNCServerST::QueryConnectionHandler {
public:
- XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener,
- network::TcpListener* httpListener_,
+ XserverDesktop(ScreenPtr pScreen_,
+ std::list<network::TcpListener> listeners_,
+ std::list<network::TcpListener> httpListeners_,
const char* name, const rfb::PixelFormat &pf,
void* fbptr, int stride);
virtual ~XserverDesktop();
@@ -127,8 +128,8 @@ private:
ScreenPtr pScreen;
rfb::VNCServerST* server;
rfb::HTTPServer* httpServer;
- network::TcpListener* listener;
- network::TcpListener* httpListener;
+ std::list<network::TcpListener> listeners;
+ std::list<network::TcpListener> httpListeners;
bool deferredUpdateTimerSet;
bool grabbing;
bool ignoreHooks_;
Index: tigervnc-1.4.3/unix/xserver/hw/vnc/vncExtInit.cc
===================================================================
--- tigervnc-1.4.3.orig/unix/xserver/hw/vnc/vncExtInit.cc
+++ tigervnc-1.4.3/unix/xserver/hw/vnc/vncExtInit.cc
@@ -223,30 +223,38 @@ void vncExtensionInit()
for (int scr = 0; scr < screenInfo.numScreens; scr++) {
if (!desktop[scr]) {
- network::TcpListener* listener = 0;
- network::TcpListener* httpListener = 0;
+ std::list<network::TcpListener> listeners;
+ std::list<network::TcpListener> httpListeners;
if (scr == 0 && vncInetdSock != -1) {
if (network::TcpSocket::isSocket(vncInetdSock) &&
!network::TcpSocket::isConnected(vncInetdSock))
{
- listener = new network::TcpListener(NULL, 0, 0, vncInetdSock, true);
+ listeners.push_back (network::TcpListener(vncInetdSock));
vlog.info("inetd wait");
}
} else {
int port = rfbport;
if (port == 0) port = 5900 + atoi(display);
port += 1000 * scr;
- listener = new network::TcpListener(listenaddr, port, localhostOnly);
+ if (localhostOnly)
+ network::createLocalTcpListeners(&listeners, port);
+ else
+ network::createTcpListeners(&listeners, listenaddr, port);
vlog.info("Listening for VNC connections on %s interface(s), port %d",
- listenaddr == NULL ? "all" : listenaddr, port);
+ localhostOnly ? "local" : (listenaddr ? listenaddr : "all"),
+ port);
CharArray httpDirStr(httpDir.getData());
if (httpDirStr.buf[0]) {
port = httpPort;
if (port == 0) port = 5800 + atoi(display);
port += 1000 * scr;
- httpListener = new network::TcpListener(listenaddr, port, localhostOnly);
+ if (localhostOnly)
+ network::createLocalTcpListeners(&httpListeners, port);
+ else
+ network::createTcpListeners(&httpListeners, listenaddr, port);
vlog.info("Listening for HTTP connections on %s interface(s), port %d",
- listenaddr == NULL ? "all" : listenaddr, port);
+ localhostOnly ? "local" : (listenaddr ? listenaddr : "all"),
+ port);
}
}
@@ -254,15 +262,15 @@ void vncExtensionInit()
PixelFormat pf = vncGetPixelFormat(screenInfo.screens[scr]);
desktop[scr] = new XserverDesktop(screenInfo.screens[scr],
- listener,
- httpListener,
+ listeners,
+ httpListeners,
desktopNameStr.buf,
pf,
vncFbptr[scr],
vncFbstride[scr]);
vlog.info("created VNC server for screen %d", scr);
- if (scr == 0 && vncInetdSock != -1 && !listener) {
+ if (scr == 0 && vncInetdSock != -1 && listeners.empty()) {
network::Socket* sock = new network::TcpSocket(vncInetdSock);
desktop[scr]->addClient(sock, false);
vlog.info("added inetd sock");
Index: tigervnc-1.4.3/unix/xserver/hw/vnc/xvnc.cc
===================================================================
--- tigervnc-1.4.3.orig/unix/xserver/hw/vnc/xvnc.cc
+++ tigervnc-1.4.3/unix/xserver/hw/vnc/xvnc.cc
@@ -352,9 +352,12 @@ static
bool displayNumFree(int num)
{
try {
- network::TcpListener l(NULL, 6000+num);
+ // Attempt to create TCPListeners on that port.
+ // They go out of scope immediately and are destroyed.
+ std::list<network::TcpListener> dummy;
+ network::createTcpListeners (&dummy, 0, 6000 + num);
} catch (rdr::Exception& e) {
- return false;
+ return false;
}
char file[256];
sprintf(file, "/tmp/.X%d-lock", num);
Index: tigervnc-1.4.3/vncviewer/vncviewer.cxx
===================================================================
--- tigervnc-1.4.3.orig/vncviewer/vncviewer.cxx
+++ tigervnc-1.4.3/vncviewer/vncviewer.cxx
@@ -488,15 +488,45 @@ int main(int argc, char** argv)
#endif
if (listenMode) {
+ std::list<TcpListener> listeners;
try {
int port = 5500;
if (isdigit(vncServerName[0]))
port = atoi(vncServerName);
- TcpListener listener(NULL, port);
+ createTcpListeners(&listeners, 0, port);
vlog.info(_("Listening on port %d\n"), port);
- sock = listener.accept();
+
+ /* Wait for a connection */
+ while (sock == NULL) {
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ for (std::list<TcpListener>::iterator i = listeners.begin();
+ i != listeners.end();
+ i++)
+ FD_SET((*i).getFd(), &rfds);
+
+ int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
+ if (n < 0) {
+ if (errno == EINTR) {
+ vlog.debug("Interrupted select() system call");
+ continue;
+ } else {
+ throw rdr::SystemException("select", errno);
+ }
+ }
+
+ for (std::list<TcpListener>::iterator i = listeners.begin ();
+ i != listeners.end();
+ i++)
+ if (FD_ISSET((*i).getFd(), &rfds)) {
+ sock = (*i).accept();
+ if (sock)
+ /* Got a connection */
+ break;
+ }
+ }
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
fl_alert("%s", e.str());