Beginnings of threads instead of processes, pluggable client specified at command line

This commit is contained in:
Michael Jumper
2010-09-18 11:58:16 -07:00
parent c7b44d9daf
commit 709911059e
4 changed files with 80 additions and 41 deletions

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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;
}
}

View File

@@ -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);