Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative extension system #584

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions include/rfb/rfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,103 @@ typedef struct _rfbExtensionData {
struct _rfbExtensionData* next;
} rfbExtensionData;

/**
* Protocol extended extension handling.
*/

enum rfbProtocolExtensionHookType {
RFB_PROTOCOL_EXTENSION_HOOK_NONE = 0,
RFB_PROTOCOL_EXTENSION_HOOK_RESERVED_1 = 1,
RFB_PROTOCOL_EXTENSION_HOOK_NEW_CLIENT,
RFB_PROTOCOL_EXTENSION_HOOK_INIT,
RFB_PROTOCOL_EXTENSION_HOOK_PSEUDO_ENCODINGS,
RFB_PROTOCOL_EXTENSION_HOOK_ENABLE_PSEUDO_ENCODING,
RFB_PROTOCOL_EXTENSION_HOOK_HANDLE_MESSAGE,
RFB_PROTOCOL_EXTENSION_HOOK_CLOSE,
RFB_PROTOCOL_EXTENSION_HOOK_USAGE,
RFB_PROTOCOL_EXTENSION_HOOK_PROCESS_ARGUMENT,
RFB_PROTOCOL_EXTENSION_HOOK_POST_SET_ENCODINGS,
RFB_PROTOCOL_EXTENSION_HOOK_PRE_FBU,
RFB_PROTOCOL_EXTENSION_HOOK_POST_FBU,
};

typedef void* rfbProtocolExtensionHookGeneric;

/** returns FALSE if extension should be deactivated for client.
if newClient == NULL, it is always deactivated. */
typedef rfbBool (*rfbProtocolExtensionHookNewClient)(struct _rfbClientRec* client, void** data);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookNewClient), "extension hook size doesn't match");

/** returns FALSE if extension should be deactivated for client.
if init == NULL, it stays activated. */
typedef rfbBool (*rfbProtocolExtensionHookInit)(struct _rfbClientRec* client, void* data);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookInit), "extension hook size doesn't match");

/** if pseudoEncodings is not NULL, it contains a 0 terminated
list of the pseudo encodings handled by this extension. */
typedef int* rfbProtocolExtensionHookPseudoEncodings;
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookPseudoEncodings), "extension hook size doesn't match");

/** returns TRUE if that pseudo encoding is handled by the extension.
encodingNumber==0 means "reset encodings". */
typedef rfbBool (*rfbProtocolExtensionHookEnablePseudoEncoding)(struct _rfbClientRec* client,
void** data, int encodingNumber);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookEnablePseudoEncoding), "extension hook size doesn't match");

/** returns TRUE if message was handled */
typedef rfbBool (*rfbProtocolExtensionHookHandleMessage)(struct _rfbClientRec* client,
void* data,
const rfbClientToServerMsg* message);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookHandleMessage), "extension hook size doesn't match");

typedef void (*rfbProtocolExtensionHookClose)(struct _rfbClientRec* client, void* data);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookClose), "extension hook size doesn't match");

typedef void (*rfbProtocolExtensionHookUsage)(void);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookUsage), "extension hook size doesn't match");

/** processArguments returns the number of handled arguments */
typedef int (*rfbProtocolExtensionHookProcessArgument)(int argc, char *argv[]);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookProcessArgument), "extension hook size doesn't match");

typedef void (*rfbProtocolExtensionHookPostSetEncodings)(struct _rfbClientRec* client);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookPostSetEncodings), "extension hook size doesn't match");

/** returns TRUE if proceed with the framebuffer update (PostFbu is called in any case). */
typedef rfbBool (*rfbProtocolExtensionHookPreFbu)(struct _rfbClientRec* client, void* data);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookPreFbu), "extension hook size doesn't match");

typedef void (*rfbProtocolExtensionHookPostFbu)(struct _rfbClientRec* client, void* data);
_Static_assert(sizeof(rfbProtocolExtensionHookGeneric) == sizeof(rfbProtocolExtensionHookPostFbu), "extension hook size doesn't match");

