Converting to double-I/O switching and new transfer instruction

This commit is contained in:
Michael Jumper
2010-09-24 01:42:43 +00:00
parent ac87662c33
commit bf5a56ba5e
4 changed files with 55 additions and 26 deletions

View File

@@ -273,7 +273,7 @@ function VNCClient(display) {
// Start next request as soon as possible // Start next request as soon as possible
if (xmlhttprequest.readyState >= 2 && nextRequest == null && uuid) if (xmlhttprequest.readyState >= 2 && nextRequest == null && uuid)
nextRequest = makeRequest("resume:" + uuid + ";yield;"); nextRequest = makeRequest("transfer:out," + uuid + ";");
// Parse stream when data is received and when complete. // Parse stream when data is received and when complete.
if (xmlhttprequest.readyState == 3 || if (xmlhttprequest.readyState == 3 ||

View File

@@ -62,7 +62,8 @@ struct guac_client {
* their own mechanism of I/O for their protocol. The GUACIO structure is * their own mechanism of I/O for their protocol. The GUACIO structure is
* used only to communicate conveniently with the Guacamole web-client. * used only to communicate conveniently with the Guacamole web-client.
*/ */
GUACIO* io; GUACIO* io_in;
GUACIO* io_out;
/** /**
* Semaphore which will be locked while I/O is owned. * Semaphore which will be locked while I/O is owned.

View File

@@ -56,12 +56,16 @@ void guac_free_png_buffer(png_byte** png_buffer, int h) {
} }
void __guac_set_client_io(guac_client* client, GUACIO* io) { void __guac_set_client_io_out(guac_client* client, GUACIO* io) {
sem_wait(&(client->io_lock)); /* Acquire I/O */ client->io_out = io;
client->io = io;
} }
void __guac_release_client_io(guac_client* client) { void __guac_set_client_io_in(guac_client* client, GUACIO* io) {
sem_wait(&(client->io_lock)); /* Acquire I/O */
client->io_in = io;
}
void __guac_release_client_io_in(guac_client* client) {
sem_post(&(client->io_lock)); sem_post(&(client->io_lock));
} }
@@ -72,7 +76,7 @@ guac_client* __guac_alloc_client(GUACIO* io) {
memset(client, 0, sizeof(guac_client)); memset(client, 0, sizeof(guac_client));
/* Init new client */ /* Init new client */
client->io = io; client->io_in = client->io_out = io;
uuid_generate(client->uuid); uuid_generate(client->uuid);
sem_init(&(client->io_lock), 0, 0); /* I/O starts locked */ sem_init(&(client->io_lock), 0, 0); /* I/O starts locked */
@@ -114,7 +118,7 @@ guac_client* guac_get_client(int client_fd, guac_client_registry* registry, guac
/* Send UUID to web-client */ /* Send UUID to web-client */
guac_send_uuid(io, client->uuid); guac_send_uuid(io, client->uuid);
guac_flush(client->io); guac_flush(io);
} }
if (client_init(client, argc, scratch_argv) != 0) if (client_init(client, argc, scratch_argv) != 0)
@@ -124,17 +128,28 @@ guac_client* guac_get_client(int client_fd, guac_client_registry* registry, guac
} }
/* resume -> resume existing connection (when that connection pauses) */ /* resume -> resume existing connection (when that connection pauses) */
if (strcmp(instruction.opcode, "resume") == 0) { if (strcmp(instruction.opcode, "transfer") == 0) {
if (registry) { if (registry) {
client = guac_find_client( client = guac_find_client(
registry, registry,
(unsigned char*) guac_decode_base64_inplace(instruction.argv[0]) (unsigned char*) guac_decode_base64_inplace(instruction.argv[1])
); );
if (client) { if (client) {
__guac_set_client_io(client, io);
if (strcmp(instruction.argv[0], "in") == 0)
__guac_set_client_io_in(client, io);
else if (strcmp(instruction.argv[0], "out") == 0)
__guac_set_client_io_out(client, io);
else if (strcmp(instruction.argv[0], "both") == 0) {
__guac_set_client_io_in(client, io);
__guac_set_client_io_out(client, io);
}
return NULL; /* Returning NULL, so old client loop is used */ return NULL; /* Returning NULL, so old client loop is used */
/* FIXME: Fix semantics of returning NULL vs ptr. This function needs redocumentation, and callers /* FIXME: Fix semantics of returning NULL vs ptr. This function needs redocumentation, and callers
* need to lose their "error" handling. */ * need to lose their "error" handling. */
@@ -173,7 +188,9 @@ void guac_free_client(guac_client* client, guac_client_registry* registry) {
syslog(LOG_ERR, "Error calling client free handler"); syslog(LOG_ERR, "Error calling client free handler");
} }
guac_close(client->io); if (client->io_in != client->io_out)
guac_close(client->io_in);
guac_close(client->io_out);
guac_remove_client(registry, client->uuid); guac_remove_client(registry, client->uuid);
@@ -196,9 +213,20 @@ void guac_start_client(guac_client* client) {
for (;;) { for (;;) {
/* Accept changes to client I/O only before handling messages */ /* Accept changes to client I/O only before handling messages */
if (client_copy.io != client->io) { if (client_copy.io_in != client->io_in) {
guac_close_final(client_copy.io); /* Close old I/O and fd */ /* Close and free previous I/O if unused */
client_copy.io = client->io; if (client_copy.io_in != client_copy.io_out
&& client_copy.io_in != client->io_out)
guac_close_final(client_copy.io_in);
client_copy.io_in = client->io_in;
}
if (client_copy.io_out != client->io_out) {
/* Close and free previous I/O if unused */
if (client_copy.io_out != client_copy.io_in
&& client_copy.io_out != client->io_in)
guac_close_final(client_copy.io_out);
client_copy.io_out = client->io_out;
} }
/* Handle server messages */ /* Handle server messages */
@@ -210,14 +238,14 @@ void guac_start_client(guac_client* client) {
return; return;
} }
guac_flush(client_copy.io); guac_flush(client_copy.io_out);
} }
wait_result = guac_instructions_waiting(client_copy.io); wait_result = guac_instructions_waiting(client_copy.io_in);
if (wait_result > 0) { if (wait_result > 0) {
int retval; int retval;
retval = guac_read_instruction(client_copy.io, &instruction); /* 0 if no instructions finished yet, <0 if error or EOF */ retval = guac_read_instruction(client_copy.io_in, &instruction); /* 0 if no instructions finished yet, <0 if error or EOF */
if (retval > 0) { if (retval > 0) {
@@ -274,7 +302,7 @@ void guac_start_client(guac_client* client) {
else if (strcmp(instruction.opcode, "yield") == 0) { else if (strcmp(instruction.opcode, "yield") == 0) {
/* Allow other connection to take over I/O */ /* Allow other connection to take over I/O */
__guac_release_client_io(client); __guac_release_client_io_in(client);
} }
@@ -283,7 +311,7 @@ void guac_start_client(guac_client* client) {
return; return;
} }
} while ((retval = guac_read_instruction(client_copy.io, &instruction)) > 0); } while ((retval = guac_read_instruction(client_copy.io_in, &instruction)) > 0);
if (retval < 0) { if (retval < 0) {
syslog(LOG_ERR, "Error reading instruction from stream"); syslog(LOG_ERR, "Error reading instruction from stream");

View File

@@ -49,7 +49,7 @@ void guac_vnc_cursor(rfbClient* client, int x, int y, int w, int h, int bpp) {
int dx, dy; int dx, dy;
guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT);
GUACIO* io = gc->io; GUACIO* io = gc->io_out;
png_byte** png_buffer = ((vnc_guac_client_data*) gc->data)->png_buffer_alpha; png_byte** png_buffer = ((vnc_guac_client_data*) gc->data)->png_buffer_alpha;
png_byte* row; png_byte* row;
@@ -110,7 +110,7 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) {
int dx, dy; int dx, dy;
guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT);
GUACIO* io = gc->io; GUACIO* io = gc->io_out;
png_byte** png_buffer = ((vnc_guac_client_data*) gc->data)->png_buffer; png_byte** png_buffer = ((vnc_guac_client_data*) gc->data)->png_buffer;
png_byte* row; png_byte* row;
@@ -167,7 +167,7 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) {
void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { 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_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT);
GUACIO* io = gc->io; GUACIO* io = gc->io_out;
guac_send_copy(io, src_x, src_y, w, h, dest_x, dest_y); guac_send_copy(io, src_x, src_y, w, h, dest_x, dest_y);
((vnc_guac_client_data*) gc->data)->copy_rect_used = 1; ((vnc_guac_client_data*) gc->data)->copy_rect_used = 1;
@@ -187,7 +187,7 @@ char* guac_vnc_get_password(rfbClient* client) {
void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) {
guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT); guac_client* gc = rfbClientGetClientData(client, __GUAC_CLIENT);
GUACIO* io = gc->io; GUACIO* io = gc->io_out;
guac_send_clipboard(io, text); guac_send_clipboard(io, text);
@@ -335,10 +335,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
client->clipboard_handler = vnc_guac_client_clipboard_handler; client->clipboard_handler = vnc_guac_client_clipboard_handler;
/* Send name */ /* Send name */
guac_send_name(client->io, rfb_client->desktopName); guac_send_name(client->io_out, rfb_client->desktopName);
/* Send size */ /* Send size */
guac_send_size(client->io, rfb_client->width, rfb_client->height); guac_send_size(client->io_out, rfb_client->width, rfb_client->height);
return 0; return 0;