summaryrefslogtreecommitdiffstats
path: root/libvncclient
diff options
context:
space:
mode:
authorChristian Beier <[email protected]>2012-04-02 16:30:53 +0200
committerChristian Beier <[email protected]>2012-04-02 16:30:53 +0200
commitefcdab50cc10ad121653bfff0da441495af461d3 (patch)
tree4a758a7c8caaf070ac14efa80411d00aac1ab3b7 /libvncclient
parentee4593425f63821280162d4e66a091479038a652 (diff)
parent2d50fc84f7ba869767ce052aa2aa9b11a104e0de (diff)
downloadlibtdevnc-efcdab50cc10ad121653bfff0da441495af461d3.tar.gz
libtdevnc-efcdab50cc10ad121653bfff0da441495af461d3.zip
Merge branch 'server-ipv6'
Diffstat (limited to 'libvncclient')
-rw-r--r--libvncclient/listen.c77
-rw-r--r--libvncclient/sockets.c64
-rw-r--r--libvncclient/vncviewer.c2
3 files changed, 131 insertions, 12 deletions
diff --git a/libvncclient/listen.c b/libvncclient/listen.c
index 2e9fafb..c91ad6e 100644
--- a/libvncclient/listen.c
+++ b/libvncclient/listen.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2012 Christian Beier <[email protected]>
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
@@ -50,7 +51,7 @@ listenForIncomingConnections(rfbClient* client)
rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
return;
#else
- int listenSocket;
+ int listenSocket, listen6Socket = -1;
fd_set fds;
client->listenSpecified = TRUE;
@@ -65,8 +66,24 @@ listenForIncomingConnections(rfbClient* client)
rfbClientLog("%s -listen: Command line errors are not reported until "
"a connection comes in.\n", client->programName);
- while (TRUE) {
+#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
+ /* only do IPv6 listen of listen6Port is set */
+ if (client->listen6Port > 0)
+ {
+ listen6Socket = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
+
+ if (listen6Socket < 0)
+ return;
+
+ rfbClientLog("%s -listen: Listening on IPV6 port %d\n",
+ client->programName,client->listenPort);
+ rfbClientLog("%s -listen: Command line errors are not reported until "
+ "a connection comes in.\n", client->programName);
+ }
+#endif
+ while (TRUE) {
+ int r;
/* reap any zombies */
int status, pid;
while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
@@ -75,12 +92,19 @@ listenForIncomingConnections(rfbClient* client)
FD_ZERO(&fds);
- FD_SET(listenSocket, &fds);
+ if(listenSocket >= 0)
+ FD_SET(listenSocket, &fds);
+ if(listen6Socket >= 0)
+ FD_SET(listen6Socket, &fds);
+
+ r = select(max(listenSocket, listen6Socket)+1, &fds, NULL, NULL, NULL);
- select(listenSocket+1, &fds, NULL, NULL, NULL);
+ if (r > 0) {
+ if (FD_ISSET(listenSocket, &fds))
+ client->sock = AcceptTcpConnection(client->listenSock);
+ else if (FD_ISSET(listen6Socket, &fds))
+ client->sock = AcceptTcpConnection(client->listen6Sock);
- if (FD_ISSET(listenSocket, &fds)) {
- client->sock = AcceptTcpConnection(listenSocket);
if (client->sock < 0)
return;
if (!SetNonBlocking(client->sock))
@@ -97,6 +121,7 @@ listenForIncomingConnections(rfbClient* client)
case 0:
/* child - return to caller */
close(listenSocket);
+ close(listen6Socket);
return;
default:
@@ -144,24 +169,54 @@ listenForIncomingConnectionsNoFork(rfbClient* client, int timeout)
"a connection comes in.\n", client->programName);
}
+#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
+ /* only do IPv6 listen of listen6Port is set */
+ if (client->listen6Port > 0 && client->listen6Sock < 0)
+ {
+ client->listen6Sock = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
+
+ if (client->listen6Sock < 0)
+ return -1;
+
+ rfbClientLog("%s -listennofork: Listening on IPV6 port %d\n",
+ client->programName,client->listenPort);
+ rfbClientLog("%s -listennofork: Command line errors are not reported until "
+ "a connection comes in.\n", client->programName);
+ }
+#endif
+
FD_ZERO(&fds);
- FD_SET(client->listenSock, &fds);
+ if(client->listenSock >= 0)
+ FD_SET(client->listenSock, &fds);
+ if(client->listen6Sock >= 0)
+ FD_SET(client->listen6Sock, &fds);
if (timeout < 0)
- r = select(client->listenSock+1, &fds, NULL, NULL, NULL);
+ r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, NULL);
else
- r = select(client->listenSock+1, &fds, NULL, NULL, &to);
+ r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, &to);
if (r > 0)
{
- client->sock = AcceptTcpConnection(client->listenSock);
+ if (FD_ISSET(client->listenSock, &fds))
+ client->sock = AcceptTcpConnection(client->listenSock);
+ else if (FD_ISSET(client->listen6Sock, &fds))
+ client->sock = AcceptTcpConnection(client->listen6Sock);
+
if (client->sock < 0)
return -1;
if (!SetNonBlocking(client->sock))
return -1;
- close(client->listenSock);
+ if(client->listenSock >= 0) {
+ close(client->listenSock);
+ client->listenSock = -1;
+ }
+ if(client->listen6Sock >= 0) {
+ close(client->listen6Sock);
+ client->listen6Sock = -1;
+ }
return r;
}
diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c
index be9924a..1a8df56 100644
--- a/libvncclient/sockets.c
+++ b/libvncclient/sockets.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2012 Christian Beier <[email protected]>
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
@@ -494,8 +495,9 @@ int
ListenAtTcpPortAndAddress(int port, const char *address)
{
int sock;
- struct sockaddr_in addr;
int one = 1;
+#ifndef LIBVNCSERVER_IPv6
+ struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
@@ -527,6 +529,66 @@ ListenAtTcpPortAndAddress(int port, const char *address)
return -1;
}
+#else
+ int rv;
+ struct addrinfo hints, *servinfo, *p;
+ char port_str[8];
+
+ snprintf(port_str, 8, "%d", port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if address == NULL */
+
+ if (!initSockets())
+ return -1;
+
+ if ((rv = getaddrinfo(address, port_str, &hints, &servinfo)) != 0) {
+ rfbClientErr("ListenAtTcpPortAndAddress: error in getaddrinfo: %s\n", gai_strerror(rv));
+ return -1;
+ }
+
+ /* loop through all the results and bind to the first we can */
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
+ continue;
+ }
+
+#ifdef IPV6_V6ONLY
+ /* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */
+ if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
+ rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt IPV6_V6ONLY: %s\n", strerror(errno));
+ close(sock);
+ freeaddrinfo(servinfo);
+ return -1;
+ }
+#endif
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
+ rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt SO_REUSEADDR: %s\n", strerror(errno));
+ close(sock);
+ freeaddrinfo(servinfo);
+ return -1;
+ }
+
+ if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
+ close(sock);
+ continue;
+ }
+
+ break;
+ }
+
+ if (p == NULL) {
+ rfbClientErr("ListenAtTcpPortAndAddress: error in bind: %s\n", strerror(errno));
+ return -1;
+ }
+
+ /* all done with this structure now */
+ freeaddrinfo(servinfo);
+#endif
+
if (listen(sock, 5) < 0) {
rfbClientErr("ListenAtTcpPort: listen\n");
close(sock);
diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c
index 10b430f..6a4f006 100644
--- a/libvncclient/vncviewer.c
+++ b/libvncclient/vncviewer.c
@@ -197,6 +197,8 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client->sock = -1;
client->listenSock = -1;
client->listenAddress = NULL;
+ client->listen6Sock = -1;
+ client->listen6Address = NULL;
client->clientAuthSchemes = NULL;
return client;
}