From 8ac4b30fe93c7bd0ce54e0d5caebce82151393bd Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Wed, 23 Jan 2013 13:55:46 +0000 Subject: [PATCH] Re-add the "-via" parameter support on UNIX platforms. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@5032 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- vncviewer/ServerDialog.cxx | 15 +++--- vncviewer/ServerDialog.h | 2 +- vncviewer/parameters.cxx | 4 ++ vncviewer/parameters.h | 4 ++ vncviewer/vncviewer.cxx | 94 ++++++++++++++++++++++++++++++++++++-- vncviewer/vncviewer.h | 2 + 6 files changed, 107 insertions(+), 14 deletions(-) diff --git a/vncviewer/ServerDialog.cxx b/vncviewer/ServerDialog.cxx index 25a010a1..4cf35353 100644 --- a/vncviewer/ServerDialog.cxx +++ b/vncviewer/ServerDialog.cxx @@ -107,23 +107,22 @@ ServerDialog::~ServerDialog() } -const char *ServerDialog::run(const char* servername) +void ServerDialog::run(const char* servername, char *newservername) { ServerDialog dialog; - static char buffer[256]; dialog.serverName->value(servername); dialog.show(); while (dialog.shown()) Fl::wait(); - if (dialog.serverName->value() == NULL) - return NULL; - - strncpy(buffer, dialog.serverName->value(), sizeof(buffer)); - buffer[sizeof(buffer)-1] = '\0'; + if (dialog.serverName->value() == NULL) { + newservername[0] = '\0'; + return; + } - return buffer; + strncpy(newservername, dialog.serverName->value(), VNCSERVERNAMELEN); + newservername[VNCSERVERNAMELEN - 1] = '\0'; } void ServerDialog::handleOptions(Fl_Widget *widget, void *data) diff --git a/vncviewer/ServerDialog.h b/vncviewer/ServerDialog.h index 402d8ba8..e023659c 100644 --- a/vncviewer/ServerDialog.h +++ b/vncviewer/ServerDialog.h @@ -29,7 +29,7 @@ protected: ~ServerDialog(); public: - static const char *run(const char* servername); + static void run(const char* servername, char *newservername); protected: static void handleOptions(Fl_Widget *widget, void *data); diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx index 9a3bcd25..d386bd45 100644 --- a/vncviewer/parameters.cxx +++ b/vncviewer/parameters.cxx @@ -133,6 +133,10 @@ BoolParameter fullscreenSystemKeys("FullscreenSystemKeys", "to the server when in full screen mode.", true); +#ifndef WIN32 +StringParameter via("via", "Gateway to tunnel via", ""); +#endif + const char* IDENTIFIER_STRING = "TigerVNC Configuration file Version 1.0"; VoidParameter* parameterArray[] = { diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h index d7144a4b..2b4c0390 100644 --- a/vncviewer/parameters.h +++ b/vncviewer/parameters.h @@ -60,6 +60,10 @@ extern rfb::StringParameter menuKey; extern rfb::BoolParameter fullscreenSystemKeys; +#ifndef WIN32 +extern rfb::StringParameter via; +#endif + void saveViewerParameters(const char *filename, const char *servername=NULL); char* loadViewerParameters(const char *filename); diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx index a512213b..ace1ce62 100644 --- a/vncviewer/vncviewer.cxx +++ b/vncviewer/vncviewer.cxx @@ -58,6 +58,7 @@ #include "CConn.h" #include "ServerDialog.h" #include "UserDialog.h" +#include "vncviewer.h" #ifdef WIN32 #include "resource.h" @@ -76,6 +77,8 @@ static const char aboutText[] = N_("TigerVNC Viewer %d-bit v%s (%s)\n" "See http://www.tigervnc.org for information on TigerVNC."); extern const char* buildTime; +char vncServerName[VNCSERVERNAMELEN] = { '\0' }; + static bool exitMainloop = false; static const char *exitError = NULL; @@ -267,9 +270,84 @@ static void usage(const char *programName) exit(1); } +#ifndef WIN32 +static int +interpretViaParam(char *remoteHost, int *remotePort, int localPort) +{ + const int SERVER_PORT_OFFSET = 5900; + char *pos = strchr(vncServerName, ':'); + if (pos == NULL) + *remotePort = SERVER_PORT_OFFSET; + else { + int portOffset = SERVER_PORT_OFFSET; + size_t len; + *pos++ = '\0'; + len = strlen(pos); + if (*pos == ':') { + /* Two colons is an absolute port number, not an offset. */ + pos++; + len--; + portOffset = 0; + } + if (!len || strspn (pos, "-0123456789") != len ) + return 1; + *remotePort = atoi(pos) + portOffset; + } + + if (*vncServerName != '\0') + strncpy(remoteHost, vncServerName, VNCSERVERNAMELEN); + else + strncpy(remoteHost, "localhost", VNCSERVERNAMELEN); + + remoteHost[VNCSERVERNAMELEN - 1] = '\0'; + + snprintf(vncServerName, VNCSERVERNAMELEN, "localhost::%d", localPort); + vncServerName[VNCSERVERNAMELEN - 1] = '\0'; + vlog.error(vncServerName); + + return 0; +} + +static void +createTunnel(const char *gatewayHost, const char *remoteHost, + int remotePort, int localPort) +{ + char *cmd = getenv("VNC_VIA_CMD"); + char *percent; + char lport[10], rport[10]; + sprintf(lport, "%d", localPort); + sprintf(rport, "%d", remotePort); + setenv("G", gatewayHost, 1); + setenv("H", remoteHost, 1); + setenv("R", rport, 1); + setenv("L", lport, 1); + vlog.error("%s, %s, %d, %d", gatewayHost, remoteHost, rport, lport); + if (!cmd) + cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20"; + /* Compatibility with TigerVNC's method. */ + while ((percent = strchr(cmd, '%')) != NULL) + *percent = '$'; + system(cmd); +} + +static int mktunnel() +{ + const char *gatewayHost; + char remoteHost[VNCSERVERNAMELEN]; + int localPort = findFreeTcpPort(); + int remotePort; + + gatewayHost = strDup(via.getValueStr()); + if (interpretViaParam(remoteHost, &remotePort, localPort) != 0) + return 1; + createTunnel(gatewayHost, remoteHost, remotePort, localPort); + + return 0; +} +#endif /* !WIN32 */ + int main(int argc, char** argv) { - const char* vncServerName = NULL; UserDialog dlg; setlocale(LC_ALL, ""); @@ -332,7 +410,8 @@ int main(int argc, char** argv) usage(argv[0]); } - vncServerName = argv[i]; + strncpy(vncServerName, argv[i], VNCSERVERNAMELEN); + vncServerName[VNCSERVERNAMELEN - 1] = '\0'; } if (!::autoSelect.hasBeenSet()) { @@ -363,12 +442,17 @@ int main(int argc, char** argv) CSecurityTLS::msg = &dlg; #endif - if (vncServerName == NULL) { - vncServerName = ServerDialog::run(defaultServerName); - if ((vncServerName == NULL) || (vncServerName[0] == '\0')) + if (vncServerName[0] == '\0') { + ServerDialog::run(defaultServerName, vncServerName); + if (vncServerName[0] == '\0') return 1; } +#ifndef WIN32 + if (strlen (via.getValueStr()) > 0 && mktunnel() != 0) + usage(argv[0]); +#endif + CConn *cc = new CConn(vncServerName); while (!exitMainloop) { diff --git a/vncviewer/vncviewer.h b/vncviewer/vncviewer.h index 443dbea3..089fb270 100644 --- a/vncviewer/vncviewer.h +++ b/vncviewer/vncviewer.h @@ -19,6 +19,8 @@ #ifndef __VNCVIEWER_H__ #define __VNCVIEWER_H__ +#define VNCSERVERNAMELEN 64 + void exit_vncviewer(const char *error = NULL); void about_vncviewer(); -- 2.39.5