Browse Source

Fixed IPv6 support.

The TcpListener constructor now takes a 'struct sockaddr*' instead of
a string, and the createTcpListeners function creates TcpListener
instances for an address based on the results from getaddrinfo().

The XserverDesktop class now takes a list of TcpListener instances for
each of the RFB and HTTP sockets.

The TcpListener::closeFd member variable is not used and has been
removed.
tags/v1.4.90
Tim Waugh 9 years ago
parent
commit
892d10a705

+ 186
- 133
common/network/TcpSocket.cxx View File

@@ -34,7 +34,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
@@ -42,6 +41,7 @@
#endif

#include <stdlib.h>
#include <unistd.h>
#include <network/TcpSocket.h>
#include <rfb/util.h>
#include <rfb/LogWriter.h>
@@ -274,16 +274,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("");
}
@@ -426,139 +427,77 @@ int TcpSocket::getSockPort(int sock)
}
}

static int bindIPv6 (const char *listenaddr,
int port,
bool localhostOnly)
TcpListener::TcpListener(int sock)
{
#ifdef HAVE_GETADDRINFO
struct sockaddr_in6 addr6;
socklen_t sa_len;
int fd;

if (!UseIPv6)
return -1;

if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
return -1;

#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, (char *)&opt, sizeof(opt));
#else
vlog.error("IPV6_V6ONLY support is missing. "
"IPv4 clients may not be able to connect.");
#endif
fd = sock;
}

memset(&addr6, 0, (sa_len = sizeof(addr6)));
addr6.sin6_family = AF_INET6;
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) {
closesocket(fd);
return -1;
}
#else
// Unable to parse without inet_pton
closesocket(fd);
return -1;
#endif
}
TcpListener::TcpListener(const TcpListener& other)
{
fd = dup (other.fd);
// Hope TcpListener::shutdown(other) doesn't get called...
}

if (bind(fd, (struct sockaddr *) &addr6, sa_len) == -1) {
closesocket(fd);
return -1;
TcpListener& TcpListener::operator= (const TcpListener& other)
{
if (this != &other)
{
closesocket (fd);
fd = dup (other.fd);
// Hope TcpListener::shutdown(other) doesn't get called...
}

return fd;
#else
return -1;
#endif /* HAVE_GETADDRINFO */
return *this;
}

static int bindIPv4 (const char *listenaddr,
int port,
bool localhostOnly)
TcpListener::TcpListener(const struct sockaddr *listenaddr,
socklen_t listenaddrlen)
{
struct sockaddr_in addr;
socklen_t sa_len;
int fd;

if (!UseIPv4)
return -1;

if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
int one = 1;
vnc_sockaddr_t sa;
int sock;

memset(&addr, 0, (sa_len = sizeof(addr)));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
initSockets();

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);
if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0)
throw SocketException("unable to create listening socket", errorNumber);

if (bind(fd, (struct sockaddr *) &addr, sa_len) == -1) {
closesocket(fd);
return -1;
memcpy (&sa, listenaddr, listenaddrlen);
#ifdef IPV6_V6ONLY
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) */

return fd;
}

TcpListener::TcpListener(const char *listenaddr, int port, bool localhostOnly,
int sock, bool close_) : closeFd(close_)
{
if (sock != -1) {
fd = sock;
return;
if (bind(sock, &sa.u.sa, listenaddrlen) == -1) {
closesocket(sock);
throw SocketException("failed to bind socket", errorNumber);
}

initSockets();
if ((fd = bindIPv6 (listenaddr, port, localhostOnly)) < 0)
if ((fd = bindIPv4 (listenaddr, port, localhostOnly)) < 0)
throw SocketException("unable to create listening 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

// - 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()
@@ -596,46 +535,160 @@ 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
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;
}
}
#endif /* HAVE_GETADDRINFO */
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;
}
}

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;
snprintf (service, sizeof (service) - 1, "%d", port);
service[sizeof (service) - 1] = '\0';
if ((getaddrinfo(addr, service, &hints, &ai)) != 0)
throw rdr::SystemException("getaddrinfo", errorNumber);

for (current= ai; current != NULL; current = current->ai_next) {
if (current->ai_family != AF_INET && current->ai_family != AF_INET6)
for (current = ai; current != NULL; current = current->ai_next) {
switch (current->ai_family) {
case AF_INET:
if (!UseIPv4)
continue;
break;

case AF_INET6:
if (!UseIPv6)
continue;
break;

default:
continue;
}

char *addr = new char[INET6_ADDRSTRLEN];
inet_ntop(current->ai_family, current->ai_addr, addr, INET6_ADDRSTRLEN);
result->push_back(addr);
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
const hostent* addrs = gethostbyname(0);
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);
}



+ 11
- 6
common/network/TcpSocket.h View File

