From 194a76df115db3b6fe62adbccfe4181ed46d2c52 Mon Sep 17 00:00:00 2001 From: dscho Date: Thu, 6 Oct 2005 19:26:41 +0000 Subject: add an extension mechanism for LibVNCClient, modify the client data handling so that more than one data structure can be attached, and add an example to speak the client part of the back channel. --- libvncclient/rfbproto.c | 101 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 15 deletions(-) (limited to 'libvncclient/rfbproto.c') diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c index 0e8ccfe..1a491a9 100644 --- a/libvncclient/rfbproto.c +++ b/libvncclient/rfbproto.c @@ -77,6 +77,49 @@ rfbDefaultClientLog(const char *format, ...) rfbClientLogProc rfbClientLog=rfbDefaultClientLog; rfbClientLogProc rfbClientErr=rfbDefaultClientLog; +/* extensions */ + +rfbClientProtocolExtension* rfbClientExtensions = NULL; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e) +{ + e->next = rfbClientExtensions; + rfbClientExtensions = e; +} + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data) +{ + rfbClientData* clientData = client->clientData; + + while(clientData && clientData->tag != tag) + clientData = clientData->next; + if(clientData == NULL) { + clientData = calloc(sizeof(rfbClientData), 1); + clientData->next = client->clientData; + client->clientData = clientData; + clientData->tag = tag; + } + + clientData->data = data; +} + +void* rfbClientGetClientData(rfbClient* client, void* tag) +{ + rfbClientData* clientData = client->clientData; + + while(clientData) { + if(clientData->tag == tag) + return clientData->data; + clientData = clientData->next; + } + + return NULL; +} + +/* messages */ + static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) { int i,j; @@ -259,6 +302,12 @@ InitialiseRFBConnection(rfbClient* client) return FALSE; } +#if rfbProtocolMinorVersion == 7 + /* work around LibVNCClient not yet speaking RFB 3.7 */ +#undef rfbProtocolMinorVersion +#define rfbProtocolMinorVersion 3 +#endif + rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n", major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion); @@ -394,6 +443,7 @@ SetFormatAndEncodings(rfbClient* client) rfbBool requestCompressLevel = FALSE; rfbBool requestQualityLevel = FALSE; rfbBool requestLastRectEncoding = FALSE; + rfbClientProtocolExtension* e; spf.type = rfbSetPixelFormat; spf.format = client->format; @@ -535,6 +585,13 @@ SetFormatAndEncodings(rfbClient* client) encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect); } + for(e = rfbClientExtensions; e; e = e->next) + if(e->encodings) { + int* enc; + for(enc = e->encodings; *enc; enc++) + encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc); + } + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; se->nEncodings = rfbClientSwap16IfLE(se->nEncodings); @@ -923,9 +980,20 @@ HandleRFBServerMessage(rfbClient* client) #endif default: - rfbClientLog("Unknown rect encoding %d\n", - (int)rect.encoding); - return FALSE; + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleEncoding && e->handleEncoding(client, &rect)) + handled = TRUE; + + if(!handled) { + rfbClientLog("Unknown rect encoding %d\n", + (int)rect.encoding); + return FALSE; + } + } } /* Now we may discard "soft cursor locks". */ @@ -934,16 +1002,6 @@ HandleRFBServerMessage(rfbClient* client) client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); } -#ifdef MITSHM - /* if using shared memory PutImage, make sure that the X server has - updated its framebuffer before we reuse the shared memory. This is - mainly to avoid copyrect using invalid screen contents - not sure - if we'd need it otherwise. */ - - if (client->appData.useShm) - XSync(dpy, FALSE); -#endif - if (!SendIncrementalFramebufferUpdateRequest(client)) return FALSE; @@ -981,8 +1039,21 @@ HandleRFBServerMessage(rfbClient* client) } default: - rfbClientLog("Unknown message type %d from VNC server\n",msg.type); - return FALSE; + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleMessage && e->handleMessage(client, &msg)) + handled = TRUE; + + if(!handled) { + char buffer[256]; + ReadFromRFBServer(client, buffer, 256); + rfbClientLog("Unknown message type %d from VNC server\n",msg.type); + return FALSE; + } + } } return TRUE; -- cgit v1.2.1