AM_CFLAGS = -Werror -Wall -Iinclude
libguacincdir = $(includedir)/guacamole
-libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/uuidtree.h
+libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h
lib_LTLIBRARIES = libguac.la
-libguac_la_SOURCES = src/client.c src/clientreg.c src/guacio.c src/protocol.c src/uuidtree.c
+libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c
libguac_la_LDFLAGS = -version-info 0:0:0
# Checks for libraries.
AC_CHECK_LIB([png], [png_write_png])
-AC_CHECK_LIB([pthread], [sem_init])
-AC_CHECK_LIB([uuid], [uuid_generate])
# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h semaphore.h])
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
#define _CLIENT_H
#include <png.h>
-#include <uuid/uuid.h>
-#include <semaphore.h>
-#include "uuidtree.h"
#include "guacio.h"
/**
*/
typedef struct guac_client guac_client;
-typedef struct guac_client_registry guac_client_registry;
typedef int guac_client_handle_messages(guac_client* client);
typedef int guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask);
struct guac_client {
/**
- * UUID identifying this client. Useful when identifying a client
- * for connection handoff/resume.
- */
- uuid_t uuid;
-
- /**
* The GUACIO structure to be used to communicate with the web-client. It is
* expected that the implementor of any Guacamole proxy client will provide
* their own mechanism of I/O for their protocol. The GUACIO structure is
GUACIO* io;
/**
- * Semaphore which will be locked while I/O is owned.
- */
- sem_t io_lock;
-
- /**
* Arbitrary reference to proxy client-specific data. Implementors of a
* Guacamole proxy client can store any data they want here, which can then
* be retrieved as necessary in the message handlers.
* Initialize and return a new guac_client using the specified client init handler (guac_client_init_handler).
* This will normally be the guac_client_init function as provided by any of the pluggable proxy clients.
*
- * @param registry The registry to use to register/find the client we need to return.
* @param client_fd The file descriptor associated with the socket associated with the connection to the
* web-client tunnel.
* @param client_init Function pointer to the client init handler which will initialize the new guac_client
* @param argv The arguments being passed to this client.
* @return A pointer to the newly initialized (or found) client.
*/
-guac_client* guac_get_client(int client_fd, guac_client_registry* registry, guac_client_init_handler* client_init, int argc, char** argv);
+guac_client* guac_get_client(int client_fd, guac_client_init_handler* client_init, int argc, char** argv);
/**
* Enter the main network message handling loop for the given client.
* Free all resources associated with the given client.
*
* @param client The proxy client to free all reasources of.
- * @param registry The registry to remove this client from when freed.
*/
-void guac_free_client(guac_client* client, guac_client_registry* registry);
+void guac_free_client(guac_client* client);
/**
* Allocate a libpng-compatible buffer to hold raw image data.
*/
void guac_free_png_buffer(png_byte** png_buffer, int h);
-
-/**
- * Represent the Guacamole "client registry" in which all
- * currently connected clients are stored, indexed by UUID.
- */
-struct guac_client_registry {
-
- /**
- * Root of the uuid tree
- */
- guac_uuid_tree_node* root;
-
- /**
- * Semaphore controlling access to UUID tree.
- */
- sem_t tree_lock;
-
-};
-
-guac_client_registry* guac_create_client_registry();
-void guac_register_client(guac_client_registry* registry, guac_client* client);
-guac_client* guac_find_client(guac_client_registry* registry, uuid_t uuid);
-void guac_remove_client(guac_client_registry* registry, uuid_t uuid);
-void guac_cleanup_registry(guac_client_registry* registry);
-
#endif
+++ /dev/null
-
-/*
- * Guacamole - Clientless Remote Desktop
- * Copyright (C) 2010 Michael Jumper
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _UUIDTREE_H
-#define _UUIDTREE_H
-
-#include <uuid/uuid.h>
-
-typedef struct guac_uuid_tree_node guac_uuid_tree_node;
-
-/**
- * Represents a single node of a tree storing objects by UUID.
- */
-struct guac_uuid_tree_node {
-
- /**
- * The number of pointers used inside the next array.
- */
- int used;
-
- /**
- * The next guac_uuid_tree_node if currently looking at any byte
- * of the UUID except the last, or the stored object if looking at the
- * last byte of the UUID.
- */
- void* next[256];
-
-};
-
-guac_uuid_tree_node* guac_create_uuid_tree();
-void guac_uuid_tree_put(guac_uuid_tree_node* tree, uuid_t uuid, void* obj);
-void* guac_uuid_tree_get(guac_uuid_tree_node* tree, uuid_t uuid);
-void guac_uuid_tree_remove(guac_uuid_tree_node* tree, uuid_t uuid);
-void guac_cleanup_uuid_tree(guac_uuid_tree_node* tree);
-
-#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <uuid/uuid.h>
#include <syslog.h>
}
-void __guac_set_client_io(guac_client* client, GUACIO* io) {
- sem_wait(&(client->io_lock)); /* Acquire I/O */
- client->io = io;
-}
-
-void __guac_release_client_io(guac_client* client) {
- sem_post(&(client->io_lock));
-}
-
guac_client* __guac_alloc_client(GUACIO* io) {
/* Allocate new client (not handoff) */
/* Init new client */
client->io = io;
- uuid_generate(client->uuid);
- sem_init(&(client->io_lock), 0, 0); /* I/O starts locked */
return client;
}
-guac_client* guac_get_client(int client_fd, guac_client_registry* registry, guac_client_init_handler* client_init, int argc, char** argv) {
+guac_client* guac_get_client(int client_fd, guac_client_init_handler* client_init, int argc, char** argv) {
guac_client* client;
GUACIO* io = guac_open(client_fd);
- guac_instruction instruction;
/* Make copies of arguments */
char** safe_argv = malloc(argc * sizeof(char*));
for (i=0; i<argc; i++)
scratch_argv[i] = safe_argv[i] = strdup(argv[i]);
- /* Wait for handshaking messages */
- for (;;) {
-
- int retval;
- retval = guac_read_instruction(io, &instruction); /* 0 if no instructions finished yet, <0 if error or EOF */
-
- if (retval > 0) {
-
- /* connect -> create new client connection */
- if (strcmp(instruction.opcode, "connect") == 0) {
-
- /* Create new client */
- client = __guac_alloc_client(io);
-
- /* Register client */
- if (registry) {
- guac_register_client(registry, client);
-
- /* Send UUID to web-client */
- guac_send_uuid(io, client->uuid);
- guac_flush(client->io);
- }
-
- if (client_init(client, argc, scratch_argv) != 0)
- return NULL;
-
- break;
- }
-
- /* resume -> resume existing connection (when that connection pauses) */
- if (strcmp(instruction.opcode, "resume") == 0) {
-
- if (registry) {
+ /* Create new client */
+ client = __guac_alloc_client(io);
- client = guac_find_client(
- registry,
- (unsigned char*) guac_decode_base64_inplace(instruction.argv[0])
- );
-
- if (client) {
- __guac_set_client_io(client, io);
- return NULL; /* Returning NULL, so old client loop is used */
- /* FIXME: Fix semantics of returning NULL vs ptr. This function needs redocumentation, and callers
- * need to lose their "error" handling. */
- }
- }
-
- return NULL;
-
- }
-
- }
-
- if (retval < 0)
- return NULL; /* EOF or error */
-
- /* Otherwise, retval == 0 implies unfinished instruction */
-
- }
+ if (client_init(client, argc, scratch_argv) != 0)
+ return NULL;
/* Free memory used for arg copy */
for (i=0; i<argc; i++)
}
-void guac_free_client(guac_client* client, guac_client_registry* registry) {
+void guac_free_client(guac_client* client) {
if (client->free_handler) {
if (client->free_handler(client))
guac_close(client->io);
- guac_remove_client(registry, client->uuid);
-
free(client);
}
}
}
- else if (strcmp(instruction.opcode, "pause") == 0) {
-
- /* Allow other connection to take over I/O */
- __guac_release_client_io(client);
-
- }
-
else if (strcmp(instruction.opcode, "disconnect") == 0) {
syslog(LOG_INFO, "Client requested disconnect");
return;
+++ /dev/null
-
-/*
- * Guacamole - Clientless Remote Desktop
- * Copyright (C) 2010 Michael Jumper
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _CLIENTREG_H
-#define _CLIENTREG_H
-
-#include <stdlib.h>
-#include <uuid/uuid.h>
-#include <semaphore.h>
-
-#include "uuidtree.h"
-#include "client.h"
-
-guac_client_registry* guac_create_client_registry() {
-
- guac_client_registry* registry = malloc(sizeof(guac_client_registry));
-
- registry->root = guac_create_uuid_tree();
- sem_init(&(registry->tree_lock), 0, 1);
-
- return registry;
-
-}
-
-void guac_register_client(guac_client_registry* registry, guac_client* client) {
- sem_wait(&(registry->tree_lock));
- guac_uuid_tree_put(registry->root, client->uuid, client);
- sem_post(&(registry->tree_lock));
-}
-
-guac_client* guac_find_client(guac_client_registry* registry, uuid_t uuid) {
- return (guac_client*) guac_uuid_tree_get(registry->root, uuid);
-}
-
-void guac_remove_client(guac_client_registry* registry, uuid_t uuid) {
- sem_wait(&(registry->tree_lock));
- guac_uuid_tree_remove(registry->root, uuid);
- sem_post(&(registry->tree_lock));
-}
-
-void guac_cleanup_registry(guac_client_registry* registry) {
- sem_wait(&(registry->tree_lock));
- guac_cleanup_uuid_tree(registry->root);
- sem_destroy(&(registry->tree_lock));
-}
-
-#endif
#include <sys/types.h>
#include <sys/socket.h>
-#include <uuid/uuid.h>
-
#include "guacio.h"
#include "protocol.h"
guac_write_string(io, ";");
}
-void guac_send_uuid(GUACIO* io, uuid_t uuid) {
-
- guac_write_string(io, "uuid:");
- guac_write_base64(io, uuid, 16);
- guac_flush_base64(io);
- guac_write_string(io, ";");
-
-}
-
void guac_send_clipboard(GUACIO* io, const char* data) {
char* escaped = guac_escape_string(data);
+++ /dev/null
-
-/*
- * Guacamole - Clientless Remote Desktop
- * Copyright (C) 2010 Michael Jumper
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <uuid/uuid.h>
-
-#include "uuidtree.h"
-
-guac_uuid_tree_node* guac_create_uuid_tree() {
-
- guac_uuid_tree_node* tree = malloc(sizeof(guac_uuid_tree_node));
-
- tree->used = 0;
- memset(tree->next, 0, sizeof(tree->next));
-
- return tree;
-
-}
-
-void guac_uuid_tree_put(guac_uuid_tree_node* tree, uuid_t uuid, void* obj) {
-
- guac_uuid_tree_node* current = tree;
- int i;
- unsigned char index;
-
- for (i=0; i<sizeof(uuid_t)-1; i++) {
-
- guac_uuid_tree_node* next;
-
- /* Get next tree node */
- index = ((unsigned char*) uuid)[i];
- next = ((guac_uuid_tree_node**) current->next)[index];
-
- /* If no node, allocate one */
- if (next == NULL) {
- current->used++;
- next = guac_create_uuid_tree();
- ((guac_uuid_tree_node**) current->next)[index] = next;
- }
-
- current = next;
- }
-
- /* Store object */
- index = ((unsigned char*) uuid)[i];
- current->next[index] = obj;
-
-}
-
-void* guac_uuid_tree_get(guac_uuid_tree_node* tree, uuid_t uuid) {
-
- guac_uuid_tree_node* current = tree;
- int i;
- unsigned char index;
-
- for (i=0; i<sizeof(uuid_t)-1; i++) {
-
- /* Get next tree node */
- index = ((unsigned char*) uuid)[i];
- current = ((guac_uuid_tree_node**) current->next)[index];
-
- /* If no node, not present */
- if (current == NULL)
- return NULL;
-
- }
-
- /* Return if found */
- index = ((unsigned char*) uuid)[i];
- return current->next[index];
-
-}
-
-void guac_uuid_tree_remove(guac_uuid_tree_node* tree, uuid_t uuid) {
-
- guac_uuid_tree_node* current = tree;
- int i;
- unsigned char index;
-
- for (i=0; i<sizeof(uuid_t)-1; i++) {
-
- /* Get next tree node */
- index = ((unsigned char*) uuid)[i];
- current = ((guac_uuid_tree_node**) current->next)[index];
-
- /* If no node, nothing to remove */
- if (current == NULL)
- return;
-
- }
-
- /* Remove, if present*/
- if (current->next[index]) {
- current->next[index] = NULL;
- current->used--;
-
- /* FIXME: If no more objects at this node, clean up */
- if (current->used == 0) {
- /* STUB */
- }
-
- }
-
-}
-
-void guac_cleanup_uuid_tree(guac_uuid_tree_node* tree) {
-
- int i;
- for (i=0; i<sizeof(tree->next); i++) {
-
- if (tree->next[i] != NULL) {
- guac_cleanup_uuid_tree(tree->next[i]);
- tree->next[i] = NULL;
- }
-
- }
-
- free(tree);
-
-}
-