Browse Source

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 <mike.looijmans@topic.nl>
pull/1716/head
Mike Looijmans 3 months ago
parent
commit
fdd429cd58

+ 3
- 0
CMakeLists.txt View File

@@ -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)

+ 6
- 0
unix/x0vncserver/CMakeLists.txt View File

@@ -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})

+ 54
- 27
unix/x0vncserver/x0vncserver.cxx View File

@@ -38,6 +38,9 @@
#include <rfb/Timer.h>
#include <network/TcpSocket.h>
#include <network/UnixSocket.h>
#ifdef HAVE_SYSTEMD_H
# include <systemd/sd-daemon.h>
#endif

#include <signal.h>
#include <X11/X.h>
@@ -113,6 +116,25 @@ static void CleanupSignalHandler(int /*sig*/)
caughtSignal = true;
}

#ifdef HAVE_SYSTEMD_H
static int createSystemdListeners(std::list<SocketListener*> *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<SocketListener*> *)
{
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<network::SocketListener*> 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<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
(*i)->setFilter(&fileTcpFilter);
if ((int)rfbport != -1) {
std::list<network::SocketListener*> 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<SocketListener*>::iterator i = listeners.begin();
i != listeners.end();
i++)
(*i)->setFilter(&fileTcpFilter);
}
}

if (listeners.empty()) {

+ 2
- 2
unix/x0vncserver/x0vncserver.man View File

@@ -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

Loading…
Cancel
Save