aboutsummaryrefslogtreecommitdiffstats
path: root/unix/x0vncserver/x0vncserver.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unix/x0vncserver/x0vncserver.cxx')
-rw-r--r--unix/x0vncserver/x0vncserver.cxx195
1 files changed, 122 insertions, 73 deletions
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");