From 93be927b1c1c74bc4da6f6d5978ba8e6e52f3cc2 Mon Sep 17 00:00:00 2001 From: dscho Date: Tue, 27 Sep 2005 15:18:22 +0000 Subject: [PATCH] Introduce generic protocol extension method. Deprecate the processCustomClientMessage() method. --- ChangeLog | 7 +++++++ libvncserver/cargs.c | 25 ++++++++++++++++++++--- libvncserver/main.c | 38 +++++++++++++++++++++++++++++++++++ libvncserver/rfbserver.c | 43 +++++++++++++++++++++++++++++++++------- libvncserver/sockets.c | 7 +++++++ rfb/rfb.h | 31 ++++++++++++++++++++++++++++- 6 files changed, 140 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42e21a6..17a6187 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-09-27 Rohit Kumar + * libvncserver/{cargs,sockets,main,rfbserver}.c, + rfb/rfb.h: Provide a generic means to extend the RFB + protocol: rfbRegisterProtocolExtension(extension). This + deprecates the current (very limited) option to override + rfbScreenInfoPtr->processCustomClientMessage(client). + 2005-09-26 Rohit Kumar * libvncserver/{auth,main,rfbserver}.c, rfb/{rfb,rfbproto}.h: support VNC protocol version 3.7. This allows to add security diff --git a/libvncserver/cargs.c b/libvncserver/cargs.c index d0e3309..10926a9 100644 --- a/libvncserver/cargs.c +++ b/libvncserver/cargs.c @@ -19,6 +19,8 @@ extern int rfbStringToAddr(char *str, in_addr_t *iface); void rfbUsage(void) { + rfbProtocolExtension* extension; + fprintf(stderr, "-rfbport port TCP port for RFB protocol\n"); fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n"); fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n" @@ -40,6 +42,11 @@ rfbUsage(void) fprintf(stderr, "-progressive height enable progressive updating for slow links\n"); fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n"); fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n"); + + for(extension=rfbGetExtensionIterator();extension;extension=extension->next) + if(extension->usage) + extension->usage(); + rfbReleaseExtensionIterator(); } /* purges COUNT arguments from ARGV at POSITION and decrements ARGC. @@ -138,9 +145,21 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) return FALSE; } } else { - i++; - i1=i; - continue; + rfbProtocolExtension* extension; + int handled=0; + + for(extension=rfbGetExtensionIterator();handled==0 && extension; + extension=extension->next) + if(extension->processArgument) + handled = extension->processArgument(argv + i); + rfbReleaseExtensionIterator(); + + if(handled==0) { + i++; + i1=i; + continue; + } + i+=handled-1; } /* we just remove the processed arguments from the list */ rfbPurgeArguments(argc,&i1,i-i1+1,argv); diff --git a/libvncserver/main.c b/libvncserver/main.c index a9161ce..905bb83 100644 --- a/libvncserver/main.c +++ b/libvncserver/main.c @@ -40,6 +40,7 @@ #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD static MUTEX(logMutex); +static MUTEX(extMutex); #endif static int rfbEnableLogging=1; @@ -50,6 +51,43 @@ char rfbEndianTest = 0; char rfbEndianTest = -1; #endif +/* + * Protocol extensions + */ + +static rfbProtocolExtension* rfbExtensionHead = NULL; + +void +rfbRegisterProtocolExtension(rfbProtocolExtension* extension) +{ + rfbProtocolExtension* last; + + LOCK(extMutex); + last = extension; + + while(last->next) + last = last->next; + + last->next = rfbExtensionHead; + rfbExtensionHead = extension; + UNLOCK(extMutex); +} + +rfbProtocolExtension* rfbGetExtensionIterator() +{ + LOCK(extMutex); + return rfbExtensionHead; +} + +void rfbReleaseExtensionIterator() +{ + UNLOCK(extMutex); +} + +/* + * Logging + */ + void rfbLogEnable(int enabled) { rfbEnableLogging=enabled; } diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c index 1f71a18..730c789 100644 --- a/libvncserver/rfbserver.c +++ b/libvncserver/rfbserver.c @@ -3,6 +3,7 @@ */ /* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin * Copyright (C) 2002 RealVNC Ltd. * OSXvnc Copyright (C) 2001 Dan McGuirk . * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. @@ -347,6 +348,8 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, cl->progressiveSliceY = 0; + cl->extensions = NULL; + sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion, rfbProtocolMinorVersion); @@ -603,6 +606,7 @@ rfbProcessClientInitMessage(rfbClientPtr cl) int len, n; rfbClientIteratorPtr iterator; rfbClientPtr otherCl; + rfbProtocolExtension* extension; if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { if (n == 0) @@ -613,7 +617,7 @@ rfbProcessClientInitMessage(rfbClientPtr cl) return; } - memset(buf,0,256); + memset(buf,0,sizeof(buf)); si->framebufferWidth = Swap16IfLE(cl->screen->width); si->framebufferHeight = Swap16IfLE(cl->screen->height); @@ -632,6 +636,19 @@ rfbProcessClientInitMessage(rfbClientPtr cl) return; } + for(extension=rfbGetExtensionIterator();extension;extension=extension->next) + if(extension->init) { + void* data; + if(extension->init(cl, &data)) { + rfbExtensionData* extensionData=calloc(sizeof(rfbExtensionData),1); + extensionData->extension=extension; + extensionData->data=data; + extensionData->next=cl->extensions; + cl->extensions=extensionData; + } + } + rfbReleaseExtensionIterator(); + cl->state = RFB_NORMAL; if (!cl->reverseConnection && @@ -1046,15 +1063,27 @@ rfbProcessClientNormalMessage(rfbClientPtr cl) default: + { + rfbExtensionData* extension; + + for(extension=cl->extensions; extension; extension=extension->next) + if(extension->extension->handleMessage && + extension->extension->handleMessage(cl, extension->data, msg)) + return; - if(cl->screen->processCustomClientMessage(cl,msg.type)) + if(cl->screen->processCustomClientMessage(cl,msg.type)) { + rfbLog("Warning: this program uses processCustomClientMessage, " + "which is deprecated.\n" + "Please use rfbRegisterProtocolExtension instead.\n"); return; + } - rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", - msg.type); - rfbLog(" ... closing connection\n"); - rfbCloseClient(cl); - return; + rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", + msg.type); + rfbLog(" ... closing connection\n"); + rfbCloseClient(cl); + return; + } } } diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c index 24a787d..44843c2 100755 --- a/libvncserver/sockets.c +++ b/libvncserver/sockets.c @@ -19,6 +19,7 @@ */ /* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin * OSXvnc Copyright (C) 2001 Dan McGuirk . * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. * All Rights Reserved. @@ -344,6 +345,12 @@ rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen) void rfbCloseClient(rfbClientPtr cl) { + rfbExtensionData* extension; + + for(extension=cl->extensions; extension; extension=extension->next) + if(extension->extension->close) + extension->extension->close(cl, extension->data); + LOCK(cl->updateMutex); #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD if (cl->sock != -1) diff --git a/rfb/rfb.h b/rfb/rfb.h index 4254016..bac805c 100644 --- a/rfb/rfb.h +++ b/rfb/rfb.h @@ -145,7 +145,7 @@ typedef struct { } rfbColourMap; /* - * Security handling (RFB protocol version 3.7 + * Security handling (RFB protocol version 3.7) */ typedef struct _rfbSecurity { @@ -154,6 +154,29 @@ typedef struct _rfbSecurity { struct _rfbSecurity* next; } rfbSecurityHandler; +/* + * Protocol extension handling. + */ + +typedef struct _rfbProtocolExtension { + /* returns TRUE if extension should be activated */ + rfbBool (*init)(struct _rfbClientRec* client, void** data); + /* returns TRUE if message was handled */ + rfbBool (*handleMessage)(struct _rfbClientRec* client, + void* data, + rfbClientToServerMsg message); + void (*close)(struct _rfbClientRec* client, void* data); + void (*usage)(void); + /* processArguments returns the number of handled arguments */ + int (*processArgument)(char *argv[]); + struct _rfbProtocolExtension* next; +} rfbProtocolExtension; + +typedef struct _rfbExtensionData { + rfbProtocolExtension* extension; + void* data; + struct _rfbExtensionData* next; +} rfbExtensionData; /* * Per-screen (framebuffer) structure. There can be as many as you wish, @@ -481,6 +504,8 @@ typedef struct _rfbClientRec { /* if progressive updating is on, this variable holds the current * y coordinate of the progressive slice. */ int progressiveSliceY; + + rfbExtensionData* extensions; } rfbClientRec, *rfbClientPtr; /* @@ -760,6 +785,10 @@ void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion); void rfbDoNothingWithClient(rfbClientPtr cl); enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl); +void rfbRegisterProtocolExtension(rfbProtocolExtension* extension); +struct _rfbProtocolExtension* rfbGetExtensionIterator(); +void rfbReleaseExtensionIterator(); +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension); /* to check against plain passwords */ rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len);