summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Beier <dontmind@freeshell.org>2010-11-02 22:23:12 +0100
committerChristian Beier <dontmind@freeshell.org>2010-11-02 22:23:12 +0100
commite5523350a8fb5d6ccae4b4d9bc92897f3e5db18c (patch)
treea784f30fb06c79ec942613f7a3833a23f97e808c
parent5da7c7a71ac1db69902c3a2a80f8771713dde70f (diff)
downloadlibtdevnc-e5523350.tar.gz
libtdevnc-e5523350.zip
libvnc[server|client]: implement xvp VNC extension.
This implements the xvp VNC extension, which is described in the community version of the RFB protocol: http://tigervnc.sourceforge.net/cgi-bin/rfbproto It is also mentioned in the official RFB protocol.
-rw-r--r--libvncclient/rfbproto.c52
-rw-r--r--libvncserver/main.c1
-rw-r--r--libvncserver/rfbserver.c63
-rwxr-xr-xlibvncserver/stats.c2
-rw-r--r--rfb/rfb.h3
-rw-r--r--rfb/rfbclient.h5
-rw-r--r--rfb/rfbproto.h48
7 files changed, 171 insertions, 3 deletions
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 098ae38..7d881c4 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -1230,6 +1230,9 @@ SetFormatAndEncodings(rfbClient* client)
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity);
+ /* xvp */
+ if (se->nEncodings < MAX_ENCODINGS)
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXvp);
/* client extensions */
for(e = rfbClientExtensions; e; e = e->next)
@@ -1395,6 +1398,37 @@ rfbBool PermitServerInput(rfbClient* client, int enabled)
/*
+ * send xvp client message
+ * A client supporting the xvp extension sends this to request that the server initiate
+ * a clean shutdown, clean reboot or abrupt reset of the system whose framebuffer the
+ * client is displaying.
+ *
+ * only version 1 is defined in the protocol specs
+ *
+ * possible values for code are:
+ * rfbXvp_Shutdown
+ * rfbXvp_Reboot
+ * rfbXvp_Reset
+ */
+
+rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code)
+{
+ rfbXvpMsg xvp;
+
+ if (!SupportsClient2Server(client, rfbXvp)) return TRUE;
+ xvp.type = rfbXvp;
+ xvp.pad = 0;
+ xvp.version = version;
+ xvp.code = code;
+
+ if (!WriteToRFBServer(client, (char *)&xvp, sz_rfbXvpMsg))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
* SendPointerEvent.
*/
@@ -1984,6 +2018,24 @@ HandleRFBServerMessage(rfbClient* client)
break;
}
+ case rfbXvp:
+ {
+ if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
+ sz_rfbXvpMsg -1))
+ return FALSE;
+
+ SetClient2Server(client, rfbXvp);
+ /* technically, we only care what we can *send* to the server
+ * but, we set Server2Client Just in case it ever becomes useful
+ */
+ SetServer2Client(client, rfbXvp);
+
+ if(client->HandleXvpMsg)
+ client->HandleXvpMsg(client, msg.xvp.version, msg.xvp.code);
+
+ break;
+ }
+
case rfbResizeFrameBuffer:
{
if (!ReadFromRFBServer(client, ((char *)&msg) + 1,
diff --git a/libvncserver/main.c b/libvncserver/main.c
index 28bbc42..5332e2d 100644
--- a/libvncserver/main.c
+++ b/libvncserver/main.c
@@ -901,6 +901,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->displayHook = NULL;
screen->displayFinishedHook = NULL;
screen->getKeyboardLedStateHook = NULL;
+ screen->xvpHook = NULL;
/* initialize client list and iterator mutex */
rfbClientListInit(screen);
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index b540f04..b71daf8 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -874,6 +874,7 @@ rfbSendSupportedMessages(rfbClientPtr cl)
/*rfbSetBit(msgs.client2server, rfbTextChat); */
/*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */
rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor);
+ rfbSetBit(msgs.client2server, rfbXvp);
rfbSetBit(msgs.server2client, rfbFramebufferUpdate);
rfbSetBit(msgs.server2client, rfbSetColourMapEntries);
@@ -882,6 +883,7 @@ rfbSendSupportedMessages(rfbClientPtr cl)
rfbSetBit(msgs.server2client, rfbResizeFrameBuffer);
/*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */
rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer);
+ rfbSetBit(msgs.server2client, rfbXvp);
memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages);
cl->ublen += sz_rfbSupportedMessages;
@@ -1027,6 +1029,33 @@ rfbSendServerIdentity(rfbClientPtr cl)
return TRUE;
}
+/*
+ * Send an xvp server message
+ */
+
+rfbBool
+rfbSendXvp(rfbClientPtr cl, uint8_t version, uint8_t code)
+{
+ rfbXvpMsg xvp;
+
+ xvp.type = rfbXvp;
+ xvp.pad = 0;
+ xvp.version = version;
+ xvp.code = code;
+
+ LOCK(cl->sendMutex);
+ if (rfbWriteExact(cl, (char *)&xvp, sz_rfbXvpMsg) < 0) {
+ rfbLogPerror("rfbSendXvp: write");
+ rfbCloseClient(cl);
+ }
+ UNLOCK(cl->sendMutex);
+
+ rfbStatRecordMessageSent(cl, rfbXvp, sz_rfbXvpMsg, sz_rfbXvpMsg);
+
+ return TRUE;
+}
+
+
rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer)
{
rfbTextChatMsg tc;
@@ -1984,7 +2013,15 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
"%s\n", cl->host);
cl->enableServerIdentity = TRUE;
}
- break;
+ break;
+ case rfbEncodingXvp:
+ rfbLog("Enabling Xvp protocol extension for client "
+ "%s\n", cl->host);
+ if (!rfbSendXvp(cl, 1, rfbXvp_Init)) {
+ rfbCloseClient(cl);
+ return;
+ }
+ break;
default:
#ifdef LIBVNCSERVER_HAVE_LIBZ
if ( enc >= (uint32_t)rfbEncodingCompressLevel0 &&
@@ -2368,6 +2405,28 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
rfbSendNewScaleSize(cl);
return;
+ case rfbXvp:
+
+ if ((n = rfbReadExact(cl, ((char *)&msg) + 1,
+ sz_rfbXvpMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseClient(cl);
+ return;
+ }
+ rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbXvpMsg, sz_rfbXvpMsg);
+
+ /* only version when is defined, so echo back a fail */
+ if(msg.xvp.version != 1) {
+ rfbSendXvp(cl, msg.xvp.version, rfbXvp_Fail);
+ }
+ else {
+ /* if the hook exists and fails, send a fail msg */
+ if(cl->screen->xvpHook && !cl->screen->xvpHook(cl, msg.xvp.version, msg.xvp.code))
+ rfbSendXvp(cl, 1, rfbXvp_Fail);
+ }
+ return;
+
default:
{
rfbExtensionData *e,*next;
@@ -2756,7 +2815,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
if (!rfbSendServerIdentity(cl))
goto updateFailed;
}
-
+
if (!sraRgnEmpty(updateCopyRegion)) {
if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
goto updateFailed;
diff --git a/libvncserver/stats.c b/libvncserver/stats.c
index d5d6925..1e6c9b1 100755
--- a/libvncserver/stats.c
+++ b/libvncserver/stats.c
@@ -55,6 +55,7 @@ char *messageNameServer2Client(uint32_t type, char *buf, int len) {
case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break;
+ case rfbXvp: snprintf(buf, len, "XvpServerMessage"); break;
default:
snprintf(buf, len, "svr2cli-0x%08X", 0xFF);
}
@@ -78,6 +79,7 @@ char *messageNameClient2Server(uint32_t type, char *buf, int len) {
case rfbTextChat: snprintf(buf, len, "TextChat"); break;
case rfbKeyFrameRequest: snprintf(buf, len, "KeyFrameRequest"); break;
case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break;
+ case rfbXvp: snprintf(buf, len, "XvpClientMessage"); break;
default:
snprintf(buf, len, "cli2svr-0x%08X", type);
diff --git a/rfb/rfb.h b/rfb/rfb.h
index e58e59e..1ea9571 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -139,6 +139,7 @@ typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl);
typedef void (*rfbDisplayFinishedHookPtr)(struct _rfbClientRec* cl, int result);
/* support the capability to view the caps/num/scroll states of the X server */
typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen);
+typedef rfbBool (*rfbXvpHookPtr)(struct _rfbClientRec* cl, uint8_t, uint8_t);
/* If x==1 and y==1 then set the whole display
* else find the window underneath x and y and set the framebuffer to the dimensions
* of that window
@@ -356,6 +357,8 @@ typedef struct _rfbScreenInfo
/* displayFinishedHook is called just after a frame buffer update */
rfbDisplayFinishedHookPtr displayFinishedHook;
+ /* xvpHook is called to handle an xvp client message */
+ rfbXvpHookPtr xvpHook;
} rfbScreenInfo, *rfbScreenInfoPtr;
diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h
index 34c8737..1edd32e 100644
--- a/rfb/rfbclient.h
+++ b/rfb/rfbclient.h
@@ -136,6 +136,7 @@ typedef union _rfbCredential
struct _rfbClient;
typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text);
+typedef void (*HandleXvpMsgProc)(struct _rfbClient* client, uint8_t version, uint8_t opcode);
typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad);
typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y);
typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h);
@@ -316,6 +317,9 @@ typedef struct _rfbClient {
/* the QoS IP DSCP for this client */
int QoS_DSCP;
+
+ /* hook to handle xvp server messages */
+ HandleXvpMsgProc HandleXvpMsg;
} rfbClient;
/* cursor.c */
@@ -352,6 +356,7 @@ extern rfbBool TextChatOpen(rfbClient* client);
extern rfbBool TextChatClose(rfbClient* client);
extern rfbBool TextChatFinish(rfbClient* client);
extern rfbBool PermitServerInput(rfbClient* client, int enabled);
+extern rfbBool SendXvpMsg(rfbClient* client, uint8_t version, uint8_t code);
extern void PrintPixelFormat(rfbPixelFormat *format);
diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h
index c20f95c..cb62fc5 100644
--- a/rfb/rfbproto.h
+++ b/rfb/rfbproto.h
@@ -106,7 +106,7 @@ typedef uint32_t in_addr_t;
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#endif
-#define MAX_ENCODINGS 20
+#define MAX_ENCODINGS 21
/*****************************************************************************
*
@@ -405,6 +405,8 @@ typedef struct {
#define rfbKeyFrameRequest 12
/* PalmVNC 1.4 & 2.0 SetScale Factor message */
#define rfbPalmVNCSetScaleFactor 0xF
+/* Xvp message - bidirectional */
+#define rfbXvp 250
@@ -439,6 +441,9 @@ typedef struct {
#define rfbEncodingSolMonoZip 0xFFFF0008
#define rfbEncodingUltraZip 0xFFFF0009
+/* Xvp pseudo-encoding */
+#define rfbEncodingXvp 0xFFFFFECB
+
/*
* Special encoding numbers:
* 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
@@ -1061,6 +1066,44 @@ typedef struct _rfbTextChatMsg {
#define rfbTextChatFinished 0xFFFFFFFD
+/*-----------------------------------------------------------------------------
+ * Xvp Message
+ * Bidirectional message
+ * A server which supports the xvp extension declares this by sending a message
+ * with an Xvp_INIT xvp-message-code when it receives a request from the client
+ * to use the xvp Pseudo-encoding. The server must specify in this message the
+ * highest xvp-extension-version it supports: the client may assume that the
+ * server supports all versions from 1 up to this value. The client is then
+ * free to use any supported version. Currently, only version 1 is defined.
+ *
+ * A server which subsequently receives an xvp Client Message requesting an
+ * operation which it is unable to perform, informs the client of this by
+ * sending a message with an Xvp_FAIL xvp-message-code, and the same
+ * xvp-extension-version as included in the client's operation request.
+ *
+ * A client supporting the xvp extension sends this to request that the server
+ * initiate a clean shutdown, clean reboot or abrupt reset of the system whose
+ * framebuffer the client is displaying.
+ */
+
+
+typedef struct {
+ uint8_t type; /* always rfbXvp */
+ uint8_t pad;
+ uint8_t version; /* xvp extension version */
+ uint8_t code; /* xvp message code */
+} rfbXvpMsg;
+
+#define sz_rfbXvpMsg (4)
+
+/* server message codes */
+#define rfbXvp_Fail 0
+#define rfbXvp_Init 1
+/* client message codes */
+#define rfbXvp_Shutdown 2
+#define rfbXvp_Reboot 3
+#define rfbXvp_Reset 4
+
/*-----------------------------------------------------------------------------
* Modif sf@2002
@@ -1115,6 +1158,7 @@ typedef union {
rfbPalmVNCReSizeFrameBufferMsg prsfb;
rfbFileTransferMsg ft;
rfbTextChatMsg tc;
+ rfbXvpMsg xvp;
} rfbServerToClientMsg;
@@ -1350,6 +1394,7 @@ typedef struct _rfbSetSWMsg {
#define sz_rfbSetSWMsg 6
+
/*-----------------------------------------------------------------------------
* Union of all client->server messages.
*/
@@ -1369,6 +1414,7 @@ typedef union {
rfbFileTransferMsg ft;
rfbSetSWMsg sw;
rfbTextChatMsg tc;
+ rfbXvpMsg xvp;
} rfbClientToServerMsg;
/*