From e37c5c462f07c2fef6d626a844d499a5826aa609 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 2 Mar 2014 11:52:36 -0800 Subject: [PATCH] Add typing to stream data. --- src/protocols/rdp/client.h | 68 +++++++ src/protocols/rdp/guac_handlers.c | 204 ++++++++++--------- src/protocols/rdp/guac_handlers.h | 18 -- src/protocols/rdp/guac_rdpdr/rdpdr_service.c | 9 +- 4 files changed, 184 insertions(+), 115 deletions(-) diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index f8fba3b1..062d128e 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -30,6 +30,7 @@ #include "rdp_fs.h" #include "rdp_keymap.h" #include "rdp_settings.h" +#include "rdp_svc.h" #include @@ -219,6 +220,73 @@ typedef struct guac_rdp_download_status { } guac_rdp_download_status; +/** + * Structure which represents the current state of an upload. + */ +typedef struct guac_rdp_upload_status { + + /** + * The overall offset within the file that the next write should + * occur at. + */ + int offset; + + /** + * The ID of the file being written to. + */ + int file_id; + +} guac_rdp_upload_status; + +/** + * All available stream types. + */ +typedef enum guac_rdp_stream_type { + + /** + * An in-progress file upload. + */ + GUAC_RDP_UPLOAD_STREAM, + + /** + * An in-progress file download. + */ + GUAC_RDP_DOWNLOAD_STREAM, + + /** + * The inbound half of a static virtual channel. + */ + GUAC_RDP_INBOUND_SVC_STREAM + +} guac_rdp_stream_type; + +/** + * Variable-typed stream data. + */ +typedef struct guac_rdp_stream { + + /** + * The type of this stream. + */ + guac_rdp_stream_type type; + + /** + * The file upload status. Only valid for GUAC_RDP_UPLOAD_STREAM. + */ + guac_rdp_upload_status upload_status; + + /** + * The file upload status. Only valid for GUAC_RDP_DOWNLOAD_STREAM. + */ + guac_rdp_download_status download_status; + + /** + * Associated SVC instance. Only valid for GUAC_RDP_SVC_STREAM. + */ + guac_rdp_svc* svc; + +} guac_rdp_stream; + /** * Given the coordinates and dimensions of a rectangle, clips the rectangle to be * within the clipping bounds of the client data, if clipping is active. diff --git a/src/protocols/rdp/guac_handlers.c b/src/protocols/rdp/guac_handlers.c index f0ecdd79..be991b86 100644 --- a/src/protocols/rdp/guac_handlers.c +++ b/src/protocols/rdp/guac_handlers.c @@ -527,7 +527,7 @@ int rdp_guac_client_file_handler(guac_client* client, guac_stream* stream, char* mimetype, char* filename) { int file_id; - guac_rdp_upload_stat* stat; + guac_rdp_stream* rdp_stream; char file_path[GUAC_RDP_FS_MAX_PATH]; /* Get filesystem, return error if no filesystem */ @@ -553,147 +553,165 @@ int rdp_guac_client_file_handler(guac_client* client, guac_stream* stream, } /* Init upload status */ - stat = malloc(sizeof(guac_rdp_upload_stat)); - stat->offset = 0; - stat->file_id = file_id; - stream->data = stat; + rdp_stream = malloc(sizeof(guac_rdp_stream)); + rdp_stream->type = GUAC_RDP_UPLOAD_STREAM; + rdp_stream->upload_status.offset = 0; + rdp_stream->upload_status.file_id = file_id; + stream->data = rdp_stream; guac_protocol_send_ack(client->socket, stream, "OK (STREAM BEGIN)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; + } int rdp_guac_client_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { int bytes_written; - guac_rdp_upload_stat* stat; + guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); - guac_socket_flush(client->socket); - return 0; - } + /* Write any received data if upload stream */ + if (rdp_stream->type == GUAC_RDP_UPLOAD_STREAM) { - /* Get upload status */ - stat = (guac_rdp_upload_stat*) stream->data; - - /* Write entire block */ - while (length > 0) { - - /* Attempt write */ - bytes_written = guac_rdp_fs_write(fs, stat->file_id, stat->offset, - data, length); - - /* On error, abort */ - if (bytes_written < 0) { - guac_protocol_send_ack(client->socket, stream, "FAIL (BAD WRITE)", - GUAC_PROTOCOL_STATUS_PERMISSION_DENIED); + /* Get filesystem, return error if no filesystem 0*/ + guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); guac_socket_flush(client->socket); return 0; } - /* Update counters */ - stat->offset += bytes_written; - data += bytes_written; - length -= bytes_written; + /* Write entire block */ + while (length > 0) { - } + /* Attempt write */ + bytes_written = guac_rdp_fs_write(fs, + rdp_stream->upload_status.file_id, + rdp_stream->upload_status.offset, + data, length); - guac_protocol_send_ack(client->socket, stream, "OK (DATA WRITTEN)", + /* On error, abort */ + if (bytes_written < 0) { + guac_protocol_send_ack(client->socket, stream, + "FAIL (BAD WRITE)", + GUAC_PROTOCOL_STATUS_PERMISSION_DENIED); + guac_socket_flush(client->socket); + return 0; + } + + /* Update counters */ + rdp_stream->upload_status.offset += bytes_written; + data += bytes_written; + length -= bytes_written; + + } + + } /* end if upload stream */ + + guac_protocol_send_ack(client->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; + } int rdp_guac_client_end_handler(guac_client* client, guac_stream* stream) { - guac_rdp_upload_stat* stat; + guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; + + /* Close file for upload streams */ + if (rdp_stream->type == GUAC_RDP_UPLOAD_STREAM) { + + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); + guac_socket_flush(client->socket); + return 0; + } + + /* Close file */ + guac_rdp_fs_close(fs, rdp_stream->upload_status.file_id); - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); - guac_socket_flush(client->socket); - return 0; } - /* Get upload status */ - stat = (guac_rdp_upload_stat*) stream->data; - - /* Close file */ - guac_rdp_fs_close(fs, stat->file_id); - free(stat); - + /* Acknowledge stream end */ guac_protocol_send_ack(client->socket, stream, "OK (STREAM END)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); + + free(rdp_stream); return 0; + } int rdp_guac_client_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { - /* Get status */ - guac_rdp_download_status* download = - (guac_rdp_download_status*) stream->data; + guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Ignore acks for non-download stream data */ - if (download == NULL) + if (rdp_stream == NULL) return 0; - /* Get filesystem, return error if no filesystem */ - guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; - if (fs == NULL) { - guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", - GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); - guac_socket_flush(client->socket); - return 0; - } + /* Send more data when download blobs are acknowledged */ + if (rdp_stream->type == GUAC_RDP_DOWNLOAD_STREAM) { - /* If successful, read data */ - if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { - - /* Attempt read into buffer */ - char buffer[4096]; - int bytes_read = guac_rdp_fs_read(fs, download->file_id, - download->offset, buffer, sizeof(buffer)); - - /* If bytes read, send as blob */ - if (bytes_read > 0) { - download->offset += bytes_read; - guac_protocol_send_blob(client->socket, stream, - buffer, bytes_read); + /* Get filesystem, return error if no filesystem */ + guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; + if (fs == NULL) { + guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", + GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); + guac_socket_flush(client->socket); + return 0; } - /* If EOF, send end */ - else if (bytes_read == 0) { - guac_protocol_send_end(client->socket, stream); + /* If successful, read data */ + if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { + + /* Attempt read into buffer */ + char buffer[4096]; + int bytes_read = guac_rdp_fs_read(fs, + rdp_stream->download_status.file_id, + rdp_stream->download_status.offset, buffer, sizeof(buffer)); + + /* If bytes read, send as blob */ + if (bytes_read > 0) { + rdp_stream->download_status.offset += bytes_read; + guac_protocol_send_blob(client->socket, stream, + buffer, bytes_read); + } + + /* If EOF, send end */ + else if (bytes_read == 0) { + guac_protocol_send_end(client->socket, stream); + guac_client_free_stream(client, stream); + free(rdp_stream); + } + + /* Otherwise, fail stream */ + else { + guac_client_log_error(client, + "Error reading file for download"); + guac_protocol_send_end(client->socket, stream); + guac_client_free_stream(client, stream); + free(rdp_stream); + } + + guac_socket_flush(client->socket); + + } + + /* Otherwise, return stream to client */ + else guac_client_free_stream(client, stream); - free(download); - } - - /* Otherwise, fail stream */ - else { - guac_client_log_error(client, "Error reading file for download"); - guac_protocol_send_end(client->socket, stream); - guac_client_free_stream(client, stream); - free(download); - } - - guac_socket_flush(client->socket); } - /* Otherwise, return stream to client */ - else - guac_client_free_stream(client, stream); - return 0; } diff --git a/src/protocols/rdp/guac_handlers.h b/src/protocols/rdp/guac_handlers.h index 822d2636..15de6a57 100644 --- a/src/protocols/rdp/guac_handlers.h +++ b/src/protocols/rdp/guac_handlers.h @@ -29,24 +29,6 @@ #include #include -/** - * Structure which represents the current state of an upload. - */ -typedef struct guac_rdp_upload_stat { - - /** - * The overall offset within the file that the next write should - * occur at. - */ - int offset; - - /** - * The ID of the file being written to. - */ - int file_id; - -} guac_rdp_upload_stat; - int rdp_guac_client_free_handler(guac_client* client); int rdp_guac_client_handle_messages(guac_client* client); int rdp_guac_client_mouse_handler(guac_client* client, int x, int y, int mask); diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c index 2bf5f886..f04cc631 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_service.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_service.c @@ -230,7 +230,7 @@ void guac_rdpdr_start_download(guac_rdpdr_device* device, const char* path) { /* If file opened successfully, start stream */ if (file_id >= 0) { - guac_rdp_download_status* status; + guac_rdp_stream* rdp_stream; const char* basename; int i; @@ -238,9 +238,10 @@ void guac_rdpdr_start_download(guac_rdpdr_device* device, const char* path) { /* Associate stream with transfer status */ guac_stream* stream = guac_client_alloc_stream(client); - stream->data = status = malloc(sizeof(guac_rdp_download_status)); - status->file_id = file_id; - status->offset = 0; + stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); + rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; + rdp_stream->download_status.file_id = file_id; + rdp_stream->download_status.offset = 0; /* Get basename from absolute path */ i=0;