diff --git a/libvncserver/httpd.c b/libvncserver/httpd.c index e2de6c707..43566086b 100644 --- a/libvncserver/httpd.c +++ b/libvncserver/httpd.c @@ -63,6 +63,10 @@ #include #endif +#ifdef LIBVNCSERVER_WITH_SYSTEMD +#include +#endif + #define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \ "File Not Found\n" \ @@ -100,6 +104,32 @@ rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) if (!rfbScreen->httpDir) return; +#ifdef LIBVNCSERVER_WITH_SYSTEMD + if (sd_listen_fds(0) == 2) { + rfbSocket sock = SD_LISTEN_FDS_START + 1; + if (sd_is_socket(sock, AF_UNSPEC, 0, 0)) { + rfbErr("Systemd socket activation passed 'accept=yes' inetd style socket. Only passing listening sockets is supported for http socket\n"); + } else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) { + struct sockaddr_storage sa; + int sa_len = sizeof(sa); + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + + if (getsockname(sock, (struct sockaddr *) &sa, &sa_len) == 0 + && getnameinfo((struct sockaddr *)&sa, sa_len, hoststr, sizeof(hoststr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + rfbLog("Socket activation through systemd. Listening for HTTP connections on %s:%s\n", hoststr, portstr); + } else { + rfbLogPerror("Error retrieving nameinfo of socket received from systemd\n"); + } + + rfbScreen->httpListenSock = sock; + } + + return; + } +#endif + if (rfbScreen->httpPort == 0) { rfbScreen->httpPort = rfbScreen->port-100; } diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 2c87376b8..55345e39a 100644 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -178,13 +178,31 @@ rfbInitSockets(rfbScreenInfoPtr rfbScreen) rfbScreen->socketState = RFB_SOCKET_READY; #ifdef LIBVNCSERVER_WITH_SYSTEMD - if (sd_listen_fds(0) == 1) + if (sd_listen_fds(0) == 1 || sd_listen_fds(0) == 2) { rfbSocket 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); + else if (sd_is_socket(sock, AF_UNSPEC, 0, 1)) { + struct sockaddr_storage sa; + int sa_len = sizeof(sa); + char hoststr[NI_MAXHOST]; + char portstr[NI_MAXSERV]; + + if (getsockname(sock, (struct sockaddr *) &sa, &sa_len) == 0 + && getnameinfo((struct sockaddr *)&sa, sa_len, hoststr, sizeof(hoststr), + portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { + rfbLog("Socket activation through systemd. Listening for VNC connections on %s:%s\n", hoststr, portstr); + rfbScreen->port = atoi(portstr); + } else { + rfbLogPerror("Error retrieving nameinfo of socket received from systemd\n"); + } + + FD_ZERO(&(rfbScreen->allFds)); + rfbScreen->listenSock = sock; + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; + } return; } else