From: Mike Looijmans Date: Fri, 12 Jan 2024 08:24:48 +0000 (+0100) Subject: x0vncserver: Add support for systemd socket activation X-Git-Tag: v1.13.90~29^2~5 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fdd429cd587737840a8ca08c2eb59b63423d4c3e;p=tigervnc.git x0vncserver: Add support for systemd socket activation systemd can pass in sockets as file descriptors 3 and beyond. Allows the server to use socket activation. When triggered by systemd, no other listening sockets (e.g. rfbport) will be activated. Signed-off-by: Mike Looijmans --- diff --git a/CMakeLists.txt b/CMakeLists.txt index e8d8d85d..6028fadf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,9 @@ if(UNIX AND NOT APPLE) endif() endif() +# check for systemd support (socket activation) +pkg_check_modules(LIBSYSTEMD libsystemd) + # Generate config.h and make sure the source finds it configure_file(config.h.in config.h) add_definitions(-DHAVE_CONFIG_H) diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt index 31da5118..08b346f1 100644 --- a/unix/x0vncserver/CMakeLists.txt +++ b/unix/x0vncserver/CMakeLists.txt @@ -21,6 +21,12 @@ target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/unix) target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/common) target_link_libraries(x0vncserver tx rfb network rdr unixcommon) +# systemd support (socket activation) +if (LIBSYSTEMD_FOUND) + add_definitions(-DHAVE_SYSTEMD_H) + target_link_libraries(x0vncserver ${LIBSYSTEMD_LIBRARIES}) +endif() + if(X11_FOUND AND X11_XTest_LIB) add_definitions(-DHAVE_XTEST) target_link_libraries(x0vncserver ${X11_XTest_LIB}) diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx index f87eb61e..5e9a7a57 100644 --- a/unix/x0vncserver/x0vncserver.cxx +++ b/unix/x0vncserver/x0vncserver.cxx @@ -38,6 +38,9 @@ #include #include #include +#ifdef HAVE_SYSTEMD_H +# include +#endif #include #include @@ -113,6 +116,25 @@ static void CleanupSignalHandler(int /*sig*/) caughtSignal = true; } +#ifdef HAVE_SYSTEMD_H +static int createSystemdListeners(std::list *listeners) +{ + int count = sd_listen_fds(0); + + for (int i = 0; i < count; ++i) { + /* systemd sockets start at FD 3 */ + listeners->push_back(new TcpListener(3 + i)); + } + + return count; +} +#else +static int createSystemdListeners(std::list *) +{ + return 0; +} +#endif + class FileTcpFilter : public TcpFilter { @@ -300,35 +322,40 @@ int main(int argc, char** argv) VNCServerST server(desktopName, &desktop); - if (rfbunixpath.getValueStr()[0] != '\0') { - listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode)); - vlog.info("Listening on %s (mode %04o)", (const char*)rfbunixpath, (int)rfbunixmode); - } - - if ((int)rfbport != -1) { - std::list tcp_listeners; - const char *addr = interface; - - if (strcasecmp(addr, "all") == 0) - addr = 0; - if (localhostOnly) - createLocalTcpListeners(&tcp_listeners, (int)rfbport); - else - createTcpListeners(&tcp_listeners, addr, (int)rfbport); - - if (!tcp_listeners.empty()) { - listeners.splice (listeners.end(), tcp_listeners); - vlog.info("Listening for VNC connections on %s interface(s), port %d", - localhostOnly ? "local" : (const char*)interface, - (int)rfbport); + if (createSystemdListeners(&listeners)) { + // When systemd is in charge of listeners, do not listen to anything else + vlog.info("Listening on systemd sockets"); + } else { + if (rfbunixpath.getValueStr()[0] != '\0') { + listeners.push_back(new network::UnixListener(rfbunixpath, rfbunixmode)); + vlog.info("Listening on %s (mode %04o)", (const char*)rfbunixpath, (int)rfbunixmode); } - FileTcpFilter fileTcpFilter(hostsFile); - if (strlen(hostsFile) != 0) - for (std::list::iterator i = listeners.begin(); - i != listeners.end(); - i++) - (*i)->setFilter(&fileTcpFilter); + if ((int)rfbport != -1) { + std::list tcp_listeners; + const char *addr = interface; + + if (strcasecmp(addr, "all") == 0) + addr = 0; + if (localhostOnly) + createLocalTcpListeners(&tcp_listeners, (int)rfbport); + else + createTcpListeners(&tcp_listeners, addr, (int)rfbport); + + if (!tcp_listeners.empty()) { + listeners.splice (listeners.end(), tcp_listeners); + vlog.info("Listening for VNC connections on %s interface(s), port %d", + localhostOnly ? "local" : (const char*)interface, + (int)rfbport); + } + + FileTcpFilter fileTcpFilter(hostsFile); + if (strlen(hostsFile) != 0) + for (std::list::iterator i = listeners.begin(); + i != listeners.end(); + i++) + (*i)->setFilter(&fileTcpFilter); + } } if (listeners.empty()) { diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man index 35953865..0ba195ad 100644 --- a/unix/x0vncserver/x0vncserver.man +++ b/unix/x0vncserver/x0vncserver.man @@ -61,7 +61,7 @@ DISPLAY environment variable. Specifies the TCP port on which x0vncserver listens for connections from viewers (the protocol used in VNC is called RFB - "remote framebuffer"). The default port is 5900. Specify \fB-1\fP to disable listening on a TCP -port. +port. Ignored when activated by a systemd socket. . .TP .B \-UseIPv4 @@ -74,7 +74,7 @@ Use IPv6 for incoming and outgoing connections. Default is on. .TP .B \-rfbunixpath \fIpath\fP Specifies the path of a Unix domain socket on which x0vncserver listens for -connections from viewers. +connections from viewers. Ignored when activated by a systemd socket. . .TP .B \-rfbunixmode \fImode\fP