From a7b00aa79f19c687e404c44214176936c095233b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 21 Dec 2011 18:18:25 -0800 Subject: [PATCH] Renaming and regrouping. --- protocols/vnc/src/client.c | 245 ++++---------------------- protocols/vnc/src/guac_handlers.c | 152 ++++++++++++++++ protocols/vnc/src/vnc_handlers.c | 283 ++++++++++++++++++++++++++++++ 3 files changed, 466 insertions(+), 214 deletions(-) create mode 100644 protocols/vnc/src/guac_handlers.c create mode 100644 protocols/vnc/src/vnc_handlers.c diff --git a/protocols/vnc/src/client.c b/protocols/vnc/src/client.c index 77deb9d3..bad597b8 100644 --- a/protocols/vnc/src/client.c +++ b/protocols/vnc/src/client.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -71,217 +72,6 @@ typedef struct vnc_guac_client_data { } vnc_guac_client_data; -void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { - - guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); - guac_socket* socket = gc->socket; - - /* Cairo image buffer */ - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); - unsigned char* buffer = malloc(h*stride); - unsigned char* buffer_row_current = buffer; - cairo_surface_t* surface; - - /* VNC image buffer */ - unsigned int fb_stride = bpp * w; - unsigned char* fb_row_current = client->rcSource; - unsigned char* fb_mask = client->rcMask; - - int dx, dy; - - /* Copy image data from VNC client to RGBA buffer */ - for (dy = 0; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); - green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); - blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); - - /* Output ARGB */ - *(buffer_current++) = (alpha << 24) | (red << 16) | (green << 8) | blue; - - /* Next VNC pixel */ - fb_current += bpp; - - } - } - - /* SEND CURSOR */ - surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, w, h, stride); - guac_protocol_send_cursor(socket, x, y, surface); - - /* Free surface */ - cairo_surface_destroy(surface); - free(buffer); - - /* libvncclient does not free rcMask as it does rcSource */ - free(client->rcMask); -} - - -void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { - - guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); - guac_socket* socket = gc->socket; - - int dx, dy; - - /* Cairo image buffer */ - int stride; - unsigned char* buffer; - unsigned char* buffer_row_current; - cairo_surface_t* surface; - - /* VNC framebuffer */ - unsigned int bpp; - unsigned int fb_stride; - unsigned char* fb_row_current; - - /* Ignore extra update if already handled by copyrect */ - if (((vnc_guac_client_data*) gc->data)->copy_rect_used) { - ((vnc_guac_client_data*) gc->data)->copy_rect_used = 0; - return; - } - - /* Init Cairo buffer */ - stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w); - buffer = malloc(h*stride); - buffer_row_current = buffer; - - bpp = client->format.bitsPerPixel/8; - fb_stride = bpp * client->width; - fb_row_current = client->frameBuffer + (y * fb_stride) + (x * bpp); - - /* Copy image data from VNC client to PNG */ - for (dy = y; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); - green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); - blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); - - /* Output RGB */ - *(buffer_current++) = (red << 16) | (green << 8) | blue; - - fb_current += bpp; - - } - } - - /* For now, only use default layer */ - surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, w, h, stride); - guac_protocol_send_png(socket, GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, x, y, surface); - - /* Free surface */ - cairo_surface_destroy(surface); - free(buffer); - -} - -void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { - - guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); - guac_socket* socket = gc->socket; - - /* For now, only use default layer */ - guac_protocol_send_copy(socket, - GUAC_DEFAULT_LAYER, src_x, src_y, w, h, - GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, dest_x, dest_y); - - ((vnc_guac_client_data*) gc->data)->copy_rect_used = 1; - -} - -char* guac_vnc_get_password(rfbClient* client) { - guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); - return ((vnc_guac_client_data*) gc->data)->password; -} - -rfbBool guac_vnc_malloc_framebuffer(rfbClient* rfb_client) { - - guac_client* gc = rfbClientGetClientData(rfb_client, __GUAC_CLIENT); - vnc_guac_client_data* guac_client_data = (vnc_guac_client_data*) gc->data; - - /* Send new size */ - guac_protocol_send_size(gc->socket, rfb_client->width, rfb_client->height); - - /* Use original, wrapped proc */ - return guac_client_data->rfb_MallocFrameBuffer(rfb_client); -} - - -void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { - - guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); - guac_socket* socket = gc->socket; - - guac_protocol_send_clipboard(socket, text); - -} - int vnc_guac_client_handle_messages(guac_client* client) { int wait_result; @@ -365,6 +155,33 @@ int vnc_guac_client_free_handler(guac_client* client) { } +/* + * Logging, required as libvncclient does not pass the client + * to its logging functions, thus we cannot use guac_client_log*() + */ +void vnc_guac_client_log_info(const char* format, ...) { + + va_list args; + va_start(args, format); + + vsyslog(LOG_INFO, format, args); + + va_end(args); + +} + +void vnc_guac_client_log_error(const char* format, ...) { + + va_list args; + va_start(args, format); + + vsyslog(LOG_ERR, format, args); + + va_end(args); + +} + + int guac_client_init(guac_client* client, int argc, char** argv) { rfbClient* rfb_client; @@ -373,9 +190,9 @@ int guac_client_init(guac_client* client, int argc, char** argv) { int read_only = 0; - /* FIXME: Set up libvncclient logging */ - /*rfbClientLog = guac_log_info; - rfbClientErr = guac_log_error;*/ + /* Set up libvncclient logging */ + rfbClientLog = vnc_guac_client_log_info; + rfbClientErr = vnc_guac_client_log_error; /*** PARSE ARGUMENTS ***/ diff --git a/protocols/vnc/src/guac_handlers.c b/protocols/vnc/src/guac_handlers.c new file mode 100644 index 00000000..7c5f4466 --- /dev/null +++ b/protocols/vnc/src/guac_handlers.c @@ -0,0 +1,152 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-vnc. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +static char* __GUAC_CLIENT = "GUAC_CLIENT"; + +typedef struct vnc_guac_client_data { + + rfbClient* rfb_client; + MallocFrameBufferProc rfb_MallocFrameBuffer; + + int copy_rect_used; + char* password; + char* encodings; + +} vnc_guac_client_data; + +int vnc_guac_client_handle_messages(guac_client* client) { + + int wait_result; + rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; + + wait_result = WaitForMessage(rfb_client, 1000000); + if (wait_result < 0) { + guac_client_log_error(client, "Error waiting for VNC server message\n"); + return 1; + } + + if (wait_result > 0) { + + if (!HandleRFBServerMessage(rfb_client)) { + guac_client_log_error(client, "Error handling VNC server message\n"); + return 1; + } + + } + + return 0; + +} + + +int vnc_guac_client_mouse_handler(guac_client* client, int x, int y, int mask) { + + rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; + + SendPointerEvent(rfb_client, x, y, mask); + + return 0; +} + +int vnc_guac_client_key_handler(guac_client* client, int keysym, int pressed) { + + rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; + + SendKeyEvent(rfb_client, keysym, pressed); + + return 0; +} + +int vnc_guac_client_clipboard_handler(guac_client* client, char* data) { + + rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; + + SendClientCutText(rfb_client, data, strlen(data)); + + return 0; +} + +int vnc_guac_client_free_handler(guac_client* client) { + + vnc_guac_client_data* guac_client_data = (vnc_guac_client_data*) client->data; + rfbClient* rfb_client = guac_client_data->rfb_client; + + /* Free encodings string, if used */ + if (guac_client_data->encodings != NULL) + free(guac_client_data->encodings); + + /* Free generic data struct */ + free(client->data); + + /* Free memory not free'd by libvncclient's rfbClientCleanup() */ + if (rfb_client->frameBuffer != NULL) free(rfb_client->frameBuffer); + if (rfb_client->raw_buffer != NULL) free(rfb_client->raw_buffer); + if (rfb_client->rcSource != NULL) free(rfb_client->rcSource); + + /* Free VNC rfbClientData linked list (not free'd by rfbClientCleanup()) */ + while (rfb_client->clientData != NULL) { + rfbClientData* next = rfb_client->clientData->next; + free(rfb_client->clientData); + rfb_client->clientData = next; + } + + /* Clean up VNC client*/ + rfbClientCleanup(rfb_client); + + return 0; +} + + +/* + * Logging, required as libvncclient does not pass the client + * to its logging functions, thus we cannot use guac_client_log*() + */ + diff --git a/protocols/vnc/src/vnc_handlers.c b/protocols/vnc/src/vnc_handlers.c new file mode 100644 index 00000000..90183603 --- /dev/null +++ b/protocols/vnc/src/vnc_handlers.c @@ -0,0 +1,283 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-vnc. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { + + guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); + guac_socket* socket = gc->socket; + + /* Cairo image buffer */ + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w); + unsigned char* buffer = malloc(h*stride); + unsigned char* buffer_row_current = buffer; + cairo_surface_t* surface; + + /* VNC image buffer */ + unsigned int fb_stride = bpp * w; + unsigned char* fb_row_current = client->rcSource; + unsigned char* fb_mask = client->rcMask; + + int dx, dy; + + /* Copy image data from VNC client to RGBA buffer */ + for (dy = 0; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); + green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); + blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); + + /* Output ARGB */ + *(buffer_current++) = (alpha << 24) | (red << 16) | (green << 8) | blue; + + /* Next VNC pixel */ + fb_current += bpp; + + } + } + + /* SEND CURSOR */ + surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, w, h, stride); + guac_protocol_send_cursor(socket, x, y, surface); + + /* Free surface */ + cairo_surface_destroy(surface); + free(buffer); + + /* libvncclient does not free rcMask as it does rcSource */ + free(client->rcMask); +} + + +void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { + + guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); + guac_socket* socket = gc->socket; + + int dx, dy; + + /* Cairo image buffer */ + int stride; + unsigned char* buffer; + unsigned char* buffer_row_current; + cairo_surface_t* surface; + + /* VNC framebuffer */ + unsigned int bpp; + unsigned int fb_stride; + unsigned char* fb_row_current; + + /* Ignore extra update if already handled by copyrect */ + if (((vnc_guac_client_data*) gc->data)->copy_rect_used) { + ((vnc_guac_client_data*) gc->data)->copy_rect_used = 0; + return; + } + + /* Init Cairo buffer */ + stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, w); + buffer = malloc(h*stride); + buffer_row_current = buffer; + + bpp = client->format.bitsPerPixel/8; + fb_stride = bpp * client->width; + fb_row_current = client->frameBuffer + (y * fb_stride) + (x * bpp); + + /* Copy image data from VNC client to PNG */ + for (dy = y; dy> client->format.redShift) * 0x100 / (client->format.redMax + 1); + green = (v >> client->format.greenShift) * 0x100 / (client->format.greenMax+ 1); + blue = (v >> client->format.blueShift) * 0x100 / (client->format.blueMax + 1); + + /* Output RGB */ + *(buffer_current++) = (red << 16) | (green << 8) | blue; + + fb_current += bpp; + + } + } + + /* For now, only use default layer */ + surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_RGB24, w, h, stride); + guac_protocol_send_png(socket, GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, x, y, surface); + + /* Free surface */ + cairo_surface_destroy(surface); + free(buffer); + +} + +void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { + + guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); + guac_socket* socket = gc->socket; + + /* For now, only use default layer */ + guac_protocol_send_copy(socket, + GUAC_DEFAULT_LAYER, src_x, src_y, w, h, + GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, dest_x, dest_y); + + ((vnc_guac_client_data*) gc->data)->copy_rect_used = 1; + +} + +char* guac_vnc_get_password(rfbClient* client) { + guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); + return ((vnc_guac_client_data*) gc->data)->password; +} + +rfbBool guac_vnc_malloc_framebuffer(rfbClient* rfb_client) { + + guac_client* gc = rfbClientGetClientData(rfb_client, __GUAC_CLIENT); + vnc_guac_client_data* guac_client_data = (vnc_guac_client_data*) gc->data; + + /* Send new size */ + guac_protocol_send_size(gc->socket, rfb_client->width, rfb_client->height); + + /* Use original, wrapped proc */ + return guac_client_data->rfb_MallocFrameBuffer(rfb_client); +} + +void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { + + guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); + guac_socket* socket = gc->socket; + + guac_protocol_send_clipboard(socket, text); + +} + +void guac_vnc_client_log_info(const char* format, ...) { + + va_list args; + va_start(args, format); + + vsyslog(LOG_INFO, format, args); + + va_end(args); + +} + +void guac_vnc_client_log_error(const char* format, ...) { + + va_list args; + va_start(args, format); + + vsyslog(LOG_ERR, format, args); + + va_end(args); + +} +