typedef struct _rfbProtocolExtensionElement {
union {
/** for the type 1 extensions */
rfbProtocolExtensionHookGeneric generic;

rfbProtocolExtensionHookNewClient newClient;
rfbProtocolExtensionHookInit init;
rfbProtocolExtensionHookPseudoEncodings pseudoEncodings;
rfbProtocolExtensionHookEnablePseudoEncoding enablePseudoEncoding;
rfbProtocolExtensionHookHandleMessage handleMessage;
rfbProtocolExtensionHookClose close;
rfbProtocolExtensionHookUsage usage;
rfbProtocolExtensionHookProcessArgument processArgument;

rfbProtocolExtensionHookPostSetEncodings postSetEncodings;
rfbProtocolExtensionHookPreFbu preFbu;
rfbProtocolExtensionHookPostFbu postFbu;
} hook;
/** which hook it is */
int type;
} rfbProtocolExtensionElement;

typedef struct _rfbProtocolExtension2 {
rfbProtocolExtensionElement* elements;
size_t elementsCount;
struct _rfbProtocolExtension2* next;
} rfbProtocolExtension2;

/**
* Per-screen (framebuffer) structure. There can be as many as you wish,
* each serving different clients. However, you have to call
Expand Down Expand Up @@ -707,6 +804,8 @@ typedef struct _rfbClientRec {
int tightPngDstDataLen;
#endif
#endif

struct _rfbExtension2Data* extensions2;
} rfbClientRec, *rfbClientPtr;

/**
Expand Down Expand Up @@ -1039,6 +1138,15 @@ rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension,
rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension);
void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension);

void rfbRegisterProtocolExtension2(rfbProtocolExtension2* extension2);
void rfbUnregisterProtocolExtension2(rfbProtocolExtension2* extension2);
struct _rfbProtocolExtension2* rfbGetExtension2Iterator(void);
void rfbReleaseExtension2Iterator(void);
rfbBool rfbEnableExtension2(rfbClientPtr cl, rfbProtocolExtension2* extension2,
void* data);
rfbBool rfbDisableExtension2(rfbClientPtr cl, rfbProtocolExtension2* extension2);
void* rfbGetExtension2ClientData(rfbClientPtr cl, rfbProtocolExtension2* extension2);

/** to check against plain passwords */
rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len);

Expand Down
50 changes: 38 additions & 12 deletions src/libvncserver/cargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

#include <rfb/rfb.h>

#include "private.h"

extern int rfbStringToAddr(char *str, in_addr_t *iface);

void
rfbUsage(void)
{
rfbProtocolExtension* extension;

fprintf(stderr, "-rfbport port TCP port for RFB protocol\n");
#ifdef LIBVNCSERVER_IPv6
fprintf(stderr, "-rfbportv6 port TCP6 port for RFB protocol\n");
Expand Down Expand Up @@ -61,10 +61,24 @@ rfbUsage(void)
fprintf(stderr, " addr ipv6addr. '-listen localhost' and hostname work too.\n");
#endif

for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
if(extension->usage)
extension->usage();
rfbReleaseExtensionIterator();
rfbProtocolExtension2* extension2 = rfbGetExtension2Iterator();
for (; extension2; extension2 = extension2->next) {
rfbProtocolExtensionElement* el = extension2->elements;
for (; el && el < extension2->elements + extension2->elementsCount; ++el) {
rfbProtocolExtensionHookUsage ptrUsage = NULL;
if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_USAGE) {
ptrUsage = el->hook.usage;
} else if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_EXTENSION1) {
rfbProtocolExtension* extension = (rfbProtocolExtensionHookExtension1) el->hook.generic;
ptrUsage = extension->usage;
}
if (ptrUsage) {
ptrUsage();
break;
}
}
}
rfbReleaseExtension2Iterator();
}

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

for(extension=rfbGetExtensionIterator();handled==0 && extension;
extension=extension->next)
if(extension->processArgument)
handled = extension->processArgument(*argc - i, argv + i);
rfbReleaseExtensionIterator();
for (extension2 = rfbGetExtension2Iterator(); handled == 0 && extension2; extension2 = extension2->next) {
rfbProtocolExtensionHookProcessArgument ptrProcessArgument = NULL;
rfbProtocolExtensionElement* el = extension2->elements;
for (; el && el < extension2->elements + extension2->elementsCount; ++el) {
if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_PROCESS_ARGUMENT) {
ptrProcessArgument = el->hook.processArgument;
} else if (el->type == RFB_PROTOCOL_EXTENSION_HOOK_EXTENSION1) {
rfbProtocolExtension* extension = (rfbProtocolExtensionHookExtension1) el->hook.generic;
ptrProcessArgument = extension->processArgument;
}
if (ptrProcessArgument) {
handled = ptrProcessArgument(*argc - i, argv + i);
break;
}
}
}
rfbReleaseExtension2Iterator();

if(handled==0) {
i++;
Expand Down
Loading