Skip to content

Commit b4312dd

Browse files
author
Volodymyr Samokhatko
committed
libvncserver: Extension2 system
1 parent 3ea549b commit b4312dd

File tree

6 files changed

+617
-135
lines changed

6 files changed

+617
-135
lines changed

include/rfb/rfb.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,86 @@ typedef struct _rfbExtensionData {
192192
struct _rfbExtensionData* next;
193193
} rfbExtensionData;
194194

195+
/**
196+
* Protocol extended extension handling.
197+
*/
198+
199+
enum rfbProtocolExtensionHookType {
200+
RFB_PROTOCOL_EXTENSION_HOOK_NONE = 0,
201+
RFB_PROTOCOL_EXTENSION_HOOK_RESERVED_1 = 1,
202+
RFB_PROTOCOL_EXTENSION_HOOK_NEW_CLIENT,
203+
RFB_PROTOCOL_EXTENSION_HOOK_INIT,
204+
RFB_PROTOCOL_EXTENSION_HOOK_PSEUDO_ENCODINGS,
205+
RFB_PROTOCOL_EXTENSION_HOOK_ENABLE_PSEUDO_ENCODING,
206+
RFB_PROTOCOL_EXTENSION_HOOK_HANDLE_MESSAGE,
207+
RFB_PROTOCOL_EXTENSION_HOOK_CLOSE,
208+
RFB_PROTOCOL_EXTENSION_HOOK_USAGE,
209+
RFB_PROTOCOL_EXTENSION_HOOK_PROCESS_ARGUMENT,
210+
};
211+
212+
typedef void* rfbProtocolExtensionHookGeneric;
213+
214+
/** returns FALSE if extension should be deactivated for client.
215+
if newClient == NULL, it is always deactivated. */
216+
typedef rfbBool (*rfbProtocolExtensionHookNewClient)(struct _rfbClientRec* client, void** data);
217+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookNewClient), "extension hook size doesn't match");
218+
219+
/** returns FALSE if extension should be deactivated for client.
220+
if init == NULL, it stays activated. */
221+
typedef rfbBool (*rfbProtocolExtensionHookInit)(struct _rfbClientRec* client, void* data);
222+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookInit), "extension hook size doesn't match");
223+
224+
/** if pseudoEncodings is not NULL, it contains a 0 terminated
225+
list of the pseudo encodings handled by this extension. */
226+
typedef int* rfbProtocolExtensionHookPseudoEncodings;
227+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookPseudoEncodings), "extension hook size doesn't match");
228+
229+
/** returns TRUE if that pseudo encoding is handled by the extension.
230+
encodingNumber==0 means "reset encodings". */
231+
typedef rfbBool (*rfbProtocolExtensionHookEnablePseudoEncoding)(struct _rfbClientRec* client,
232+
void** data, int encodingNumber);
233+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookEnablePseudoEncoding), "extension hook size doesn't match");
234+
235+
/** returns TRUE if message was handled */
236+
typedef rfbBool (*rfbProtocolExtensionHookHandleMessage)(struct _rfbClientRec* client,
237+
void* data,
238+
const rfbClientToServerMsg* message);
239+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookHandleMessage), "extension hook size doesn't match");
240+
241+
typedef void (*rfbProtocolExtensionHookClose)(struct _rfbClientRec* client, void* data);
242+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookClose), "extension hook size doesn't match");
243+
244+
typedef void (*rfbProtocolExtensionHookUsage)(void);
245+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookUsage), "extension hook size doesn't match");
246+
247+
/** processArguments returns the number of handled arguments */
248+
typedef int (*rfbProtocolExtensionHookProcessArgument)(int argc, char *argv[]);
249+
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookProcessArgument), "extension hook size doesn't match");
250+
251+
typedef struct _rfbProtocolExtensionElement {
252+
union {
253+
/** for the type 1 extensions */
254+
rfbProtocolExtensionHookGeneric generic;
255+
256+
rfbProtocolExtensionHookNewClient newClient;
257+
rfbProtocolExtensionHookInit init;
258+
rfbProtocolExtensionHookPseudoEncodings pseudoEncodings;
259+
rfbProtocolExtensionHookEnablePseudoEncoding enablePseudoEncoding;
260+
rfbProtocolExtensionHookHandleMessage handleMessage;
261+
rfbProtocolExtensionHookClose close;
262+
rfbProtocolExtensionHookUsage usage;
263+
rfbProtocolExtensionHookProcessArgument processArgument;
264+
} hook;
265+
/** which hook it is */
266+
int type;
267+
} rfbProtocolExtensionElement;
268+
269+
typedef struct _rfbProtocolExtension2 {
270+
rfbProtocolExtensionElement* elements;
271+
size_t elementsCount;
272+
struct _rfbProtocolExtension2* next;
273+
} rfbProtocolExtension2;
274+
195275
/**
196276
* Per-screen (framebuffer) structure. There can be as many as you wish,
197277
* each serving different clients. However, you have to call
@@ -707,6 +787,8 @@ typedef struct _rfbClientRec {
707787
int tightPngDstDataLen;
708788
#endif
709789
#endif
790+
791+
struct _rfbExtension2Data* extensions2;
710792
} rfbClientRec, *rfbClientPtr;
711793

712794
/**
@@ -1039,6 +1121,15 @@ rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
10391121
rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension);
10401122
void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension);
10411123

1124+
void rfbRegisterProtocolExtension2(rfbProtocolExtension2* extension2);
1125+
void rfbUnregisterProtocolExtension2(rfbProtocolExtension2* extension2);
1126+
struct _rfbProtocolExtension2* rfbGetExtension2Iterator(void);
1127+
void rfbReleaseExtension2Iterator(void);
1128+
rfbBool rfbEnableExtension2(rfbClientPtr cl, rfbProtocolExtension2* extension2,
1129+
void* data);
1130+
rfbBool rfbDisableExtension2(rfbClientPtr cl, rfbProtocolExtension2* extension2);
1131+
void* rfbGetExtension2ClientData(rfbClientPtr cl, rfbProtocolExtension2* extension2);
1132+
10421133
/** to check against plain passwords */
10431134
rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len);
10441135

