summaryrefslogtreecommitdiffstats
path: root/libvncserver/rfbserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvncserver/rfbserver.c')
-rw-r--r--libvncserver/rfbserver.c280
1 files changed, 277 insertions, 3 deletions
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index d3e1fbb..89bf0ca 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -64,7 +64,7 @@
#else
#define DEBUGPROTO(x)
#endif
-
+#include <stdarg.h>
#include <scale.h>
static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
@@ -353,6 +353,9 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE;
cl->enableKeyboardLedState = FALSE;
+ cl->enableSupportedMessages = FALSE;
+ cl->enableSupportedEncodings = FALSE;
+ cl->enableServerIdentity = FALSE;
cl->lastKeyboardLedState = -1;
cl->cursorX = rfbScreen->cursorX;
cl->cursorY = rfbScreen->cursorY;
@@ -782,6 +785,204 @@ rfbSendKeyboardLedState(rfbClientPtr cl)
}
+#define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8)))
+
+/*
+ * Send rfbEncodingSupportedMessages.
+ */
+
+rfbBool
+rfbSendSupportedMessages(rfbClientPtr cl)
+{
+ rfbFramebufferUpdateRectHeader rect;
+ rfbSupportedMessages msgs;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = Swap16IfLE(sz_rfbFramebufferUpdateRectHeader);
+ rect.r.h = 0;
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ memset((char *)&msgs, 0, sz_rfbSupportedMessages);
+ rfbSetBit(msgs.client2server, rfbSetPixelFormat);
+ rfbSetBit(msgs.client2server, rfbFixColourMapEntries);
+ rfbSetBit(msgs.client2server, rfbSetEncodings);
+ rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest);
+ rfbSetBit(msgs.client2server, rfbKeyEvent);
+ rfbSetBit(msgs.client2server, rfbPointerEvent);
+ rfbSetBit(msgs.client2server, rfbClientCutText);
+ rfbSetBit(msgs.client2server, rfbFileTransfer);
+ rfbSetBit(msgs.client2server, rfbSetScale);
+ //rfbSetBit(msgs.client2server, rfbSetServerInput);
+ //rfbSetBit(msgs.client2server, rfbSetSW);
+ //rfbSetBit(msgs.client2server, rfbTextChat);
+ //rfbSetBit(msgs.client2server, rfbKeyFrameRequest);
+ rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
+
+ rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
+ rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
+ rfbSetBit(msgs.server2client, rfbBell);
+ rfbSetBit(msgs.server2client, rfbServerCutText);
+ rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
+ //rfbSetBit(msgs.server2client, rfbKeyFrameUpdate);
+ rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
+ cl->ublen += sz_rfbSupportedMessages;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+static void rfbSendSupporteddEncodings_SendEncoding(rfbClientPtr cl, uint32_t enc)
+{
+ uint32_t nSwapped=0;
+ nSwapped = Swap32IfLE(enc);
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&nSwapped, sizeof(nSwapped));
+ cl->ublen+=sizeof(nSwapped);
+}
+
+
+/*
+ * Send rfbEncodingSupportedEncodings.
+ */
+
+rfbBool
+rfbSendSupportedEncodings(rfbClientPtr cl)
+{
+ rfbFramebufferUpdateRectHeader rect;
+ uint16_t nEncodings=0;
+
+ /* think rfbSetEncodingsMsg */
+
+ /* TODO: dynamic way of doing this */
+ nEncodings=16;
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ nEncodings += 2;
+#endif
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ nEncodings++;
+#endif
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
+ + (nEncodings*sizeof(uint32_t)) > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t));
+ rect.r.h = Swap16IfLE(nEncodings);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRaw);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCopyRect);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRRE);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingCoRRE);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingHextile);
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZlib);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingTight);
+#endif
+#ifdef LIBVNCSERVER_HAVE_LIBZ
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingZRLE);
+#endif
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltra);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingUltraZip);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingXCursor);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingRichCursor);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingPointerPos);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingLastRect);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingNewFBSize);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingKeyboardLedState);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedMessages);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingSupportedEncodings);
+ rfbSendSupporteddEncodings_SendEncoding(cl, rfbEncodingServerIdentity);
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void
+rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...)
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
+ va_end(ap);
+
+ if (screen->versionString!=NULL) free(screen->versionString);
+ screen->versionString = strdup(buffer);
+}
+
+/*
+ * Send rfbEncodingServerIdentity.
+ */
+
+rfbBool
+rfbSendServerIdentity(rfbClientPtr cl)
+{
+ rfbFramebufferUpdateRectHeader rect;
+ char buffer[512];
+
+ /* tack on our library version */
+ snprintf(buffer,sizeof(buffer)-1, "%s (%s)",
+ (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString),
+ LIBVNCSERVER_PACKAGE_STRING);
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader
+ + (strlen(buffer)+1) > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingServerIdentity);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = Swap16IfLE(strlen(buffer)+1);
+ rect.r.h = 0;
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1);
+ cl->ublen += strlen(buffer)+1;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+
+
/*
* rfbProcessClientNormalMessage is called when the client has sent a normal
* protocol message.
@@ -978,6 +1179,27 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl->enableKeyboardLedState = TRUE;
}
break;
+ case rfbEncodingSupportedMessages:
+ if (!cl->enableSupportedMessages) {
+ rfbLog("Enabling SupportedMessages protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableSupportedMessages = TRUE;
+ }
+ break;
+ case rfbEncodingSupportedEncodings:
+ if (!cl->enableSupportedEncodings) {
+ rfbLog("Enabling SupportedEncodings protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableSupportedEncodings = TRUE;
+ }
+ break;
+ case rfbEncodingServerIdentity:
+ if (!cl->enableServerIdentity) {
+ rfbLog("Enabling ServerIdentity protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableServerIdentity = TRUE;
+ }
+ break;
#ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZRLE:
if (cl->preferredEncoding == -1) {
@@ -1268,6 +1490,9 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
rfbBool sendCursorShape = FALSE;
rfbBool sendCursorPos = FALSE;
rfbBool sendKeyboardLedState = FALSE;
+ rfbBool sendSupportedMessages = FALSE;
+ rfbBool sendSupportedEncodings = FALSE;
+ rfbBool sendServerIdentity = FALSE;
rfbBool result = TRUE;
@@ -1325,6 +1550,40 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
}
}
+ /*
+ * Do we plan to send a rfbEncodingSupportedMessages?
+ */
+ if (cl->enableSupportedMessages)
+ {
+ sendSupportedMessages = TRUE;
+ /* We only send this message ONCE <per setEncodings message received>
+ * (We disable it here)
+ */
+ cl->enableSupportedMessages = FALSE;
+ }
+ /*
+ * Do we plan to send a rfbEncodingSupportedEncodings?
+ */
+ if (cl->enableSupportedEncodings)
+ {
+ sendSupportedEncodings = TRUE;
+ /* We only send this message ONCE <per setEncodings message received>
+ * (We disable it here)
+ */
+ cl->enableSupportedEncodings = FALSE;
+ }
+ /*
+ * Do we plan to send a rfbEncodingServerIdentity?
+ */
+ if (cl->enableServerIdentity)
+ {
+ sendServerIdentity = TRUE;
+ /* We only send this message ONCE <per setEncodings message received>
+ * (We disable it here)
+ */
+ cl->enableServerIdentity = FALSE;
+ }
+
LOCK(cl->updateMutex);
/*
@@ -1368,7 +1627,8 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
sraRgnEmpty(updateRegion) &&
(cl->enableCursorShapeUpdates ||
(cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) &&
- !sendCursorShape && !sendCursorPos && !sendKeyboardLedState) {
+ !sendCursorShape && !sendCursorPos && !sendKeyboardLedState &&
+ !sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) {
sraRgnDestroy(updateRegion);
UNLOCK(cl->updateMutex);
return TRUE;
@@ -1529,7 +1789,8 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
}
fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
nUpdateRegionRects +
- !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState));
+ !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState +
+ !!sendSupportedMessages + !!sendSupportedEncodings + !!sendServerIdentity));
} else {
fu->nRects = 0xFFFF;
}
@@ -1551,6 +1812,19 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
if (!rfbSendKeyboardLedState(cl))
goto updateFailed;
}
+
+ if (sendSupportedMessages) {
+ if (!rfbSendSupportedMessages(cl))
+ goto updateFailed;
+ }
+ if (sendSupportedEncodings) {
+ if (!rfbSendSupportedEncodings(cl))
+ goto updateFailed;
+ }
+ if (sendServerIdentity) {
+ if (!rfbSendServerIdentity(cl))
+ goto updateFailed;
+ }
if (!sraRgnEmpty(updateCopyRegion)) {
if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))