Skip to content

Commit 722c7f8

Browse files
committed
libvncserver: introduce rfbUltraVNCRepeaterMode2Connection()
This function is used to make a connection to an UltraVNC repeater in mode 2. It connects to the given UltraVNC mode 2 repeater host and sends the given repeater id, see https://uvnc.com/pchelpware/sc/repeater.html
1 parent 80fdcbd commit 722c7f8

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

include/rfb/rfb.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,8 @@ typedef struct _rfbClientRec {
713713
#endif
714714
/** Destination port in case of an outgoing/reverse connection */
715715
int destPort;
716+
/** ID on repeater in case of an UltraVNC mode 2 repeater connection */
717+
char *repeaterId;
716718
} rfbClientRec, *rfbClientPtr;
717719

718720
/**
@@ -803,6 +805,19 @@ extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,rfbSocket sock);
803805
extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,rfbSocket sock);
804806
extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen);
805807
extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port);
808+
/**
809+
* @brief Make a connection to an UltraVNC repeater in mode 2
810+
*
811+
* This function connects to the given UltraVNC mode 2 repeater host and sends
812+
* the given repeater id, see https://uvnc.com/pchelpware/sc/repeater.html
813+
*
814+
* @param rfbScreen The VNC server handle.
815+
* @param repeaterHost The hostname of the repeater to connect to.
816+
* @param repeaterPort The port of the repeater to connect to.
817+
* @param repeaterId The id on the repeater without the 'ID:' prefix, must be parseable to long for UltraVNC compatibility.
818+
* @return A valid client pointer (also when there is no viewer counterpart yet on the repeater), NULL on failure.
819+
*/
820+
extern rfbClientPtr rfbUltraVNCRepeaterMode2Connection(rfbScreenInfoPtr rfbScreen, char *repeaterHost, int repeaterPort, const char* repeaterId);
806821
extern void rfbClientConnectionGone(rfbClientPtr cl);
807822
extern void rfbProcessClientMessage(rfbClientPtr cl);
808823
extern void rfbClientConnFailed(rfbClientPtr cl, const char *reason);

src/libvncserver/rfbserver.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,60 @@ rfbReverseConnection(rfbScreenInfoPtr rfbScreen,
280280
}
281281

282282

283+
rfbClientPtr rfbUltraVNCRepeaterMode2Connection(rfbScreenInfoPtr rfbScreen,
284+
char *repeaterHost,
285+
int repeaterPort,
286+
const char* repeaterId)
287+
{
288+
rfbSocket sock;
289+
rfbClientPtr cl;
290+
// Using 250 here as this is what UltraVNC repeaters expect to read in one
291+
// go. If we send less bytes as an id, the repeater will read our
292+
// rfbProtocolVersion message into its id buffer, thus rfbProtocolVersion
293+
// will never reach the viewer.
294+
char id[250];
295+
rfbLog("rfbUltraVNCRepeaterMode2Connection: connecting to repeater %s:%d\n", repeaterHost, repeaterPort);
296+
297+
if ((sock = rfbConnect(rfbScreen, repeaterHost, repeaterPort)) == RFB_INVALID_SOCKET) {
298+
return NULL;
299+
}
300+
301+
memset(id, 0, sizeof(id));
302+
if (snprintf(id, sizeof(id), "ID:%s", repeaterId) >= (int)sizeof(id)) {
303+
/* truncated! */
304+
rfbErr("rfbUltraVNCRepeaterMode2Connection: error, given ID is too long.\n");
305+
return NULL;
306+
}
307+
308+
if (send(sock, id, sizeof(id), 0) != sizeof(id)) {
309+
rfbErr("rfbUltraVNCRepeaterMode2Connection: sending repeater ID failed\n");
310+
return NULL;
311+
}
312+
313+
cl = rfbNewClient(rfbScreen, sock);
314+
if (!cl) {
315+
rfbErr("rfbUltraVNCRepeaterMode2Connection: new client failed\n");
316+
return NULL;
317+
}
318+
319+
cl->reverseConnection = 0;
320+
321+
// Save repeater id without the 'ID:' prefix
322+
cl->repeaterId = malloc(sizeof(id) - 3);
323+
if(cl->repeaterId) {
324+
memcpy(cl->repeaterId, id + 3, sizeof(id) - 3);
325+
} else {
326+
rfbErr("rfbUltraVNCRepeaterMode2Connection: could not allocate memory for saving repeater id\n");
327+
}
328+
329+
if (!cl->onHold) {
330+
rfbStartOnHoldClient(cl);
331+
}
332+
333+
return cl;
334+
}
335+
336+
283337
void
284338
rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_)
285339
{
@@ -610,7 +664,8 @@ rfbClientConnectionGone(rfbClientPtr cl)
610664

611665
rfbLog("Client %s gone\n",cl->host);
612666
free(cl->host);
613-
667+
free(cl->repeaterId);
668+
614669
if (cl->wsctx != NULL){
615670
free(cl->wsctx);
616671
cl->wsctx = NULL;

0 commit comments

Comments
 (0)