src/libvncserver/cargs.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414

1515
#include <rfb/rfb.h>
1616

17+
#include "private.h"
18+
1719
extern int rfbStringToAddr(char *str, in_addr_t *iface);
1820

1921
void
2022
rfbUsage(void)
2123
{
22-
rfbProtocolExtension* extension;
23-
2424
fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
2525
#ifdef LIBVNCSERVER_IPv6
2626
fprintf(stderr, "-rfbportv6 port TCP6 port for RFB protocol\n");
@@ -61,10 +61,24 @@ rfbUsage(void)
6161
fprintf(stderr, " addr ipv6addr. '-listen localhost' and hostname work too.\n");
6262
#endif
6363

64-
for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
65-
if(extension->usage)
66-
extension->usage();
67-
rfbReleaseExtensionIterator();
64+
rfbProtocolExtension2* extension2 = rfbGetExtension2Iterator();
65+
for (; extension2; extension2 = extension2->next) {
66+
rfbProtocolExtensionElement* el = extension2->elements;
67+
for (; el && el < extension2->elements + extension2->elementsCount; ++el) {
68+
rfbProtocolExtensionHookUsage ptrUsage = NULL;
69+
if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_USAGE) {
70+
ptrUsage = el->hook.usage;
71+
} else if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_EXTENSION1) {
72+
rfbProtocolExtension* extension = (rfbProtocolExtensionHookExtension1) el->hook.generic;
73+
ptrUsage = extension->usage;
74+
}
75+
if (ptrUsage) {
76+
ptrUsage();
77+
break;
78+
}
79+
}
80+
}
81+
rfbReleaseExtension2Iterator();
6882
}
6983

7084
/* purges COUNT arguments from ARGV at POSITION and decrements ARGC.
@@ -217,14 +231,26 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
217231
rfbScreen->sslcertfile = argv[++i];
218232
#endif
219233
} else {
220-
rfbProtocolExtension* extension;
234+
rfbProtocolExtension2* extension2;
221235
int handled=0;
222236

223-
for(extension=rfbGetExtensionIterator();handled==0 && extension;
224-
extension=extension->next)
225-
if(extension->processArgument)
226-
handled = extension->processArgument(*argc - i, argv + i);
227-
rfbReleaseExtensionIterator();
237+
for (extension2 = rfbGetExtension2Iterator(); handled == 0 && extension2; extension2 = extension2->next) {
238+
rfbProtocolExtensionHookProcessArgument ptrProcessArgument = NULL;
239+
rfbProtocolExtensionElement* el = extension2->elements;
240+
for (; el && el < extension2->elements + extension2->elementsCount; ++el) {
241+
if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_PROCESS_ARGUMENT) {
242+
ptrProcessArgument = el->hook.processArgument;
243+
} else if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_EXTENSION1) {
244+
rfbProtocolExtension* extension = (rfbProtocolExtensionHookExtension1) el->hook.generic;
245+
ptrProcessArgument = extension->processArgument;
246+
}
247+
if (ptrProcessArgument) {
248+
handled = ptrProcessArgument(*argc - i, argv + i);
249+
break;
250+
}
251+
}
252+
}
253+
rfbReleaseExtension2Iterator();
228254

229255
if(handled==0) {
230256
i++;

0 commit comments

Comments
 (0)