diff --git a/BUILDING.txt b/BUILDING.txt index bfcad5b940..83a68aee17 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -48,6 +48,9 @@ Build Requirements (Unix) * All build requirements Xorg imposes (see its documentation) * patch +-- If building x0vncserver with socket activation support: + * libsystemd + -- Optional ffmpeg development kit support (libav) * You might have to enable additional repositories for this. E.g., on RHEL, EPEL and RPMFusion (free + nonfree) need to be enabled. diff --git a/CMakeLists.txt b/CMakeLists.txt index e8d8d85d43..f1bfd61850 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,14 @@ if(UNIX AND NOT APPLE) endif() endif() +# check for systemd support (socket activation) +if(UNIX AND NOT APPLE) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(LIBSYSTEMD libsystemd) + endif() +endif() + # 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 31da51183a..08b346f1a6 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 f87eb61e4a..28567a6e26 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,37 @@ static void CleanupSignalHandler(int /*sig*/) caughtSignal = true; } +static bool hasSystemdListeners() +{ +#ifdef HAVE_SYSTEMD_H + // This also returns true on errors, because we then assume we were + // meant to use systemd but failed somewhere + return sd_listen_fds(0) != 0; +#else + return false; +#endif +} + +static int createSystemdListeners(std::list *listeners) +{ +#ifdef HAVE_SYSTEMD_H + int count = sd_listen_fds(0); + if (count < 0) { + vlog.error("Error getting listening sockets from systemd: %s", + strerror(-count)); + return count; + } + + for (int i = 0; i < count; ++i) + listeners->push_back(new TcpListener(SD_LISTEN_FDS_START + i)); + + return count; +#else + (void)listeners; + return 0; +#endif +} + class FileTcpFilter : public TcpFilter { @@ -252,6 +286,10 @@ int main(int argc, char** argv) Configuration::removeParam("SendCutText"); Configuration::removeParam("MaxCutText"); + // Assume different defaults when socket activated + if (hasSystemdListeners()) + rfbport.setParam(-1); + for (int i = 1; i < argc; i++) { if (Configuration::setParam(argv[i])) continue; @@ -300,6 +338,11 @@ int main(int argc, char** argv) VNCServerST server(desktopName, &desktop); + if (createSystemdListeners(&listeners) > 0) { + // When systemd is in charge of listeners, do not listen to anything else + vlog.info("Listening on systemd sockets"); + } + 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); diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man index 359538656f..78cf60b9a4 100644 --- a/unix/x0vncserver/x0vncserver.man +++ b/unix/x0vncserver/x0vncserver.man @@ -60,8 +60,8 @@ DISPLAY environment variable. .B \-rfbport \fIport\fP 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. +Specify \fB-1\fP to disable listening on a TCP port. The default port is +5900 when started directly, and -1 when activated by a systemd socket. . .TP .B \-UseIPv4 @@ -74,7 +74,8 @@ 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. Default is to not listen to any Unix domain +socket. . .TP .B \-rfbunixmode \fImode\fP