@@ -29,6 +29,7 @@
#define __NETWORK_TCP_SOCKET_H__

#include <network/Socket.h>
#include <sys/socket.h>

#include <list>

@@ -66,20 +67,24 @@ 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;
};

void createLocalTcpListeners(std::list<TcpListener> *listeners,
int port);
void createTcpListeners(std::list<TcpListener> *listeners,
const char *addr,
int port);

class TcpFilter : public ConnectionFilter {
public:
TcpFilter(const char* filter);

+ 22
- 9
unix/x0vncserver/x0vncserver.cxx View File

@@ -477,6 +477,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)),
@@ -491,13 +493,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);
@@ -513,7 +518,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++) {
@@ -558,12 +567,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");
}
}
}


+ 4
- 1
unix/xserver/hw/vnc/RFBGlue.cc View File

@@ -187,7 +187,10 @@ int vncGetSocketPort(int fd)
int vncIsTCPPortUsed(int port)
{
try {
network::TcpListener l(NULL, port);
// 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, port);
} catch (rdr::Exception& e) {
return 0;
}

+ 26
- 18
unix/xserver/hw/vnc/XserverDesktop.cc View File

@@ -91,14 +91,14 @@ public:


XserverDesktop::XserverDesktop(int screenIndex_,
network::TcpListener* listener_,
network::TcpListener* httpListener_,
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)
: screenIndex(screenIndex_),
server(0), httpServer(0),
listener(listener_), httpListener(httpListener_),
listeners(listeners_), httpListeners(httpListeners_),
deferredUpdateTimerSet(false), directFbptr(true),
queryConnectId(0)
{
@@ -108,7 +108,7 @@ XserverDesktop::XserverDesktop(int screenIndex_,
setFramebuffer(width, height, fbptr, stride);
server->setQueryConnectionHandler(this);

if (httpListener)
if (!httpListeners.empty ())
httpServer = new FileHTTPServer(this);
}

@@ -222,7 +222,7 @@ char* XserverDesktop::substitute(const char* varName)
}
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) {
@@ -393,14 +393,18 @@ void XserverDesktop::readBlockHandler(fd_set* fds, struct timeval ** timeout)

// 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()) {
@@ -452,20 +456,24 @@ void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds)
// 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());

+ 5
- 4
unix/xserver/hw/vnc/XserverDesktop.h View File

@@ -50,8 +50,9 @@ class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
public rfb::VNCServerST::QueryConnectionHandler {
public:

XserverDesktop(int screenIndex, network::TcpListener* listener,
network::TcpListener* httpListener_,
XserverDesktop(int screenIndex,
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();
@@ -112,8 +113,8 @@ private:
int screenIndex;
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 directFbptr;
struct timeval dixTimeout;

+ 23
- 12
unix/xserver/hw/vnc/vncExtInit.cc View File

@@ -134,33 +134,44 @@ void vncExtensionInit(void)
for (int scr = 0; scr < vncGetScreenCount(); 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 {
const char *addr = interface;
int port = rfbport;
if (port == 0) port = 5900 + atoi(vncGetDisplay());
port += 1000 * scr;
if (strcasecmp(interface, "all") == 0)
listener = new network::TcpListener(NULL, port, localhostOnly);
if (strcasecmp(addr, "all") == 0)
addr = 0;
if (localhostOnly)
network::createLocalTcpListeners(&listeners, port);
else
listener = new network::TcpListener(interface, port, localhostOnly);
network::createTcpListeners(&listeners, addr, port);

vlog.info("Listening for VNC connections on %s interface(s), port %d",
(const char*)interface, port);
localhostOnly ? "local" : (const char*)interface,
port);

CharArray httpDirStr(httpDir.getData());
if (httpDirStr.buf[0]) {
port = httpPort;
if (port == 0) port = 5800 + atoi(vncGetDisplay());
port += 1000 * scr;
httpListener = new network::TcpListener(interface, port, localhostOnly);
if (localhostOnly)
network::createLocalTcpListeners(&httpListeners, port);
else
network::createTcpListeners(&httpListeners, addr, port);

vlog.info("Listening for HTTP connections on %s interface(s), port %d",
(const char*)interface, port);
localhostOnly ? "local" : (const char*)interface,
port);
}
}

@@ -168,8 +179,8 @@ void vncExtensionInit(void)
PixelFormat pf = vncGetPixelFormat(scr);

desktop[scr] = new XserverDesktop(scr,
listener,
httpListener,
listeners,
httpListeners,
desktopNameStr.buf,
pf,
vncGetScreenWidth(scr),
@@ -178,7 +189,7 @@ void vncExtensionInit(void)
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");

+ 32
- 2
vncviewer/vncviewer.cxx View File

@@ -534,15 +534,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());

Loading…
Cancel
Save