summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libvncclient/rfbproto.c45
-rw-r--r--libvncclient/vncviewer.c27
-rw-r--r--rfb/rfbclient.h5
3 files changed, 76 insertions, 1 deletions
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 83cfbf9..8aa6348 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -415,6 +415,51 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
return SetNonBlocking(client->sock);
}
+/*
+ * ConnectToRFBRepeater.
+ */
+
+rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort)
+{
+ unsigned int host;
+ rfbProtocolVersionMsg pv;
+ int major,minor;
+ char tmphost[250];
+
+ if (!StringToIPAddr(repeaterHost, &host)) {
+ rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost);
+ return FALSE;
+ }
+
+ client->sock = ConnectClientToTcpAddr(host, repeaterPort);
+
+ if (client->sock < 0) {
+ rfbClientLog("Unable to connect to VNC repeater\n");
+ return FALSE;
+ }
+
+ if (!SetNonBlocking(client->sock))
+ return FALSE;
+
+ if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg))
+ return FALSE;
+ pv[sz_rfbProtocolVersionMsg] = 0;
+
+ /* UltraVNC repeater always report version 000.000 to identify itself */
+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) {
+ rfbClientLog("Not a valid VNC repeater (%s)\n",pv);
+ return FALSE;
+ }
+
+ rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor);
+
+ snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort);
+ if (!WriteToRFBServer(client, tmphost, sizeof(tmphost)))
+ return FALSE;
+
+ return TRUE;
+}
+
extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key);
diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c
index 111a7f6..fa150cd 100644
--- a/libvncclient/vncviewer.c
+++ b/libvncclient/vncviewer.c
@@ -119,6 +119,9 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client->programName="";
client->serverHost=strdup("");
client->serverPort=5900;
+
+ client->destHost = NULL;
+ client->destPort = 5900;
client->CurrentKeyboardLedState = 0;
client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
@@ -202,8 +205,15 @@ static rfbBool rfbInitConnection(rfbClient* client)
given VNC server */
if (!client->listenSpecified) {
- if (!client->serverHost || !ConnectToRFBServer(client,client->serverHost,client->serverPort))
+ if (!client->serverHost)
return FALSE;
+ if (client->destHost) {
+ if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort))
+ return FALSE;
+ } else {
+ if (!ConnectToRFBServer(client,client->serverHost,client->serverPort))
+ return FALSE;
+ }
}
/* Initialise the VNC connection, including reading the password */
@@ -278,6 +288,19 @@ rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) {
} else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) {
client->appData.scaleSetting = atoi(argv[i+1]);
j+=2;
+ } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) {
+ char* colon=strchr(argv[i+1],':');
+
+ if(client->destHost)
+ free(client->destHost);
+ client->destPort = 5900;
+
+ client->destHost = strdup(argv[i+1]);
+ if(colon) {
+ client->destHost[(int)(colon-argv[i+1])] = '\0';
+ client->destPort = atoi(colon+1);
+ }
+ j+=2;
} else {
char* colon=strchr(argv[i],':');
@@ -342,6 +365,8 @@ void rfbClientCleanup(rfbClient* client) {
close(client->listenSock);
free(client->desktopName);
free(client->serverHost);
+ if (client->destHost)
+ free(client->destHost);
if (client->clientAuthSchemes)
free(client->clientAuthSchemes);
free(client);
diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h
index a82ea22..bc4ec14 100644
--- a/rfb/rfbclient.h
+++ b/rfb/rfbclient.h
@@ -309,6 +309,10 @@ typedef struct _rfbClient {
/* The 0-terminated security types supported by the client.
* Set by function SetClientAuthSchemes() */
uint32_t *clientAuthSchemes;
+
+ /* When the server is a repeater, this specifies the final destination */
+ char *destHost;
+ int destPort;
} rfbClient;
/* cursor.c */
@@ -326,6 +330,7 @@ extern rfbBool rfbEnableClientLogging;
typedef void (*rfbClientLogProc)(const char *format, ...);
extern rfbClientLogProc rfbClientLog,rfbClientErr;
extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port);
+extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort);
extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size);
extern rfbBool InitialiseRFBConnection(rfbClient* client);
extern rfbBool SetFormatAndEncodings(rfbClient* client);