diff options
Diffstat (limited to 'unix/x0vncserver')
-rw-r--r-- | unix/x0vncserver/CMakeLists.txt | 7 | ||||
-rw-r--r-- | unix/x0vncserver/Geometry.cxx | 15 | ||||
-rw-r--r-- | unix/x0vncserver/Geometry.h | 13 | ||||
-rw-r--r-- | unix/x0vncserver/Image.cxx | 5 | ||||
-rw-r--r-- | unix/x0vncserver/PollingManager.cxx | 19 | ||||
-rw-r--r-- | unix/x0vncserver/XDesktop.cxx | 64 | ||||
-rw-r--r-- | unix/x0vncserver/XDesktop.h | 3 | ||||
-rw-r--r-- | unix/x0vncserver/XPixelBuffer.cxx | 36 | ||||
-rw-r--r-- | unix/x0vncserver/XPixelBuffer.h | 10 | ||||
-rw-r--r-- | unix/x0vncserver/XSelection.cxx | 32 | ||||
-rw-r--r-- | unix/x0vncserver/x0vncserver.cxx | 195 | ||||
-rw-r--r-- | unix/x0vncserver/x0vncserver.man | 322 |
12 files changed, 394 insertions, 327 deletions
diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt index 9d6d2133..4ea09dd8 100644 --- a/unix/x0vncserver/CMakeLists.txt +++ b/unix/x0vncserver/CMakeLists.txt @@ -20,11 +20,12 @@ target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/unix/common) target_include_directories(x0vncserver PUBLIC ${CMAKE_SOURCE_DIR}/unix/tx) 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) +target_link_libraries(x0vncserver core tx rfb network rdr unixcommon) # systemd support (socket activation) -if (LIBSYSTEMD_FOUND) - target_link_libraries(x0vncserver ${LIBSYSTEMD_LIBRARIES}) +if (SYSTEMD_FOUND) + target_include_directories(x0vncserver SYSTEM PRIVATE ${SYSTEMD_INCLUDE_DIRS}) + target_link_libraries(x0vncserver ${SYSTEMD_LIBRARIES}) endif() if(X11_XTest_LIB) diff --git a/unix/x0vncserver/Geometry.cxx b/unix/x0vncserver/Geometry.cxx index 28e71be4..0a848cbb 100644 --- a/unix/x0vncserver/Geometry.cxx +++ b/unix/x0vncserver/Geometry.cxx @@ -26,14 +26,13 @@ #include <string.h> -#include <rfb/LogWriter.h> -#include <x0vncserver/Geometry.h> +#include <core/LogWriter.h> -using namespace rfb; +#include <x0vncserver/Geometry.h> -static LogWriter vlog("Geometry"); +static core::LogWriter vlog("Geometry"); -StringParameter Geometry::m_geometryParam("Geometry", +core::StringParameter Geometry::m_geometryParam("Geometry", "Screen area shown to VNC clients. " "Format is <width>x<height>+<offset_x>+<offset_y>, " "more information in man X, section GEOMETRY SPECIFICATIONS. " @@ -67,9 +66,9 @@ void Geometry::recalc(int fullWidth, int fullHeight) width(), height(), offsetLeft(), offsetTop()); } -Rect Geometry::parseString(const char *arg) const +core::Rect Geometry::parseString(const char* arg) const { - Rect result; // empty by default + core::Rect result; // empty by default if (arg != nullptr && strlen(arg) > 0) { int w, h; @@ -83,7 +82,7 @@ Rect Geometry::parseString(const char *arg) const x = m_fullWidth - w - x; if (sign_y[0] == '-') y = m_fullHeight - h - y; - Rect partRect(x, y, x + w, y + h); + core::Rect partRect(x, y, x + w, y + h); result = partRect.intersect(m_rect); if (result.area() <= 0) { vlog.error("Requested area is out of the desktop boundaries"); diff --git a/unix/x0vncserver/Geometry.h b/unix/x0vncserver/Geometry.h index d938d63f..709d5e35 100644 --- a/unix/x0vncserver/Geometry.h +++ b/unix/x0vncserver/Geometry.h @@ -23,8 +23,9 @@ #ifndef __GEOMETRY_H__ #define __GEOMETRY_H__ -#include <rfb/Rect.h> -#include <rfb/Configuration.h> +#include <core/Rect.h> + +namespace core { class StringParameter; } class Geometry { @@ -42,18 +43,18 @@ public: int offsetTop() const { return m_rect.tl.y; } // Return the same information as a Rect structure. - const rfb::Rect& getRect() const { return m_rect; } + const core::Rect& getRect() const { return m_rect; } protected: // Parse a string, extract size and coordinates, // and return that rectangle clipped to m_rect. - rfb::Rect parseString(const char *arg) const; + core::Rect parseString(const char* arg) const; - static rfb::StringParameter m_geometryParam; + static core::StringParameter m_geometryParam; int m_fullWidth; int m_fullHeight; - rfb::Rect m_rect; + core::Rect m_rect; }; #endif // __GEOMETRY_H__ diff --git a/unix/x0vncserver/Image.cxx b/unix/x0vncserver/Image.cxx index bd48c88d..88467c61 100644 --- a/unix/x0vncserver/Image.cxx +++ b/unix/x0vncserver/Image.cxx @@ -32,7 +32,8 @@ #include <sys/ipc.h> #include <sys/shm.h> -#include <rfb/LogWriter.h> +#include <core/LogWriter.h> + #include <x0vncserver/Image.h> // @@ -60,7 +61,7 @@ ImageCleanup imageCleanup; // Image class implementation. // -static rfb::LogWriter vlog("Image"); +static core::LogWriter vlog("Image"); Image::Image(Display *d) : xim(nullptr), dpy(d) diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx index 1761e358..04c3d065 100644 --- a/unix/x0vncserver/PollingManager.cxx +++ b/unix/x0vncserver/PollingManager.cxx @@ -27,17 +27,18 @@ #include <stdio.h> #include <string.h> #include <time.h> + #include <X11/Xlib.h> -#include <rfb/LogWriter.h> + +#include <core/Configuration.h> +#include <core/LogWriter.h> + #include <rfb/VNCServer.h> -#include <rfb/Configuration.h> #include <rfb/ServerCore.h> #include <x0vncserver/PollingManager.h> -using namespace rfb; - -static LogWriter vlog("PollingMgr"); +static core::LogWriter vlog("PollingMgr"); const int PollingManager::m_pollingOrder[32] = { 0, 16, 8, 24, 4, 20, 12, 28, @@ -123,7 +124,7 @@ void PollingManager::debugAfterPoll() // Search for changed rectangles on the screen. // -void PollingManager::poll(VNCServer *server) +void PollingManager::poll(rfb::VNCServer* server) { #ifdef DEBUG debugBeforePoll(); @@ -142,7 +143,7 @@ void PollingManager::poll(VNCServer *server) #define DBG_REPORT_CHANGES(title) #endif -bool PollingManager::pollScreen(VNCServer *server) +bool PollingManager::pollScreen(rfb::VNCServer* server) { if (!server) return false; @@ -259,12 +260,12 @@ int PollingManager::checkColumn(int x, int y, int h, bool *pChangeFlags) return nTilesChanged; } -int PollingManager::sendChanges(VNCServer *server) const +int PollingManager::sendChanges(rfb::VNCServer* server) const { const bool *pChangeFlags = m_changeFlags; int nTilesChanged = 0; - Rect rect; + core::Rect rect; for (int y = 0; y < m_heightTiles; y++) { for (int x = 0; x < m_widthTiles; x++) { if (*pChangeFlags++) { diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx index b43e3f79..b52b20e1 100644 --- a/unix/x0vncserver/XDesktop.cxx +++ b/unix/x0vncserver/XDesktop.cxx @@ -28,9 +28,11 @@ #include <algorithm> +#include <core/LogWriter.h> + #include <network/Socket.h> -#include <rfb/LogWriter.h> +#include <rfb/ScreenSet.h> #include <x0vncserver/XDesktop.h> @@ -56,25 +58,27 @@ void vncSetGlueContext(Display *dpy, void *res); #include <x0vncserver/Geometry.h> #include <x0vncserver/XPixelBuffer.h> -using namespace rfb; - extern const unsigned short code_map_qnum_to_xorgevdev[]; extern const unsigned int code_map_qnum_to_xorgevdev_len; extern const unsigned short code_map_qnum_to_xorgkbd[]; extern const unsigned int code_map_qnum_to_xorgkbd_len; -BoolParameter useShm("UseSHM", "Use MIT-SHM extension if available", true); -BoolParameter rawKeyboard("RawKeyboard", - "Send keyboard events straight through and " - "avoid mapping them to the current keyboard " - "layout", false); -IntParameter queryConnectTimeout("QueryConnectTimeout", - "Number of seconds to show the 'Accept connection' dialog before " - "rejecting the connection", - 10); - -static rfb::LogWriter vlog("XDesktop"); +core::BoolParameter + useShm("UseSHM", "Use MIT-SHM extension if available", true); +core::BoolParameter + rawKeyboard("RawKeyboard", + "Send keyboard events straight through and avoid " + "mapping them to the current keyboard layout", + false); +core::IntParameter + queryConnectTimeout("QueryConnectTimeout", + "Number of seconds to show the 'Accept " + "connection' dialog before rejecting the " + "connection", + 10, 0, INT_MAX); + +static core::LogWriter vlog("XDesktop"); // order is important as it must match RFB extension static const char * ledNames[XDESKTOP_N_LEDS] = { @@ -234,12 +238,12 @@ void XDesktop::poll() { &x, &y, &wx, &wy, &mask)) { x -= geometry->offsetLeft(); y -= geometry->offsetTop(); - server->setCursorPos(rfb::Point(x, y), false); + server->setCursorPos({x, y}, false); } } } -void XDesktop::init(VNCServer* vs) +void XDesktop::init(rfb::VNCServer* vs) { server = vs; } @@ -347,7 +351,9 @@ void XDesktop::queryConnection(network::Socket* sock, queryConnectDialog->map(); } -void XDesktop::pointerEvent(const Point& pos, uint16_t buttonMask) { +void XDesktop::pointerEvent(const core::Point& pos, + uint16_t buttonMask) +{ #ifdef HAVE_XTEST if (!haveXtest) return; XTestFakeMotionEvent(dpy, DefaultScreen(dpy), @@ -605,9 +611,9 @@ void XDesktop::keyEvent(uint32_t keysym, uint32_t xtcode, bool down) { #endif } -ScreenSet XDesktop::computeScreenLayout() +rfb::ScreenSet XDesktop::computeScreenLayout() { - ScreenSet layout; + rfb::ScreenSet layout; char buffer[2048]; #ifdef HAVE_XRANDR @@ -622,8 +628,8 @@ ScreenSet XDesktop::computeScreenLayout() XRRFreeScreenResources(res); // Adjust the layout relative to the geometry - ScreenSet::iterator iter, iter_next; - Point offset(-geometry->offsetLeft(), -geometry->offsetTop()); + rfb::ScreenSet::iterator iter, iter_next; + core::Point offset(-geometry->offsetLeft(), -geometry->offsetTop()); for (iter = layout.begin();iter != layout.end();iter = iter_next) { iter_next = iter; ++iter_next; iter->dimensions = iter->dimensions.intersect(geometry->getRect()); @@ -705,9 +711,9 @@ unsigned int XDesktop::setScreenLayout(int fb_width, int fb_height, } else { vlog.debug("Impossible layout - trying to adjust"); - ScreenSet::const_iterator firstscreen = layout.begin(); + rfb::ScreenSet::const_iterator firstscreen = layout.begin(); adjustedLayout.add_screen(*firstscreen); - ScreenSet::iterator iter = adjustedLayout.begin(); + rfb::ScreenSet::iterator iter = adjustedLayout.begin(); RROutput outputId = None; for (int i = 0;i < vncRandRGetOutputCount();i++) { @@ -861,15 +867,15 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) { #ifdef HAVE_XDAMAGE } else if (ev->type == xdamageEventBase) { XDamageNotifyEvent* dev; - Rect rect; + core::Rect rect; if (!running) return true; dev = (XDamageNotifyEvent*)ev; rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height); - rect = rect.translate(Point(-geometry->offsetLeft(), - -geometry->offsetTop())); + rect = rect.translate({-geometry->offsetLeft(), + -geometry->offsetTop()}); server->add_changed(rect); return true; @@ -940,7 +946,7 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) { server->setPixelBuffer(pb, computeScreenLayout()); // Mark entire screen as changed - server->add_changed(rfb::Region(Rect(0, 0, cev->width, cev->height))); + server->add_changed({{0, 0, cev->width, cev->height}}); } return true; @@ -985,7 +991,7 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) { if (cev->window == cev->root) return false; - server->setCursor(0, 0, Point(), nullptr); + server->setCursor(0, 0, {}, nullptr); return true; #endif } @@ -1046,7 +1052,7 @@ bool XDesktop::setCursor() } try { - server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot), + server->setCursor(cim->width, cim->height, {cim->xhot, cim->yhot}, cursorData); } catch (std::exception& e) { vlog.error("XserverDesktop::setCursor: %s",e.what()); diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h index a27a1eae..89e2531d 100644 --- a/unix/x0vncserver/XDesktop.h +++ b/unix/x0vncserver/XDesktop.h @@ -63,7 +63,8 @@ public: bool isRunning(); void queryConnection(network::Socket* sock, const char* userName) override; - void pointerEvent(const rfb::Point& pos, uint16_t buttonMask) override; + void pointerEvent(const core::Point& pos, + uint16_t buttonMask) override; void keyEvent(uint32_t keysym, uint32_t xtcode, bool down) override; unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout) override; diff --git a/unix/x0vncserver/XPixelBuffer.cxx b/unix/x0vncserver/XPixelBuffer.cxx index 0e24cc51..5e89a342 100644 --- a/unix/x0vncserver/XPixelBuffer.cxx +++ b/unix/x0vncserver/XPixelBuffer.cxx @@ -25,15 +25,17 @@ #include <config.h> #endif +#include <string.h> #include <vector> -#include <rfb/Region.h> + #include <X11/Xlib.h> -#include <x0vncserver/XPixelBuffer.h> -using namespace rfb; +#include <core/Region.h> + +#include <x0vncserver/XPixelBuffer.h> XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, - const Rect &rect) + const core::Rect& rect) : FullFramePixelBuffer(), m_poller(nullptr), m_dpy(dpy), @@ -42,16 +44,16 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, m_offsetTop(rect.tl.y) { // Fill in the PixelFormat structure of the parent class. - format = PixelFormat(m_image->xim->bits_per_pixel, - m_image->xim->depth, - (m_image->xim->byte_order == MSBFirst), - true, - m_image->xim->red_mask >> (ffs(m_image->xim->red_mask) - 1), - m_image->xim->green_mask >> (ffs(m_image->xim->green_mask) - 1), - m_image->xim->blue_mask >> (ffs(m_image->xim->blue_mask) - 1), - ffs(m_image->xim->red_mask) - 1, - ffs(m_image->xim->green_mask) - 1, - ffs(m_image->xim->blue_mask) - 1); + format = rfb::PixelFormat(m_image->xim->bits_per_pixel, + m_image->xim->depth, + (m_image->xim->byte_order == MSBFirst), + true, + m_image->xim->red_mask >> (ffs(m_image->xim->red_mask) - 1), + m_image->xim->green_mask >> (ffs(m_image->xim->green_mask) - 1), + m_image->xim->blue_mask >> (ffs(m_image->xim->blue_mask) - 1), + ffs(m_image->xim->red_mask) - 1, + ffs(m_image->xim->green_mask) - 1, + ffs(m_image->xim->blue_mask) - 1); // Set up the remaining data of the parent class. setBuffer(rect.width(), rect.height(), (uint8_t *)m_image->xim->data, @@ -72,10 +74,10 @@ XPixelBuffer::~XPixelBuffer() } void -XPixelBuffer::grabRegion(const rfb::Region& region) +XPixelBuffer::grabRegion(const core::Region& region) { - std::vector<Rect> rects; - std::vector<Rect>::const_iterator i; + std::vector<core::Rect> rects; + std::vector<core::Rect>::const_iterator i; region.get_rects(&rects); for (i = rects.begin(); i != rects.end(); i++) { grabRect(*i); diff --git a/unix/x0vncserver/XPixelBuffer.h b/unix/x0vncserver/XPixelBuffer.h index 7556e6ef..727d0867 100644 --- a/unix/x0vncserver/XPixelBuffer.h +++ b/unix/x0vncserver/XPixelBuffer.h @@ -24,10 +24,12 @@ #define __XPIXELBUFFER_H__ #include <rfb/PixelBuffer.h> -#include <rfb/VNCServer.h> + #include <x0vncserver/Image.h> #include <x0vncserver/PollingManager.h> +namespace rfb { class VNCServer; } + // // XPixelBuffer is an Image-based implementation of FullFramePixelBuffer. // @@ -35,7 +37,7 @@ class XPixelBuffer : public rfb::FullFramePixelBuffer { public: - XPixelBuffer(Display *dpy, ImageFactory &factory, const rfb::Rect &rect); + XPixelBuffer(Display* dpy, ImageFactory& factory, const core::Rect& rect); virtual ~XPixelBuffer(); // Provide access to the underlying Image object. @@ -45,7 +47,7 @@ public: inline void poll(rfb::VNCServer *server) { m_poller->poll(server); } // Override PixelBuffer::grabRegion(). - void grabRegion(const rfb::Region& region) override; + void grabRegion(const core::Region& region) override; protected: PollingManager *m_poller; @@ -57,7 +59,7 @@ protected: // Copy pixels from the screen to the pixel buffer, // for the specified rectangular area of the buffer. - inline void grabRect(const rfb::Rect &r) { + inline void grabRect(const core::Rect& r) { m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft + r.tl.x, m_offsetTop + r.tl.y, r.width(), r.height(), r.tl.x, r.tl.y); diff --git a/unix/x0vncserver/XSelection.cxx b/unix/x0vncserver/XSelection.cxx index c724d2ac..5de171d1 100644 --- a/unix/x0vncserver/XSelection.cxx +++ b/unix/x0vncserver/XSelection.cxx @@ -17,19 +17,23 @@ */ #include <X11/Xatom.h> -#include <rfb/Configuration.h> -#include <rfb/LogWriter.h> -#include <rfb/util.h> + +#include <core/Configuration.h> +#include <core/LogWriter.h> +#include <core/string.h> + #include <x0vncserver/XSelection.h> -rfb::BoolParameter setPrimary("SetPrimary", - "Set the PRIMARY as well as the CLIPBOARD selection", - true); -rfb::BoolParameter sendPrimary("SendPrimary", - "Send the PRIMARY as well as the CLIPBOARD selection", - true); +core::BoolParameter + setPrimary("SetPrimary", + "Set the PRIMARY as well as the CLIPBOARD selection", + true); +core::BoolParameter + sendPrimary("SendPrimary", + "Send the PRIMARY as well as the CLIPBOARD selection", + true); -static rfb::LogWriter vlog("XSelection"); +static core::LogWriter vlog("XSelection"); XSelection::XSelection(Display* dpy_, XSelectionHandler* handler_) : TXWindow(dpy_, 1, 1, nullptr), handler(handler_), announcedSelection(None) @@ -89,7 +93,7 @@ bool XSelection::selectionRequest(Window requestor, Atom selection, Atom target, return false; if (target == XA_STRING) { - std::string latin1 = rfb::utf8ToLatin1(clientData.data(), clientData.length()); + std::string latin1 = core::utf8ToLatin1(clientData.data(), clientData.length()); XChangeProperty(dpy, requestor, property, XA_STRING, 8, PropModeReplace, (unsigned char*)latin1.data(), latin1.length()); return true; @@ -184,11 +188,11 @@ void XSelection::selectionNotify(XSelectionEvent* ev, Atom type, int format, return; if (type == xaUTF8_STRING) { - std::string result = rfb::convertLF((char*)data, nitems); + std::string result = core::convertLF((char*)data, nitems); handler->handleXSelectionData(result.c_str()); } else if (type == XA_STRING) { - std::string result = rfb::convertLF((char*)data, nitems); - result = rfb::latin1ToUTF8(result.data(), result.length()); + std::string result = core::convertLF((char*)data, nitems); + result = core::latin1ToUTF8(result.data(), result.length()); handler->handleXSelectionData(result.c_str()); } } diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx index 7ea427ed..b8b631aa 100644 --- a/unix/x0vncserver/x0vncserver.cxx +++ b/unix/x0vncserver/x0vncserver.cxx @@ -31,13 +31,20 @@ #include <errno.h> #include <pwd.h> -#include <rfb/Logger_stdio.h> -#include <rfb/LogWriter.h> +#include <core/Configuration.h> +#include <core/Logger_stdio.h> +#include <core/LogWriter.h> +#include <core/Timer.h> + +#include <rdr/FdInStream.h> +#include <rdr/FdOutStream.h> + +#include <rfb/UnixPasswordValidator.h> #include <rfb/VNCServerST.h> -#include <rfb/Configuration.h> -#include <rfb/Timer.h> + #include <network/TcpSocket.h> #include <network/UnixSocket.h> + #ifdef HAVE_LIBSYSTEMD # include <systemd/sd-daemon.h> #endif @@ -54,30 +61,40 @@ extern char buildtime[]; -using namespace rfb; -using namespace network; - -static LogWriter vlog("Main"); +static core::LogWriter vlog("Main"); static const char* defaultDesktopName(); -IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling " - "cycle; actual interval may be dynamically " - "adjusted to satisfy MaxProcessorUsage setting", 30); -IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of " - "CPU time to be consumed", 35); -StringParameter desktopName("desktop", "Name of VNC desktop", defaultDesktopName()); -StringParameter displayname("display", "The X display", ""); -IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900); -StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", ""); -IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600); -StringParameter hostsFile("HostsFile", "File with IP access control rules", ""); -BoolParameter localhostOnly("localhost", - "Only allow connections from localhost", - false); -StringParameter interface("interface", - "Listen on the specified network address", - "all"); +core::IntParameter + pollingCycle("PollingCycle", + "Milliseconds per one polling cycle; actual interval " + "may be dynamically adjusted to satisfy " + "MaxProcessorUsage setting", 30, 0, INT_MAX); +core::IntParameter + maxProcessorUsage("MaxProcessorUsage", + "Maximum percentage of CPU time to be consumed", + 35, 0, 100); +core::StringParameter + desktopName("desktop", "Name of VNC desktop", defaultDesktopName()); +core::StringParameter + displayname("display", "The X display", ""); +core::IntParameter + rfbport("rfbport", + "TCP port to listen for RFB protocol", 5900, -1, 65535); +core::StringParameter + rfbunixpath("rfbunixpath", + "Unix socket to listen for RFB protocol", ""); +core::IntParameter + rfbunixmode("rfbunixmode", + "Unix socket access mode", 0600, 0000, 0777); +core::StringParameter + hostsFile("HostsFile", "File with IP access control rules", ""); +core::BoolParameter + localhostOnly("localhost", + "Only allow connections from localhost", false); +core::StringParameter + interface("interface", + "Listen on the specified network address", "all"); static const char* defaultDesktopName() { @@ -127,7 +144,7 @@ static bool hasSystemdListeners() #endif } -static int createSystemdListeners(std::list<SocketListener*> *listeners) +static int createSystemdListeners(std::list<network::SocketListener*> *listeners) { #ifdef HAVE_LIBSYSTEMD int count = sd_listen_fds(0); @@ -138,7 +155,7 @@ static int createSystemdListeners(std::list<SocketListener*> *listeners) } for (int i = 0; i < count; ++i) - listeners->push_back(new TcpListener(SD_LISTEN_FDS_START + i)); + listeners->push_back(new network::TcpListener(SD_LISTEN_FDS_START + i)); return count; #else @@ -148,7 +165,7 @@ static int createSystemdListeners(std::list<SocketListener*> *listeners) } -class FileTcpFilter : public TcpFilter +class FileTcpFilter : public network::TcpFilter { public: @@ -166,7 +183,7 @@ public: free(fileName); } - bool verifyConnection(Socket* s) override + bool verifyConnection(network::Socket* s) override { if (!reloadRules()) { vlog.error("Could not read IP filtering rules, rejecting all clients"); @@ -267,59 +284,72 @@ static void usage() "Other valid forms are <param>=<value> -<param>=<value> " "--<param>=<value>\n" "Parameter names are case-insensitive. The parameters are:\n\n"); - Configuration::listParams(79, 14); + core::Configuration::listParams(79, 14); exit(1); } int main(int argc, char** argv) { - initStdIOLoggers(); - LogWriter::setLogParams("*:stderr:30"); + core::initStdIOLoggers(); + core::LogWriter::setLogParams("*:stderr:30"); programName = argv[0]; Display* dpy; - Configuration::enableServerParams(); - // Assume different defaults when socket activated if (hasSystemdListeners()) rfbport.setParam(-1); - for (int i = 1; i < argc; i++) { - if (Configuration::setParam(argv[i])) + for (int i = 1; i < argc;) { + int ret; + + ret = core::Configuration::handleParamArg(argc, argv, i); + if (ret > 0) { + i += ret; continue; + } - if (argv[i][0] == '-') { - if (i+1 < argc) { - if (Configuration::setParam(&argv[i][1], argv[i+1])) { - i++; - continue; - } - } - if (strcmp(argv[i], "-v") == 0 || - strcmp(argv[i], "-version") == 0 || - strcmp(argv[i], "--version") == 0) { - printVersion(stdout); - return 0; - } + if (strcmp(argv[i], "-h") == 0 || + strcmp(argv[i], "-help") == 0 || + strcmp(argv[i], "--help") == 0) { usage(); } - usage(); + if (strcmp(argv[i], "-v") == 0 || + strcmp(argv[i], "-version") == 0 || + strcmp(argv[i], "--version") == 0) { + printVersion(stdout); + return 0; + } + + if (argv[i][0] == '-') { + fprintf(stderr, "%s: Unrecognized option '%s'\n", + programName, argv[i]); + fprintf(stderr, "See '%s --help' for more information.\n", + programName); + exit(1); + } + + fprintf(stderr, "%s: Extra argument '%s'\n", programName, argv[i]); + fprintf(stderr, "See '%s --help' for more information.\n", + programName); + exit(1); } + const char *displayName = XDisplayName(displayname); if (!(dpy = XOpenDisplay(displayname))) { // FIXME: Why not vlog.error(...)? fprintf(stderr,"%s: Unable to open display \"%s\"\r\n", - programName, XDisplayName(displayname)); + programName, displayName); exit(1); } + rfb::UnixPasswordValidator::setDisplayName(displayName); signal(SIGHUP, CleanupSignalHandler); signal(SIGINT, CleanupSignalHandler); signal(SIGTERM, CleanupSignalHandler); - std::list<SocketListener*> listeners; + std::list<network::SocketListener*> listeners; try { TXWindow::init(dpy,"x0vncserver"); @@ -331,7 +361,9 @@ int main(int argc, char** argv) } XDesktop desktop(dpy, &geo); - VNCServerST server(desktopName, &desktop); + rfb::VNCServerST server(desktopName, &desktop); + + FileTcpFilter fileTcpFilter(hostsFile); if (createSystemdListeners(&listeners) > 0) { // When systemd is in charge of listeners, do not listen to anything else @@ -361,9 +393,8 @@ int main(int argc, char** argv) (int)rfbport); } - FileTcpFilter fileTcpFilter(hostsFile); if (strlen(hostsFile) != 0) - for (SocketListener* listener : listeners) + for (network::SocketListener* listener : listeners) listener->setFilter(&fileTcpFilter); } @@ -378,8 +409,8 @@ int main(int argc, char** argv) int wait_ms, nextTimeout; struct timeval tv; fd_set rfds, wfds; - std::list<Socket*> sockets; - std::list<Socket*>::iterator i; + std::list<network::Socket*> sockets; + std::list<network::Socket*>::iterator i; // Process any incoming X events TXWindow::handleXEvents(dpy); @@ -388,21 +419,16 @@ int main(int argc, char** argv) FD_ZERO(&wfds); FD_SET(ConnectionNumber(dpy), &rfds); - for (SocketListener* listener : listeners) + for (network::SocketListener* listener : listeners) FD_SET(listener->getFd(), &rfds); server.getSockets(&sockets); int clients_connected = 0; for (i = sockets.begin(); i != sockets.end(); i++) { - if ((*i)->isShutdown()) { - server.removeSocket(*i); - delete (*i); - } else { - FD_SET((*i)->getFd(), &rfds); - if ((*i)->outStream().hasBufferedData()) - FD_SET((*i)->getFd(), &wfds); - clients_connected++; - } + FD_SET((*i)->getFd(), &rfds); + if ((*i)->outStream().hasBufferedData()) + FD_SET((*i)->getFd(), &wfds); + clients_connected++; } if (!clients_connected) @@ -418,7 +444,7 @@ int main(int argc, char** argv) } // Trigger timers and check when the next will expire - nextTimeout = Timer::checkTimeouts(); + nextTimeout = core::Timer::checkTimeouts(); if (nextTimeout >= 0 && (wait_ms == -1 || nextTimeout < wait_ms)) wait_ms = nextTimeout; @@ -436,14 +462,14 @@ int main(int argc, char** argv) vlog.debug("Interrupted select() system call"); continue; } else { - throw rdr::socket_error("select", errno); + throw core::socket_error("select", errno); } } // Accept new VNC connections - for (SocketListener* listener : listeners) { + for (network::SocketListener* listener : listeners) { if (FD_ISSET(listener->getFd(), &rfds)) { - Socket* sock = listener->accept(); + network::Socket* sock = listener->accept(); if (sock) { server.addSocket(sock); } else { @@ -452,7 +478,7 @@ int main(int argc, char** argv) } } - Timer::checkTimeouts(); + core::Timer::checkTimeouts(); // Client list could have been changed. server.getSockets(&sockets); @@ -467,6 +493,29 @@ int main(int argc, char** argv) server.processSocketReadEvent(*i); if (FD_ISSET((*i)->getFd(), &wfds)) server.processSocketWriteEvent(*i); + + // Do a graceful close by waiting for the peer to close their + // end + if ((*i)->isShutdown()) { + bool done; + + done = false; + while (true) { + try { + (*i)->inStream().skip((*i)->inStream().avail()); + if (!(*i)->inStream().hasData(1)) + break; + } catch (std::exception&) { + done = true; + break; + } + } + + if (done) { + server.removeSocket(*i); + delete (*i); + } + } } if (desktop.isRunning() && sched.goodTimeToPoll()) { @@ -483,7 +532,7 @@ int main(int argc, char** argv) TXWindow::handleXEvents(dpy); // Run listener destructors; remove UNIX sockets etc - for (SocketListener* listener : listeners) + for (network::SocketListener* listener : listeners) delete listener; vlog.info("Terminated"); diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man index ce4bd6a9..f1a28f54 100644 --- a/unix/x0vncserver/x0vncserver.man +++ b/unix/x0vncserver/x0vncserver.man @@ -20,7 +20,7 @@ will fall back to polling the screen for changes. .SH OPTIONS .B x0vncserver interprets the command line as a list of parameters with optional values. -Running \fBx0vncserver -h\fP will show a list of all valid parameters with +Running \fBx0vncserver \-h\fP will show a list of all valid parameters with short descriptions. All parameters are optional, but normally you would have to use the \fBPasswordFile\fP parameter (see its description below). .PP @@ -47,47 +47,76 @@ arbitrary. .SH PARAMETERS .TP -.B \-desktop \fIdesktop-name\fP -Each desktop has a name which may be displayed by the viewer. It defaults to -"<user>@<hostname>". +.B \-AcceptKeyEvents +Accept key press and release events from clients. Default is on. . .TP -.B \-display \fIdisplay\fP -The X display name. If not specified, it defaults to the value of the -DISPLAY environment variable. +.B \-AcceptPointerEvents +Accept pointer movement and button events from clients. Default is on. . .TP -.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"). -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. +.B \-AcceptSetDesktopSize +Accept requests to resize the size of the desktop. Default is on. . .TP -.B \-UseIPv4 -Use IPv4 for incoming and outgoing connections. Default is on. +.B \-AlwaysShared +Always treat incoming connections as shared, regardless of the client-specified +setting. Default is off. . .TP -.B \-UseIPv6 -Use IPv6 for incoming and outgoing connections. Default is on. +.B \-BlacklistThreshold \fIcount\fP +The number of unauthenticated connection attempts allowed from any individual +host before that host is black-listed. Default is 5. . .TP -.B \-rfbunixpath \fIpath\fP -Specifies the path of a Unix domain socket on which x0vncserver listens for -connections from viewers. Default is to not listen to any Unix domain -socket. +.B \-BlacklistTimeout \fIseconds\fP +The initial timeout applied when a host is first black-listed. The host +cannot re-attempt a connection until the timeout expires. Default is 10. . .TP -.B \-rfbunixmode \fImode\fP -Specifies the mode of the Unix domain socket. The default is 0600. +.B \-CompareFB \fImode\fP +Perform pixel comparison on framebuffer to reduce unnecessary updates. Can +be either \fB0\fP (off), \fB1\fP (always) or \fB2\fP (auto). Default is +\fB2\fP. . .TP -.B \-Log \fIlogname\fP:\fIdest\fP:\fIlevel\fP -Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP, -\fBstdout\fP or \fBsyslog\fP, and \fIlevel\fP is between 0 and 100, 100 meaning -most verbose output. \fIlogname\fP is usually \fB*\fP meaning all, but you can -target a specific source file if you know the name of its "LogWriter". Default -is \fB*:stderr:30\fP. +.B \-desktop \fIdesktop-name\fP +Each desktop has a name which may be displayed by the viewer. It defaults to +"<user>@<hostname>". +. +.TP +.B \-DisconnectClients +Disconnect existing clients if an incoming connection is non-shared. Default is +on. If \fBDisconnectClients\fP is false, then a new non-shared connection will +be refused while there is a client active. When combined with +\fBNeverShared\fP this means only one client is allowed at a time. +. +.TP +.B \-display \fIdisplay\fP +The X display name. If not specified, it defaults to the value of the +DISPLAY environment variable. +. +.TP +.B \-FrameRate \fIfps\fP +The maximum number of updates per second sent to each client. If the screen +updates any faster then those changes will be aggregated and sent in a single +update to the client. Note that this only controls the maximum rate and a +client may get a lower rate when resources are limited. Default is \fB60\fP. +. +.TP +.B \-Geometry \fIgeometry\fP +This option specifies the screen area that will be shown to VNC clients. The +format is +.B \fIwidth\fPx\fIheight\fP+\fIxoffset\fP+\fIyoffset\fP +, where `+' signs can be replaced with `\-' signs to specify offsets from the +right and/or from the bottom of the screen. Offsets are optional, +0+0 is +assumed by default (top left corner). If the argument is empty, full screen +is shown to VNC clients (this is the default). +. +.TP +.B \-GnuTLSPriority \fIpriority\fP +GnuTLS priority string that controls the TLS session’s handshake algorithms. +See the GnuTLS manual for possible values. Default is \fBNORMAL\fP. . .TP .B \-HostsFile \fIfilename\fP @@ -102,124 +131,108 @@ include only an action sign (+, - or ?) will match any IP address. Default is to accept connections from any IP address. . .TP -.B \-SecurityTypes \fIsec-types\fP -Specify which security scheme to use for incoming connections. Valid values -are a comma separated list of \fBNone\fP, \fBVncAuth\fP, \fBPlain\fP, -\fBTLSNone\fP, \fBTLSVnc\fP, \fBTLSPlain\fP, \fBX509None\fP, \fBX509Vnc\fP, -\fBX509Plain\fP, \fBRA2\fP, \fBRA2ne\fP, \fBRA2_256\fP and \fBRA2ne_256\fP. -Default is \fBTLSVnc,VncAuth\fP. -. -.TP -.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP -Password file for VNC authentication. There is no default, you should -specify the password file explicitly. Password file should be created with -the \fBvncpasswd\fP(1) utility. The file is accessed each time a connection -comes in, so it can be changed on the fly. -. -.TP -.B \-Password \fIpassword\fP -Obfuscated binary encoding of the password which clients must supply to -access the server. Using this parameter is insecure, use \fBPasswordFile\fP -parameter instead. -. -.TP -.B \-PlainUsers \fIuser-list\fP -A comma separated list of user names that are allowed to authenticate via -any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP -to allow any user to authenticate using this security type. Specify \fB%u\fP -to allow the user of the server process. Default is to deny all users. -. -.TP -.B \-pam_service \fIname\fP, \-PAMService \fIname\fP -PAM service name to use when authentication users using any of the "Plain" -security types. Default is \fBvnc\fP. +.B \-IdleTimeout \fIseconds\fP +The number of seconds after which an idle VNC connection will be dropped. +Default is 0, which means that idle connections will never be dropped. . .TP -.B \-X509Cert \fIpath\fP -Path to a X509 certificate in PEM format to be used for all X509 based -security types (X509None, X509Vnc, etc.). +.B \-ImprovedHextile +Use improved compression algorithm for Hextile encoding which achieves better +compression ratios by the cost of using slightly more CPU time. Default is +on. . .TP -.B \-X509Key \fIpath\fP -Private key counter part to the certificate given in \fBX509Cert\fP. Must -also be in PEM format. +.B \-interface \fIIP address\fP +Listen on interface. By default x0vncserver listens on all available interfaces. . .TP -.B \-GnuTLSPriority \fIpriority\fP -GnuTLS priority string that controls the TLS session’s handshake algorithms. -See the GnuTLS manual for possible values. Default is \fBNORMAL\fP. +.B \-localhost +Only allow connections from the same machine. Useful if you use SSH and want to +stop non-SSH connections from any other hosts. . .TP -.B \-RSAKey \fIpath\fP -Path to the RSA key for the RSA-AES security types (\fBRA2\fP, \fBRA2ne\fP, -\fBRA2_256\fP and \fBRA2ne_256\fP) in PEM format. +.B \-Log \fIlogname\fP:\fIdest\fP:\fIlevel\fP[, ...] +Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP, +\fBstdout\fP or \fBsyslog\fP, and \fIlevel\fP is between 0 and 100, 100 meaning +most verbose output. \fIlogname\fP is usually \fB*\fP meaning all, but you can +target a specific source file if you know the name of its "LogWriter". Default +is \fB*:stderr:30\fP. . .TP -.B \-RequireUsername -Require username for the RSA-AES security types. Default is off. +.B \-MaxConnectionTime \fIseconds\fP +Terminate when a client has been connected for \fIN\fP seconds. Default is +0. . .TP -.B \-UseBlacklist -Temporarily reject connections from a host if it repeatedly fails to -authenticate. Default is on. +.B \-MaxDisconnectionTime \fIseconds\fP +Terminate when no client has been connected for \fIN\fP seconds. Default is +0. . .TP -.B \-BlacklistThreshold \fIcount\fP -The number of unauthenticated connection attempts allowed from any individual -host before that host is black-listed. Default is 5. +.B \-MaxIdleTime \fIseconds\fP +Terminate after \fIN\fP seconds of user inactivity. Default is 0. . .TP -.B \-BlacklistTimeout \fIseconds\fP -The initial timeout applied when a host is first black-listed. The host -cannot re-attempt a connection until the timeout expires. Default is 10. +.B \-MaxProcessorUsage \fIpercent\fP +Maximum percentage of CPU time to be consumed when polling the +screen. Default is 35. . .TP -.B \-QueryConnect -Prompts the user of the desktop to explicitly accept or reject incoming -connections. Default is off. +.B \-NeverShared +Never treat incoming connections as shared, regardless of the client-specified +setting. Default is off. . .TP -.B \-QueryConnectTimeout \fIseconds\fP -Number of seconds to show the Accept connection dialog before rejecting the -connection. Default is \fB10\fP. +.B \-pam_service \fIname\fP, \-PAMService \fIname\fP +PAM service name to use when authentication users using any of the "Plain" +security types. Default is \fBvnc\fP. . .TP -.B \-localhost -Only allow connections from the same machine. Useful if you use SSH and want to -stop non-SSH connections from any other hosts. +.B \-Password \fIpassword\fP +Obfuscated binary encoding of the password which clients must supply to +access the server. Using this parameter is insecure, use \fBPasswordFile\fP +parameter instead. . .TP -.B \-interface \fIIP address\fP -Listen on interface. By default x0vncserver listens on all available interfaces. +.B \-PasswordFile \fIpasswd-file\fP, \-rfbauth \fIpasswd-file\fP +Password file for VNC authentication. There is no default, you should +specify the password file explicitly. Password file should be created with +the \fBvncpasswd\fP(1) utility. The file is accessed each time a connection +comes in, so it can be changed on the fly. . .TP -.B \-AlwaysShared -Always treat incoming connections as shared, regardless of the client-specified -setting. Default is off. +.B \-PlainUsers \fIuser-list\fP +A comma separated list of user names that are allowed to authenticate via +any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP +to allow any user to authenticate using this security type. Specify \fB%u\fP +to allow the user of the server process. Default is to deny all users. . .TP -.B \-NeverShared -Never treat incoming connections as shared, regardless of the client-specified -setting. Default is off. +.B \-PollingCycle \fImilliseconds\fP +Milliseconds per one polling cycle. Actual interval may be dynamically +adjusted to satisfy \fBMaxProcessorUsage\fP setting. Default is 30. . .TP -.B \-DisconnectClients -Disconnect existing clients if an incoming connection is non-shared. Default is -on. If \fBDisconnectClients\fP is false, then a new non-shared connection will -be refused while there is a client active. When combined with -\fBNeverShared\fP this means only one client is allowed at a time. +.B \-Protocol3.3 +Always use protocol version 3.3 for backwards compatibility with badly-behaved +clients. Default is off. . .TP -.B \-AcceptKeyEvents -Accept key press and release events from clients. Default is on. +.B \-QueryConnect +Prompts the user of the desktop to explicitly accept or reject incoming +connections. Default is off. . .TP -.B \-AcceptPointerEvents -Accept pointer movement and button events from clients. Default is on. +.B \-QueryConnectTimeout \fIseconds\fP +Number of seconds to show the Accept connection dialog before rejecting the +connection. Default is \fB10\fP. . .TP -.B \-AcceptSetDesktopSize -Accept requests to resize the size of the desktop. Default is on. +.B \-RawKeyboard +Send keyboard events straight through and avoid mapping them to the current +keyboard layout. This effectively makes the keyboard behave according to the +layout configured on the server instead of the layout configured on the +client. Default is off. . .TP .B \-AcceptCutText @@ -259,79 +272,66 @@ RemapKeys=0x22<>0x40 .RE . .TP -.B \-RawKeyboard -Send keyboard events straight through and avoid mapping them to the current -keyboard layout. This effectively makes the keyboard behave according to the -layout configured on the server instead of the layout configured on the -client. Default is off. -. -.TP -.B \-Protocol3.3 -Always use protocol version 3.3 for backwards compatibility with badly-behaved -clients. Default is off. +.B \-RequireUsername +Require username for the RSA-AES security types. Default is off. . .TP -.B \-Geometry \fIgeometry\fP -This option specifies the screen area that will be shown to VNC clients. The -format is -.B \fIwidth\fPx\fIheight\fP+\fIxoffset\fP+\fIyoffset\fP -, where `+' signs can be replaced with `\-' signs to specify offsets from the -right and/or from the bottom of the screen. Offsets are optional, +0+0 is -assumed by default (top left corner). If the argument is empty, full screen -is shown to VNC clients (this is the default). +.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"). +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 \-MaxProcessorUsage \fIpercent\fP -Maximum percentage of CPU time to be consumed when polling the -screen. Default is 35. +.B \-rfbunixmode \fImode\fP +Specifies the mode of the Unix domain socket. The default is 0600. . .TP -.B \-PollingCycle \fImilliseconds\fP -Milliseconds per one polling cycle. Actual interval may be dynamically -adjusted to satisfy \fBMaxProcessorUsage\fP setting. Default is 30. +.B \-rfbunixpath \fIpath\fP +Specifies the path of a Unix domain socket on which x0vncserver listens for +connections from viewers. Default is to not listen to any Unix domain +socket. . .TP -.B \-FrameRate \fIfps\fP -The maximum number of updates per second sent to each client. If the screen -updates any faster then those changes will be aggregated and sent in a single -update to the client. Note that this only controls the maximum rate and a -client may get a lower rate when resources are limited. Default is \fB60\fP. +.B \-RSAKey \fIpath\fP +Path to the RSA key for the RSA-AES security types (\fBRA2\fP, \fBRA2ne\fP, +\fBRA2_256\fP and \fBRA2ne_256\fP) in PEM format. . .TP -.B \-CompareFB \fImode\fP -Perform pixel comparison on framebuffer to reduce unnecessary updates. Can -be either \fB0\fP (off), \fB1\fP (always) or \fB2\fP (auto). Default is -\fB2\fP. +.B \-SecurityTypes \fIsec-types\fP +Specify which security scheme to use for incoming connections. Valid values +are a comma separated list of \fBNone\fP, \fBVncAuth\fP, \fBPlain\fP, +\fBTLSNone\fP, \fBTLSVnc\fP, \fBTLSPlain\fP, \fBX509None\fP, \fBX509Vnc\fP, +\fBX509Plain\fP, \fBRA2\fP, \fBRA2ne\fP, \fBRA2_256\fP and \fBRA2ne_256\fP. +Default is \fBTLSVnc,VncAuth\fP. . .TP -.B \-UseSHM -Use MIT-SHM extension if available. Using that extension accelerates reading -the screen. Default is on. +.B \-UseBlacklist +Temporarily reject connections from a host if it repeatedly fails to +authenticate. Default is on. . .TP -.B \-ImprovedHextile -Use improved compression algorithm for Hextile encoding which achieves better -compression ratios by the cost of using slightly more CPU time. Default is -on. +.B \-UseIPv4 +Use IPv4 for incoming and outgoing connections. Default is on. . .TP -.B \-IdleTimeout \fIseconds\fP -The number of seconds after which an idle VNC connection will be dropped. -Default is 0, which means that idle connections will never be dropped. +.B \-UseIPv6 +Use IPv6 for incoming and outgoing connections. Default is on. . .TP -.B \-MaxDisconnectionTime \fIseconds\fP -Terminate when no client has been connected for \fIN\fP seconds. Default is -0. +.B \-UseSHM +Use MIT-SHM extension if available. Using that extension accelerates reading +the screen. Default is on. . .TP -.B \-MaxConnectionTime \fIseconds\fP -Terminate when a client has been connected for \fIN\fP seconds. Default is -0. +.B \-X509Cert \fIpath\fP +Path to a X509 certificate in PEM format to be used for all X509 based +security types (X509None, X509Vnc, etc.). . .TP -.B \-MaxIdleTime \fIseconds\fP -Terminate after \fIN\fP seconds of user inactivity. Default is 0. +.B \-X509Key \fIpath\fP +Private key counter part to the certificate given in \fBX509Cert\fP. Must +also be in PEM format. .SH SEE ALSO .BR Xvnc (1), |