From 709911059e22ca15f0fa6d3c17448bef8864f1c7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 18 Sep 2010 11:58:16 -0700 Subject: [PATCH] Beginnings of threads instead of processes, pluggable client specified at command line --- guacamole/libguac/client.c | 4 +- guacamole/libguac/include/client.h | 20 +++---- guacamole/proxy/daemon.c | 91 +++++++++++++++++++++--------- guacamole/vnc/vnc_client.c | 6 +- 4 files changed, 80 insertions(+), 41 deletions(-) diff --git a/guacamole/libguac/client.c b/guacamole/libguac/client.c index 9234c4a49..0aa361d4d 100644 --- a/guacamole/libguac/client.c +++ b/guacamole/libguac/client.c @@ -184,7 +184,7 @@ guac_client* __guac_alloc_client(GUACIO* io) { } -guac_client* guac_get_client(int client_fd, guac_client_registry_node* registry, guac_client_init_handler* client_init, const char* hostname, int port) { +guac_client* guac_get_client(int client_fd, guac_client_registry_node* registry, guac_client_init_handler* client_init, int argc, char** argv) { guac_client* client; GUACIO* io = guac_open(client_fd); @@ -214,7 +214,7 @@ guac_client* guac_get_client(int client_fd, guac_client_registry_node* registry, } /* FIXME: hostname and port should not be required. Should be made available in some sort of client-contained argc/argv, specified after the protocol on the commandline */ - client_init(client, hostname, port); + client_init(client, argc, argv); break; } diff --git a/guacamole/libguac/include/client.h b/guacamole/libguac/include/client.h index c17a9c727..1f0c1e9db 100644 --- a/guacamole/libguac/include/client.h +++ b/guacamole/libguac/include/client.h @@ -78,7 +78,7 @@ struct guac_client { * @code * void handle_messages(guac_client* client); * - * void guac_client_init(guac_client* client) { + * void guac_client_init(guac_client* client, int argc, char** argv) { * client->handle_messages = handle_messages; * } * @endcode @@ -105,7 +105,7 @@ struct guac_client { * @code * void mouse_handler(guac_client* client, int x, int y, int button_mask); * - * void guac_client_init(guac_client* client) { + * void guac_client_init(guac_client* client, int argc, char** argv) { * client->mouse_handler = mouse_handler; * } * @endcode @@ -123,7 +123,7 @@ struct guac_client { * @code * void key_handler(guac_client* client, int keysym, int pressed); * - * void guac_client_init(guac_client* client) { + * void guac_client_init(guac_client* client, int argc, char** argv) { * client->key_handler = key_handler; * } * @endcode @@ -144,7 +144,7 @@ struct guac_client { * @code * void clipboard_handler(guac_client* client, char* copied); * - * void guac_client_init(guac_client* client) { + * void guac_client_init(guac_client* client, int argc, char** argv) { * client->clipboard_handler = clipboard_handler; * } * @endcode @@ -164,7 +164,7 @@ struct guac_client { * @code * void free_handler(guac_client* client); * - * void guac_client_init(guac_client* client) { + * void guac_client_init(guac_client* client, int argc, char** argv) { * client->free_handler = free_handler; * } * @endcode @@ -173,7 +173,7 @@ struct guac_client { }; -typedef void guac_client_init_handler(guac_client* client, const char* hostname, int port); +typedef void guac_client_init_handler(guac_client* client, int argc, char** argv); /** * Initialize and return a new guac_client using the specified client init handler (guac_client_init_handler). @@ -184,11 +184,11 @@ typedef void guac_client_init_handler(guac_client* client, const char* hostname, * web-client tunnel. * @param client_init Function pointer to the client init handler which will initialize the new guac_client * when called. The given hostname and port will be passed to this handler. - * @param hostname The hostname of the host that the proxy client should connect to. - * @param port The port of the host that the proxy client should connect to. - * @return A pointer to the newly initialized client. + * @param argc The number of arguments being passed to this 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_node* registry, guac_client_init_handler* client_init, const char* hostname, int port); +guac_client* guac_get_client(int client_fd, guac_client_registry_node* registry, guac_client_init_handler* client_init, int argc, char** argv); /** * Enter the main network message handling loop for the given client. diff --git a/guacamole/proxy/daemon.c b/guacamole/proxy/daemon.c index aaaca7c91..30c64bdf4 100644 --- a/guacamole/proxy/daemon.c +++ b/guacamole/proxy/daemon.c @@ -28,17 +28,58 @@ #include "client.h" + +typedef struct client_thread_data { + + int fd; + guac_client_init_handler* client_init; + guac_client_registry_node* registry; + + int argc; + char** argv; + +} client_thread_data; + + +void* start_client_thread(void* data) { + + guac_client* client; + client_thread_data* thread_data = (client_thread_data*) data; + + fprintf(stderr, "[guacamole] spawning client\n"); + + /* Load and start client */ + client = guac_get_client(thread_data->fd, thread_data->registry, thread_data->client_init, thread_data->argc, thread_data->argv); + guac_start_client(client); + + /* FIXME: Need to free client, but only if the client is not + * being used. This line will be reached if handoff occurs + */ + guac_free_client(client, thread_data->registry); + + /* Close socket */ + if (close(thread_data->fd) < 0) { + perror("Error closing connection"); + free(data); + return NULL; + } + + fprintf(stderr, "[guacamole] client finished\n"); + free(data); + return NULL; + +} + int main(int argc, char* argv[]) { /* Client registry */ guac_client_registry_node* registry; /* Pluggable client */ - guac_client* client; void* client_plugin_handle; union { - void (*client_init)(guac_client* client, const char* hostname, int port); + guac_client_init_handler* client_init; void* obj; } alias; @@ -55,18 +96,23 @@ int main(int argc, char* argv[]) { pid_t client_pid ; int listen_port; - const char* connect_host; - int connect_port; - if (argc < 4) { - fprintf(stderr, "USAGE: %s LISTENPORT CONNECTHOST CONNECTPORT\n", argv[0]); + int client_argc; + char** client_argv; + + char protocol_lib[256] = "libguac_client_"; + + if (argc < 3) { + fprintf(stderr, "USAGE: %s LISTENPORT PROTOCOL [PROTOCOL OPTIONS]\n", argv[0]); return 1; } listen_port = atoi(argv[1]); - connect_host = argv[2]; - connect_port = atoi(argv[3]); + strcat(protocol_lib, argv[2]); + strcat(protocol_lib, ".so"); + client_argc = argc - 3; + client_argv = &(argv[3]); /* Get binding address */ memset(&server_addr, 0, sizeof(server_addr)); /* Zero struct */ @@ -91,7 +137,7 @@ int main(int argc, char* argv[]) { fprintf(stderr, "[guacamole] loading pluggable client\n"); /* Load client plugin */ - client_plugin_handle = dlopen("libguac_client_vnc.so", RTLD_LAZY); + client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!client_plugin_handle) { fprintf(stderr, "[guacamole] could not open client plugin: %s\n", dlerror()); return 2; @@ -109,7 +155,7 @@ int main(int argc, char* argv[]) { - fprintf(stderr, "[guacamole] listening on port %i, forwarding to %s:%i\n", listen_port, connect_host, connect_port); + fprintf(stderr, "[guacamole] listening on port %i\n", listen_port); /* Allocate registry */ registry = guac_create_client_registry(); @@ -117,6 +163,8 @@ int main(int argc, char* argv[]) { /* Daemon loop */ for (;;) { + client_thread_data* data; + /* Listen for connections */ if (listen(socket_fd, 5) < 0) { perror("Error listening on socket"); @@ -141,25 +189,16 @@ int main(int argc, char* argv[]) { /* In child ... */ else if (client_pid == 0) { - fprintf(stderr, "[guacamole] spawning client\n"); + data = malloc(sizeof(client_thread_data)); - /* Load and start client */ - client = guac_get_client(connected_socket_fd, registry, alias.client_init, connect_host, connect_port); - guac_start_client(client); + data->fd = connected_socket_fd; + data->client_init = alias.client_init; + data->registry = registry; + data->argc = client_argc; + data->argv = client_argv; - /* FIXME: Need to free client, but only if the client is not - * being used. This line will be reached if handoff occurs - */ - guac_free_client(client, registry); + start_client_thread(data); - /* Close socket */ - if (close(connected_socket_fd) < 0) { - perror("Error closing connection"); - return 3; - } - - fprintf(stderr, "[guacamole] client finished\n"); - return 0; } } diff --git a/guacamole/vnc/vnc_client.c b/guacamole/vnc/vnc_client.c index ac6c62da1..f9e643dc8 100644 --- a/guacamole/vnc/vnc_client.c +++ b/guacamole/vnc/vnc_client.c @@ -264,7 +264,7 @@ void vnc_guac_client_free_handler(guac_client* client) { } -void guac_client_init(guac_client* client, const char* hostname, int port) { +void guac_client_init(guac_client* client, int argc, char** argv) { char* hostname_copy; @@ -294,10 +294,10 @@ void guac_client_init(guac_client* client, const char* hostname, int port) { /* Connect */ hostname_copy = malloc(1024); - strncpy(hostname_copy, hostname, 1024); + strncpy(hostname_copy, argv[0], 1024); rfb_client->serverHost = hostname_copy; - rfb_client->serverPort = port; + rfb_client->serverPort = atoi(argv[1]); rfbInitClient(rfb_client, NULL, NULL);