diff options
Diffstat (limited to 'libvncserver/sockets.c')
-rw-r--r-- | libvncserver/sockets.c | 155 |
1 files changed, 92 insertions, 63 deletions
diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index a9c5a2c..bbc3d90 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -77,6 +77,10 @@ #include "rfbssl.h" #endif +#ifdef LIBVNCSERVER_WITH_SYSTEMD +#include <systemd/sd-daemon.h> +#endif + #if defined(__linux__) && defined(NEED_TIMEVAL) struct timeval { @@ -122,6 +126,54 @@ int deny_severity=LOG_WARNING; int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has gone away - needed to stop us hanging */ +static rfbBool +rfbNewConnectionFromSock(rfbScreenInfoPtr rfbScreen, int sock) +{ + const int one = 1; +#ifdef LIBVNCSERVER_IPv6 + struct sockaddr_storage addr; +#else + struct sockaddr_in addr; +#endif + socklen_t addrlen = sizeof(addr); + + getpeername(sock, (struct sockaddr *)&addr, &addrlen); + + if(!rfbSetNonBlocking(sock)) { + rfbLogPerror("rfbCheckFds: setnonblock"); + closesocket(sock); + return FALSE; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("rfbCheckFds: setsockopt failed: can't set TCP_NODELAY flag, non TCP socket?"); + } + +#ifdef USE_LIBWRAP + if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + STRING_UNKNOWN)) { + rfbLog("Rejected connection from client %s\n", + inet_ntoa(addr.sin_addr)); + closesocket(sock); + return FALSE; + } +#endif + +#ifdef LIBVNCSERVER_IPv6 + char host[1024]; + if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { + rfbLogPerror("rfbProcessNewConnection: error in getnameinfo"); + } + rfbLog("Got connection from client %s\n", host); +#else + rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); +#endif + + rfbNewClient(rfbScreen,sock); + return TRUE; +} + /* * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB * connections. It does nothing if called again. @@ -138,6 +190,20 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbScreen->socketState = RFB_SOCKET_READY; +#ifdef LIBVNCSERVER_WITH_SYSTEMD + if (sd_listen_fds(0) == 1) + { + int sock = SD_LISTEN_FDS_START + 0; + if (sd_is_socket(sock, AF_UNSPEC, 0, 0)) + rfbNewConnectionFromSock(rfbScreen, sock); + else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) + rfbProcessNewConnection(rfbScreen); + return; + } + else + rfbLog("Unable to establish connection with systemd socket\n"); +#endif + if (rfbScreen->inetdSock != -1) { const int one = 1; @@ -146,8 +212,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { - rfbLogPerror("setsockopt"); - return; + rfbLogPerror("setsockopt failed: can't set TCP_NODELAY flag, non TCP socket?"); } FD_ZERO(&(rfbScreen->allFds)); @@ -156,10 +221,10 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) return; } - if(rfbScreen->autoPort) { - int i; - FD_ZERO(&(rfbScreen->allFds)); + FD_ZERO(&(rfbScreen->allFds)); + if(rfbScreen->autoPort && rfbScreen->port>0) { + int i; rfbLog("Autoprobing TCP port \n"); for (i = 5900; i < 6000; i++) { if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) { @@ -176,8 +241,11 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbLog("Autoprobing selected TCP port %d\n", rfbScreen->port); FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); rfbScreen->maxFd = rfbScreen->listenSock; + } #ifdef LIBVNCSERVER_IPv6 + if(rfbScreen->autoPort && rfbScreen->ipv6port>0) { + int i; rfbLog("Autoprobing TCP6 port \n"); for (i = 5900; i < 6000; i++) { if ((rfbScreen->listen6Sock = rfbListenOnTCP6Port(i, rfbScreen->listen6Interface)) >= 0) { @@ -193,13 +261,12 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbLog("Autoprobing selected TCP6 port %d\n", rfbScreen->ipv6port); FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds)); - rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd); -#endif + rfbScreen->maxFd = rfbMax((int)rfbScreen->listen6Sock,rfbScreen->maxFd); } - else - { +#endif + + if(!rfbScreen->autoPort) { if(rfbScreen->port>0) { - FD_ZERO(&(rfbScreen->allFds)); if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) { rfbLogPerror("ListenOnTCPPort"); @@ -220,7 +287,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbLog("Listening for VNC connections on TCP6 port %d\n", rfbScreen->ipv6port); FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds)); - rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd); + rfbScreen->maxFd = rfbMax((int)rfbScreen->listen6Sock,rfbScreen->maxFd); } #endif @@ -236,7 +303,7 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port); FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds)); - rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd); + rfbScreen->maxFd = rfbMax((int)rfbScreen->udpSock,rfbScreen->maxFd); } } @@ -391,7 +458,15 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) { if (FD_ISSET(cl->sock, &fds)) + { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + do { + rfbProcessClientMessage(cl); + } while (cl->sock > 0 && webSocketsHasDataInBuffer(cl)); +#else rfbProcessClientMessage(cl); +#endif + } else rfbSendFileTransferChunk(cl); } @@ -404,14 +479,7 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) rfbBool rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) { - const int one = 1; int sock = -1; -#ifdef LIBVNCSERVER_IPv6 - struct sockaddr_storage addr; -#else - struct sockaddr_in addr; -#endif - socklen_t addrlen = sizeof(addr); fd_set listen_fds; int chosen_listen_sock = -1; @@ -432,49 +500,12 @@ rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen) if (rfbScreen->listen6Sock >= 0 && FD_ISSET(rfbScreen->listen6Sock, &listen_fds)) chosen_listen_sock = rfbScreen->listen6Sock; - if ((sock = accept(chosen_listen_sock, - (struct sockaddr *)&addr, &addrlen)) < 0) { + if ((sock = accept(chosen_listen_sock, NULL, NULL)) < 0) { rfbLogPerror("rfbCheckFds: accept"); return FALSE; } - if(!rfbSetNonBlocking(sock)) { - closesocket(sock); - return FALSE; - } - - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (char *)&one, sizeof(one)) < 0) { - rfbLogPerror("rfbCheckFds: setsockopt"); - closesocket(sock); - return FALSE; - } - -#ifdef USE_LIBWRAP - if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), - STRING_UNKNOWN)) { - rfbLog("Rejected connection from client %s\n", - inet_ntoa(addr.sin_addr)); - closesocket(sock); - return FALSE; - } -#endif - -#ifdef LIBVNCSERVER_IPv6 - { - char host[1024]; - if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) { - rfbLogPerror("rfbProcessNewConnection: error in getnameinfo"); - } - rfbLog("Got connection from client %s\n", host); - } -#else - rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); -#endif - - rfbNewClient(rfbScreen,sock); - - return TRUE; + return rfbNewConnectionFromSock(rfbScreen, sock); } @@ -548,14 +579,12 @@ rfbConnect(rfbScreenInfoPtr rfbScreen, if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { - rfbLogPerror("setsockopt failed"); - closesocket(sock); - return -1; + rfbLogPerror("setsockopt failed: can't set TCP_NODELAY flag, non TCP socket?"); } /* AddEnabledDevice(sock); */ FD_SET(sock, &rfbScreen->allFds); - rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + rfbScreen->maxFd = rfbMax(sock,rfbScreen->maxFd); return sock; } @@ -917,7 +946,7 @@ rfbListenOnTCP6Port(int port, } #ifdef IPV6_V6ONLY - /* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */ + /* we have separate IPv4 and IPv6 sockets since some OS's do not support dual binding */ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) { rfbLogPerror("rfbListenOnTCP6Port error in setsockopt IPV6_V6ONLY"); closesocket(sock); |