Skip to content

Commit fca39ff

Browse files
committed
Added handshakeType to allow increase wait for ws/wss handshake.
For long latency clients then may not be able to deliver the websocket handshake before we fall back to regular the RFB protocol. So to not introduce a multisecond delay for all conenction a handshakeType setting is introduced to tell which type of handshake we expect. The problem is that a RFB client will be quiet "forever" until the server sends it's signature. On the other hand a websocket client will send it's HTTP websocket handshake immediately. Before the server for sure know the the type of client the connect procedure cannot continue. There is no other option than to wait for some amount of time when the client type is auto detected.
1 parent 1c51df2 commit fca39ff

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

libvncserver/websockets.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ Connection: Upgrade\r\n\
7474
Sec-WebSocket-Accept: %s\r\n\
7575
\r\n"
7676

77-
#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100
78-
#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 100
77+
#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 500
7978
#define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096
8079

8180
#if defined(__linux__) && defined(NEED_TIMEVAL)
@@ -119,8 +118,17 @@ webSocketsCheck (rfbClientPtr cl)
119118
char bbuf[4], *scheme;
120119
int ret;
121120

122-
ret = rfbPeekExactTimeout(cl, bbuf, 4,
123-
WEBSOCKETS_CLIENT_CONNECT_WAIT_MS);
121+
int timeout = WEBSOCKETS_CLIENT_CONNECT_WAIT_MS;
122+
switch (cl->screen->handshake_type) {
123+
case RFB_HANDSHAKE_AUTO:
124+
timeout = cl->screen->maxClientWait ? cl->screen->maxClientWait : rfbMaxClientWait;
125+
break;
126+
case RFB_HANDSHAKE_WEBSOCKET:
127+
timeout = WEBSOCKETS_CLIENT_CONNECT_WAIT_MS;
128+
break;
129+
}
130+
131+
ret = rfbPeekExactTimeout(cl, bbuf, 4, timeout);
124132
if ((ret < 0) && (errno == ETIMEDOUT)) {
125133
rfbLog("Normal socket connection\n");
126134
return TRUE;
@@ -138,7 +146,7 @@ webSocketsCheck (rfbClientPtr cl)
138146
rfbErr("webSocketsHandshake: rfbssl_init failed\n");
139147
return FALSE;
140148
}
141-
ret = rfbPeekExactTimeout(cl, bbuf, 4, WEBSOCKETS_CLIENT_CONNECT_WAIT_MS);
149+
ret = rfbPeekExactTimeout(cl, bbuf, 4, timeout);
142150
scheme = "wss";
143151
} else {
144152
scheme = "ws";
@@ -183,8 +191,7 @@ webSocketsHandshake(rfbClientPtr cl, char *scheme)
183191
}
184192

185193
while (len < WEBSOCKETS_MAX_HANDSHAKE_LEN-1) {
186-
if ((n = rfbReadExactTimeout(cl, buf+len, 1,
187-
WEBSOCKETS_CLIENT_SEND_WAIT_MS)) <= 0) {
194+
if ((n = rfbReadExact(cl, buf+len, 1)) <= 0) {
188195
if ((n < 0) && (errno == ETIMEDOUT)) {
189196
break;
190197
}

rfb/rfb.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ enum rfbSocketState {
100100
RFB_SOCKET_SHUTDOWN
101101
};
102102

103+
enum rfbHandshakeType {
104+
RFB_HANDSHAKE_AUTO,
105+
RFB_HANDSHAKE_WEBSOCKET,
106+
};
107+
103108
typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl);
104109
typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl);
105110
typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl);
@@ -372,6 +377,16 @@ typedef struct _rfbScreenInfo
372377
#ifdef LIBVNCSERVER_HAVE_LIBZ
373378
rfbSetXCutTextUTF8ProcPtr setXCutTextUTF8;
374379
#endif
380+
/** This setting specifies the handshake type to expect.
381+
* WebSocket clients are detected by the presence of a special handshake.
382+
* The handshake can only be detected by waiting some time for it. Normal
383+
* RFB clients do not transmit an initial handshake.
384+
*
385+
* RFB_HANDSHAKE_AUTO - wait 100ms for WS handshake. Then fall back to normal RFB.
386+
* RFB_HANDSHAKE_WEBSOCKET - wait 500ms for WS handshake.
387+
*
388+
*/
389+
enum rfbHandshakeType handshake_type;
375390
} rfbScreenInfo, *rfbScreenInfoPtr;
376391

377392

0 commit comments

Comments
 (0)