diff --git a/guacamole/proxy/Makefile b/guacamole/proxy/Makefile index 636d2975a..aea65d8b4 100644 --- a/guacamole/proxy/Makefile +++ b/guacamole/proxy/Makefile @@ -6,19 +6,22 @@ LDFLAGS=-lpng -lvncclient all: guacd -guacd: daemon.o client.o guacio.o protocol.o - $(CC) $(CFLAGS) $(LDFLAGS) daemon.o client.o protocol.o guacio.o -o guacd +guacd: daemon.o client.o guacio.o protocol.o vnc_client.o + $(CC) $(CFLAGS) $(LDFLAGS) daemon.o client.o protocol.o guacio.o vnc_client.o -o guacd client.o: client.c client.h guacio.h $(CC) $(CFLAGS) -c client.c +vnc_client.o: vnc_client.c vnc_client.h guacio.h + $(CC) $(CFLAGS) -c vnc_client.c + protocol.o: protocol.c protocol.h guacio.h $(CC) $(CFLAGS) -c protocol.c guacio.o: guacio.c guacio.h $(CC) $(CFLAGS) -c guacio.c -daemon.o: daemon.c client.h +daemon.o: daemon.c client.h vnc_client.h $(CC) $(CFLAGS) -c daemon.c clean: diff --git a/guacamole/proxy/client.c b/guacamole/proxy/client.c index 949844a27..1c1da0377 100644 --- a/guacamole/proxy/client.c +++ b/guacamole/proxy/client.c @@ -1,152 +1,11 @@ #include #include #include -#include - -#include #include "guacio.h" #include "protocol.h" #include "client.h" -char __guac_password[] = "potato"; - -char* __GUAC_VNC_TAG_IO = "GUACIO"; -char* __GUAC_VNC_TAG_PNG_BUFFER = "PNG_BUFFER"; -char* __GUAC_VNC_TAG_PNG_BUFFER_ALPHA = "PNG_BUFFER_ALPHA"; - -void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { - - int dx, dy; - - GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); - png_byte** png_buffer = rfbClientGetClientData(client, __GUAC_VNC_TAG_PNG_BUFFER_ALPHA); - png_byte* row; - - png_byte** png_row_current = png_buffer; - - unsigned int bytesPerRow = bpp * w; - unsigned char* fb_row_current = client->rcSource; - unsigned char* fb_mask = client->rcMask; - unsigned char* fb_row; - unsigned int v; - - /* Copy image data from VNC client to PNG */ - for (dy = 0; dy> client->format.redShift) * 256 / (client->format.redMax+1); - *(row++) = (v >> client->format.greenShift) * 256 / (client->format.greenMax+1); - *(row++) = (v >> client->format.blueShift) * 256 / (client->format.blueMax+1); - - /* Handle mask */ - if (*(fb_mask++)) - *(row++) = 255; - else - *(row++) = 0; - - fb_row += bpp; - - } - } - - /* SEND CURSOR */ - guac_send_cursor(io, x, y, png_buffer, w, h); - guac_flush(io); - -} -void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { - - int dx, dy; - - GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); - png_byte** png_buffer = rfbClientGetClientData(client, __GUAC_VNC_TAG_PNG_BUFFER); - png_byte* row; - - png_byte** png_row_current = png_buffer; - - unsigned int bpp = client->format.bitsPerPixel/8; - unsigned int bytesPerRow = bpp * client->width; - unsigned char* fb_row_current = client->frameBuffer + (y * bytesPerRow) + (x * bpp); - unsigned char* fb_row; - unsigned int v; - - /* Copy image data from VNC client to PNG */ - for (dy = y; dy> client->format.redShift) * 256 / (client->format.redMax+1); - *(row++) = (v >> client->format.greenShift) * 256 / (client->format.greenMax+1); - *(row++) = (v >> client->format.blueShift) * 256 / (client->format.blueMax+1); - - fb_row += bpp; - - } - } - - guac_send_png(io, x, y, png_buffer, w, h); - guac_flush(io); - -} - -void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { - - GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); - - guac_send_copy(io, src_x, src_y, w, h, dest_x, dest_y); - guac_flush(io); - -} - -char* guac_vnc_get_password(rfbClient* client) { - - /* Freed after use by libvncclient */ - char* password = malloc(64); - strncpy(password, __guac_password, 63); - - fprintf(stderr, "Sending password: %s\n", password); - - return password; -} - png_byte** guac_alloc_png_buffer(int w, int h, int bpp) { @@ -175,98 +34,64 @@ void guac_free_png_buffer(png_byte** png_buffer, int h) { } -void client(int client_fd) { +guac_client* guac_get_client(int client_fd, void (*client_init)(guac_client* client)) { - char* hostname; + guac_client* client = malloc(sizeof(guac_client)); + + client->io = guac_open(client_fd); + + client_init(client); + + return client; + +} + +void guac_free_client(guac_client* client) { + if (client->free_handler) + client->free_handler(client); + + guac_close(client->io); + + free(client); +} + + +void guac_start_client(guac_client* client) { + + GUACIO* io = client->io; int wait_result; - rfbClient* rfb_client; - - png_byte** png_buffer; - png_byte** png_buffer_alpha; - - GUACIO* io = guac_open(client_fd); - - /*** INIT ***/ - - rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */ - - /* Framebuffer update handler */ - rfb_client->GotFrameBufferUpdate = guac_vnc_update; - /*rfb_client->GotCopyRect = guac_vnc_copyrect;*/ - - /* Enable client-side cursor */ - rfb_client->GotCursorShape = guac_vnc_cursor; - rfb_client->appData.useRemoteCursor = TRUE; - - /* Password */ - rfb_client->GetPassword = guac_vnc_get_password; - - hostname = malloc(64); - strcpy(hostname, "localhost"); - - rfb_client->serverHost = hostname; - rfb_client->serverPort = 5902; - - if (rfbInitClient(rfb_client, NULL, NULL)) { - fprintf(stderr, "SUCCESS.\n"); - } - - png_buffer = guac_alloc_png_buffer(rfb_client->width, rfb_client->height, 3); /* No-alpha */ - png_buffer_alpha = guac_alloc_png_buffer(rfb_client->width, rfb_client->height, 4); /* With alpha */ - - /* Store Guac data in client */ - rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_IO, io); - rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_PNG_BUFFER, png_buffer); - rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_PNG_BUFFER_ALPHA, png_buffer_alpha); - - /* Send name */ - guac_send_name(io, rfb_client->desktopName); - - /* Send size */ - guac_send_size(io, rfb_client->width, rfb_client->height); - guac_flush(io); /* VNC Client Loop */ for (;;) { - /* TODO: Separate into THREADS ... no need to do this weird polling thing */ - - wait_result = WaitForMessage(rfb_client, 2000); - if (wait_result < 0) { - fprintf(stderr, "WAIT FAIL\n"); - break; - } - - if (wait_result > 0) { - - if (!HandleRFBServerMessage(rfb_client)) { - fprintf(stderr, "HANDLE FAIL\n"); - break; - } - - } + /* Handle server messages */ + if (client->handle_messages) + client->handle_messages(client); wait_result = guac_instructions_waiting(io); if (wait_result > 0) { + guac_instruction* instruction; while ((instruction = guac_read_instruction(io))) { if (strcmp(instruction->opcode, "mouse") == 0) { - SendPointerEvent( - rfb_client, + if (client->mouse_handler) + client->mouse_handler( + client, atoi(instruction->argv[0]), /* x */ atoi(instruction->argv[1]), /* y */ atoi(instruction->argv[2]) /* mask */ - ); + ); } else if (strcmp(instruction->opcode, "key") == 0) { - SendKeyEvent( - rfb_client, + if (client->key_handler) + client->key_handler( + client, atoi(instruction->argv[0]), /* keysym */ atoi(instruction->argv[1]) /* pressed */ - ); + ); } guac_free_instruction(instruction); @@ -275,15 +100,5 @@ void client(int client_fd) { } - /* Free PNG data */ - guac_free_png_buffer(png_buffer, rfb_client->height); - guac_free_png_buffer(png_buffer_alpha, rfb_client->height); - - /* Clean up VNC client*/ - - rfbClientCleanup(rfb_client); - - guac_write_string(io, "error:Test finished.;"); - guac_close(io); } diff --git a/guacamole/proxy/client.h b/guacamole/proxy/client.h index 2ad10793e..6510325a3 100644 --- a/guacamole/proxy/client.h +++ b/guacamole/proxy/client.h @@ -1,6 +1,26 @@ -#ifndef _PROXY_H_ -#define _PROXY_H +#ifndef _CLIENT_H +#define _CLIENT_H -void client(int client_fd); +#include + +#include "guacio.h" + +typedef struct guac_client { + + GUACIO* io; + void* data; + + void (*handle_messages)(struct guac_client* client); + void (*mouse_handler)(struct guac_client* client, int x, int y, int button_mask); + void (*key_handler)(struct guac_client* client, int keysym, int pressed); + void (*free_handler)(void* client); + +} guac_client; + +guac_client* guac_get_client(int client_fd, void (*client_init)(guac_client* client)); +void guac_start_client(guac_client* client); +void guac_free_client(guac_client* client); +png_byte** guac_alloc_png_buffer(int w, int h, int bpp); +void guac_free_png_buffer(png_byte** png_buffer, int h); #endif diff --git a/guacamole/proxy/daemon.c b/guacamole/proxy/daemon.c index 29be3a8f0..0490ce71e 100644 --- a/guacamole/proxy/daemon.c +++ b/guacamole/proxy/daemon.c @@ -7,6 +7,7 @@ #include #include "client.h" +#include "vnc_client.h" int main(int argc, char* argv[]) { @@ -67,7 +68,10 @@ int main(int argc, char* argv[]) { /* In child ... */ else if (client_pid == 0) { - client(connected_socket_fd); + + guac_client* client = guac_get_client(connected_socket_fd, vnc_guac_client_init); + guac_start_client(client); + guac_free_client(client); /* Close socket */ if (close(connected_socket_fd) < 0) { diff --git a/guacamole/proxy/vnc_client.c b/guacamole/proxy/vnc_client.c new file mode 100644 index 000000000..d2f42ca11 --- /dev/null +++ b/guacamole/proxy/vnc_client.c @@ -0,0 +1,280 @@ +#include +#include +#include +#include + +#include + +#include "guacio.h" +#include "protocol.h" +#include "client.h" + +char __guac_password[] = "potato"; + +char* __GUAC_VNC_TAG_IO = "GUACIO"; +char* __GUAC_VNC_TAG_PNG_BUFFER = "PNG_BUFFER"; +char* __GUAC_VNC_TAG_PNG_BUFFER_ALPHA = "PNG_BUFFER_ALPHA"; + + +typedef struct vnc_guac_client_data { + rfbClient* rfb_client; + png_byte** png_buffer; + png_byte** png_buffer_alpha; +} vnc_guac_client_data; + + +void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) { + + int dx, dy; + + GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); + png_byte** png_buffer = rfbClientGetClientData(client, __GUAC_VNC_TAG_PNG_BUFFER_ALPHA); + png_byte* row; + + png_byte** png_row_current = png_buffer; + + unsigned int bytesPerRow = bpp * w; + unsigned char* fb_row_current = client->rcSource; + unsigned char* fb_mask = client->rcMask; + unsigned char* fb_row; + unsigned int v; + + /* Copy image data from VNC client to PNG */ + for (dy = 0; dy> client->format.redShift) * 256 / (client->format.redMax+1); + *(row++) = (v >> client->format.greenShift) * 256 / (client->format.greenMax+1); + *(row++) = (v >> client->format.blueShift) * 256 / (client->format.blueMax+1); + + /* Handle mask */ + if (*(fb_mask++)) + *(row++) = 255; + else + *(row++) = 0; + + fb_row += bpp; + + } + } + + /* SEND CURSOR */ + guac_send_cursor(io, x, y, png_buffer, w, h); + guac_flush(io); + +} +void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) { + + int dx, dy; + + GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); + png_byte** png_buffer = rfbClientGetClientData(client, __GUAC_VNC_TAG_PNG_BUFFER); + png_byte* row; + + png_byte** png_row_current = png_buffer; + + unsigned int bpp = client->format.bitsPerPixel/8; + unsigned int bytesPerRow = bpp * client->width; + unsigned char* fb_row_current = client->frameBuffer + (y * bytesPerRow) + (x * bpp); + unsigned char* fb_row; + unsigned int v; + + /* Copy image data from VNC client to PNG */ + for (dy = y; dy> client->format.redShift) * 256 / (client->format.redMax+1); + *(row++) = (v >> client->format.greenShift) * 256 / (client->format.greenMax+1); + *(row++) = (v >> client->format.blueShift) * 256 / (client->format.blueMax+1); + + fb_row += bpp; + + } + } + + guac_send_png(io, x, y, png_buffer, w, h); + guac_flush(io); + +} + +void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { + + GUACIO* io = rfbClientGetClientData(client, __GUAC_VNC_TAG_IO); + + guac_send_copy(io, src_x, src_y, w, h, dest_x, dest_y); + guac_flush(io); + +} + +char* guac_vnc_get_password(rfbClient* client) { + + /* Freed after use by libvncclient */ + char* password = malloc(64); + strncpy(password, __guac_password, 63); + + fprintf(stderr, "Sending password: %s\n", password); + + return password; +} + + +void 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, 2000); + if (wait_result < 0) { + fprintf(stderr, "WAIT FAIL\n"); + return; + } + + if (wait_result > 0) { + + if (!HandleRFBServerMessage(rfb_client)) { + fprintf(stderr, "HANDLE FAIL\n"); + return; + } + + } + +} + + +void 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); + +} + +void 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); + +} + + + +void vnc_guac_client_free_handler(guac_client* client) { + + rfbClient* rfb_client = ((vnc_guac_client_data*) client->data)->rfb_client; + png_byte** png_buffer = ((vnc_guac_client_data*) client->data)->png_buffer; + png_byte** png_buffer_alpha = ((vnc_guac_client_data*) client->data)->png_buffer_alpha; + + /* Free PNG data */ + guac_free_png_buffer(png_buffer, rfb_client->height); + guac_free_png_buffer(png_buffer_alpha, rfb_client->height); + + /* Clean up VNC client*/ + rfbClientCleanup(rfb_client); + +} + + +void vnc_guac_client_init(guac_client* client) { + + char* hostname; + rfbClient* rfb_client; + + png_byte** png_buffer; + png_byte** png_buffer_alpha; + + vnc_guac_client_data* vnc_guac_client_data; + + /*** INIT ***/ + rfb_client = rfbGetClient(8, 3, 4); /* 32-bpp client */ + + /* Framebuffer update handler */ + rfb_client->GotFrameBufferUpdate = guac_vnc_update; + /*rfb_client->GotCopyRect = guac_vnc_copyrect;*/ + + /* Enable client-side cursor */ + rfb_client->GotCursorShape = guac_vnc_cursor; + rfb_client->appData.useRemoteCursor = TRUE; + + /* Password */ + rfb_client->GetPassword = guac_vnc_get_password; + + /* Connect */ + hostname = malloc(64); + strcpy(hostname, "localhost"); + + rfb_client->serverHost = hostname; + rfb_client->serverPort = 5902; + + rfbInitClient(rfb_client, NULL, NULL); + + /* Allocate buffers */ + png_buffer = guac_alloc_png_buffer(rfb_client->width, rfb_client->height, 3); /* No-alpha */ + png_buffer_alpha = guac_alloc_png_buffer(rfb_client->width, rfb_client->height, 4); /* With alpha */ + + /* Store Guac data in client */ + rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_IO, client->io); + rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_PNG_BUFFER, png_buffer); + rfbClientSetClientData(rfb_client, __GUAC_VNC_TAG_PNG_BUFFER_ALPHA, png_buffer_alpha); + + /* Send name */ + guac_send_name(client->io, rfb_client->desktopName); + + /* Send size */ + guac_send_size(client->io, rfb_client->width, rfb_client->height); + guac_flush(client->io); + + /* Set client data */ + vnc_guac_client_data = malloc(sizeof(vnc_guac_client_data)); + vnc_guac_client_data->rfb_client = rfb_client; + vnc_guac_client_data->png_buffer = png_buffer; + vnc_guac_client_data->png_buffer_alpha = png_buffer_alpha; + client->data = vnc_guac_client_data; + + /* Set handlers */ + client->handle_messages = vnc_guac_client_handle_messages; + client->mouse_handler = vnc_guac_client_mouse_handler; + client->key_handler = vnc_guac_client_key_handler; + + fprintf(stderr, "VNC Client loaded.\n"); + +} + diff --git a/guacamole/proxy/vnc_client.h b/guacamole/proxy/vnc_client.h new file mode 100644 index 000000000..d18fa6e9d --- /dev/null +++ b/guacamole/proxy/vnc_client.h @@ -0,0 +1,10 @@ + +#ifndef _VNC_CLIENT_H +#define _VNC_CLIENT_H + +#include "client.h" + +void vnc_guac_client_init(guac_client* client); + +#endif +