From c2fe48f00ccebfb6e122ce643db1101c7e15bd7a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 17 Jul 2013 17:54:28 -0700 Subject: [PATCH] Much more robust testing. Initial migration to own settings structure. --- configure.ac | 46 ++++++++-- src/protocols/rdp/Makefile.am | 2 + src/protocols/rdp/client.c | 113 +++++++---------------- src/protocols/rdp/client.h | 35 +------- src/protocols/rdp/rdp_settings.c | 127 ++++++++++++++++++++++++++ src/protocols/rdp/rdp_settings.h | 148 +++++++++++++++++++++++++++++++ 6 files changed, 351 insertions(+), 120 deletions(-) create mode 100644 src/protocols/rdp/rdp_settings.c create mode 100644 src/protocols/rdp/rdp_settings.h diff --git a/configure.ac b/configure.ac index 64b0bf4c..ce56cb55 100644 --- a/configure.ac +++ b/configure.ac @@ -216,6 +216,7 @@ fi have_winpr=yes have_freerdp=yes legacy_freerdp_extensions=no +rdpsettings_interface=unknown RDP_LIBS= # libfreerdp-cache @@ -246,23 +247,29 @@ AC_CHECK_LIB([freerdp-codec], [freerdp_image_convert], [RDP_LIBS="$RDP_LIBS -lfreerdp-codec"], [have_freerdp=no]) -# FreeRDP-specific structure members +# Check for interval polling in plugins AC_CHECK_MEMBERS([rdpSvcPlugin.interval_ms], [[#include ]]) # FreeRDP-specific headers -AC_CHECK_HEADERS([freerdp/locale/keyboard.h]) +AC_CHECK_HEADERS([freerdp/locale/keyboard.h],, + AC_CHECK_HEADERS([freerdp/kbd/layouts.h],, + [have_freerdp=no])) + +# +# FreeRDP: WinPR +# # Check for stream support via WinPR -AC_CHECK_HEADER(winpr/stream.h,, # <-- stable-1.1 +AC_CHECK_HEADER(winpr/stream.h,, [have_winpr=no, - AC_CHECK_LIB([freerdp-utils], [stream_write_uint8],, # <-- stable-1.0 + AC_CHECK_LIB([freerdp-utils], [stream_write_uint8],, [have_freerdp=no])]) # Check for types in WinPR -AC_CHECK_HEADER(winpr/wtypes.h,, # <-- stable-1.1 +AC_CHECK_HEADER(winpr/wtypes.h,, [have_winpr=no, - AC_CHECK_HEADER(freerdp/types.h,, # <-- stable-1.0 + AC_CHECK_HEADER(freerdp/types.h,, [have_freerdp=no])]) if test "x${have_winpr}" = "xyes" @@ -270,6 +277,33 @@ then AC_DEFINE([ENABLE_WINPR]) fi +# +# FreeRDP: rdpSettings +# + +# Check for current (as of 1.1) rdpSettings interface +AC_CHECK_MEMBERS([rdpSettings.Width, + rdpSettings.Height, + rdpSettings.OrderSupport], + [rdpsettings_interface=stable],, + [[#include ]]) + +# If not current, check for legacy interface +if test "x${rdpsettings_interface}" = "xunknown" +then + AC_CHECK_MEMBERS([rdpSettings.width, + rdpSettings.height, + rdpSettings.order_support], + [rdpsettings_interface=legacy],, + [[#include ]]) +fi + +# Set defines based on interface type, warn if unknown +if test "x${rdpsettings_interface}" = "xlegacy"; then + AC_DEFINE([LEGACY_RDPSETTINGS]) +elif test "x${rdpsettings_interface}" = "xunknown"; then + have_freerdp=no +fi AM_CONDITIONAL([LEGACY_FREERDP_EXTENSIONS], [test "x${legacy_freerdp_extensions}" = "xyes"]) AM_CONDITIONAL([ENABLE_WINPR], [test "x${have_winpr}" = "xyes"]) diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index b7a72296..65b7ab8c 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -57,6 +57,7 @@ libguac_client_rdp_la_SOURCES = \ rdp_keymap_fr_fr.c \ rdp_keymap_en_us.c \ rdp_pointer.c \ + rdp_settings.c \ wav_encoder.c guacsnd_sources = \ @@ -86,6 +87,7 @@ noinst_HEADERS = \ rdp_glyph.h \ rdp_keymap.h \ rdp_pointer.h \ + rdp_settings.h \ wav_encoder.h # Add compatibility layer for WinPR if not available diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 84c924bc..3015446f 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -151,7 +151,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { guac_client_log_error(client, "Failed to load cliprdr plugin."); /* If audio enabled, choose an encoder */ - if (guac_client_data->audio_enabled) { + if (guac_client_data->settings.audio_enabled) { /* Choose an encoding */ for (i=0; client->info.audio_mimetypes[i] != NULL; i++) { @@ -195,7 +195,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { } /* end if audio enabled */ /* If printing enabled, load rdpdr */ - if (guac_client_data->printing_enabled) { + if (guac_client_data->settings.printing_enabled) { /* Load RDPDR plugin */ if (freerdp_channels_load_plugin(channels, instance->settings, @@ -348,22 +348,12 @@ void __guac_rdp_client_load_keymap(guac_client* client, int guac_client_init(guac_client* client, int argc, char** argv) { rdp_guac_client_data* guac_client_data; + guac_rdp_settings* settings; freerdp* rdp_inst; - rdpSettings* settings; - char* hostname; - int port = RDP_DEFAULT_PORT; - BOOL bitmap_cache; - - /** - * Selected server-side keymap. Client will be assumed to also use this - * keymap. Keys will be sent to server based on client input on a - * best-effort basis. - */ - const guac_rdp_keymap* chosen_keymap; - - if (argc < RDP_ARGS_COUNT) { + /* Validate number of arguments received */ + if (argc != RDP_ARGS_COUNT) { guac_protocol_send_error(client->socket, "Wrong argument count received."); @@ -375,12 +365,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) { return 1; } - /* If port specified, use it */ - if (argv[IDX_PORT][0] != '\0') - port = atoi(argv[IDX_PORT]); - - hostname = argv[IDX_HOSTNAME]; - /* Allocate client data */ guac_client_data = malloc(sizeof(rdp_guac_client_data)); @@ -401,22 +385,19 @@ int guac_client_init(guac_client* client, int argc, char** argv) { freerdp_context_new(rdp_inst); /* Set settings */ - settings = rdp_inst->settings; + settings = &(guac_client_data->settings); /* Console */ - settings->console_session = (strcmp(argv[IDX_CONSOLE], "true") == 0); + settings->console = (strcmp(argv[IDX_CONSOLE], "true") == 0); settings->console_audio = (strcmp(argv[IDX_CONSOLE_AUDIO], "true") == 0); - /* --no-auth */ - settings->authentication = FALSE; + /* Set hostname */ + settings->hostname = strdup(argv[IDX_HOSTNAME]); - /* --sec rdp */ - settings->rdp_security = TRUE; - settings->tls_security = FALSE; - settings->nla_security = FALSE; - settings->encryption = TRUE; - settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; - settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; + /* If port specified, use it */ + settings->port = RDP_DEFAULT_PORT; + if (argv[IDX_PORT][0] != '\0') + settings->port = atoi(argv[IDX_PORT]); /* Use optimal width unless overridden */ settings->width = client->info.optimal_width; @@ -447,28 +428,25 @@ int guac_client_init(guac_client* client, int argc, char** argv) { argv[IDX_WIDTH], settings->height); } - /* Set hostname */ - settings->hostname = strdup(hostname); - settings->port = port; - settings->window_title = strdup(hostname); - /* Domain */ + settings->domain = NULL; if (argv[IDX_DOMAIN][0] != '\0') settings->domain = strdup(argv[IDX_DOMAIN]); /* Username */ + settings->username = NULL; if (argv[IDX_USERNAME][0] != '\0') settings->username = strdup(argv[IDX_USERNAME]); /* Password */ - if (argv[IDX_PASSWORD][0] != '\0') { + settings->password = NULL; + if (argv[IDX_PASSWORD][0] != '\0') settings->password = strdup(argv[IDX_PASSWORD]); - settings->autologon = 1; - } /* Initial program */ + settings->initial_program = NULL; if (argv[IDX_INITIAL_PROGRAM][0] != '\0') - settings->shell = strdup(argv[IDX_INITIAL_PROGRAM]); + settings->initial_program = strdup(argv[IDX_INITIAL_PROGRAM]); /* Session color depth */ settings->color_depth = RDP_DEFAULT_DEPTH; @@ -484,41 +462,15 @@ int guac_client_init(guac_client* client, int argc, char** argv) { } /* Audio enable/disable */ - guac_client_data->audio_enabled = + guac_client_data->settings.audio_enabled = (strcmp(argv[IDX_DISABLE_AUDIO], "true") != 0); /* Printing enable/disable */ - guac_client_data->printing_enabled = + guac_client_data->settings.printing_enabled = (strcmp(argv[IDX_ENABLE_PRINTING], "true") == 0); - /* Order support */ - bitmap_cache = settings->bitmap_cache; - settings->os_major_type = OSMAJORTYPE_UNSPECIFIED; - settings->os_minor_type = OSMINORTYPE_UNSPECIFIED; - settings->order_support[NEG_DSTBLT_INDEX] = TRUE; - settings->order_support[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ - settings->order_support[NEG_SCRBLT_INDEX] = TRUE; - settings->order_support[NEG_OPAQUE_RECT_INDEX] = TRUE; - settings->order_support[NEG_DRAWNINEGRID_INDEX] = FALSE; - settings->order_support[NEG_MULTIDSTBLT_INDEX] = FALSE; - settings->order_support[NEG_MULTIPATBLT_INDEX] = FALSE; - settings->order_support[NEG_MULTISCRBLT_INDEX] = FALSE; - settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = FALSE; - settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; - settings->order_support[NEG_LINETO_INDEX] = FALSE; - settings->order_support[NEG_POLYLINE_INDEX] = FALSE; - settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; - settings->order_support[NEG_MEM3BLT_INDEX] = FALSE; - settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; - settings->order_support[NEG_MEM3BLT_V2_INDEX] = FALSE; - settings->order_support[NEG_SAVEBITMAP_INDEX] = FALSE; - settings->order_support[NEG_GLYPH_INDEX_INDEX] = TRUE; - settings->order_support[NEG_FAST_INDEX_INDEX] = TRUE; - settings->order_support[NEG_FAST_GLYPH_INDEX] = TRUE; - settings->order_support[NEG_POLYGON_SC_INDEX] = FALSE; - settings->order_support[NEG_POLYGON_CB_INDEX] = FALSE; - settings->order_support[NEG_ELLIPSE_SC_INDEX] = FALSE; - settings->order_support[NEG_ELLIPSE_CB_INDEX] = FALSE; + /* Commit settings */ + guac_rdp_commit_settings(settings, rdp_inst->settings); /* Store client data */ guac_client_data->rdp_inst = rdp_inst; @@ -555,19 +507,19 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* US English Qwerty */ if (strcmp("en-us-qwerty", argv[IDX_SERVER_LAYOUT]) == 0) - chosen_keymap = &guac_rdp_keymap_en_us; + settings->server_layout = &guac_rdp_keymap_en_us; /* German Qwertz */ else if (strcmp("de-de-qwertz", argv[IDX_SERVER_LAYOUT]) == 0) - chosen_keymap = &guac_rdp_keymap_de_de; + settings->server_layout = &guac_rdp_keymap_de_de; /* French Azerty */ else if (strcmp("fr-fr-azerty", argv[IDX_SERVER_LAYOUT]) == 0) - chosen_keymap = &guac_rdp_keymap_fr_fr; + settings->server_layout = &guac_rdp_keymap_fr_fr; /* Failsafe (Unicode) keymap */ else if (strcmp("failsafe", argv[IDX_SERVER_LAYOUT]) == 0) - chosen_keymap = &guac_rdp_keymap_failsafe; + settings->server_layout = &guac_rdp_keymap_failsafe; /* If keymap unknown, resort to failsafe */ else { @@ -576,7 +528,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { "Unknown layout \"%s\". Using the failsafe layout instead.", argv[IDX_SERVER_LAYOUT]); - chosen_keymap = &guac_rdp_keymap_failsafe; + settings->server_layout = &guac_rdp_keymap_failsafe; } @@ -584,13 +536,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* If no keymap requested, assume US */ else - chosen_keymap = &guac_rdp_keymap_en_us; + settings->server_layout = &guac_rdp_keymap_en_us; /* Load keymap into client */ - __guac_rdp_client_load_keymap(client, chosen_keymap); - - /* Set server-side keymap */ - settings->kbd_layout = chosen_keymap->freerdp_keyboard_layout; + __guac_rdp_client_load_keymap(client, settings->server_layout); /* Connect to RDP server */ if (!freerdp_connect(rdp_inst)) { @@ -606,7 +555,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { } /* Send connection name */ - guac_protocol_send_name(client->socket, settings->window_title); + guac_protocol_send_name(client->socket, settings->hostname); /* Send size */ guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 9df91256..ae7c7c58 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -49,26 +49,8 @@ #include "audio.h" #include "rdp_keymap.h" +#include "rdp_settings.h" -/** - * The default RDP port. - */ -#define RDP_DEFAULT_PORT 3389 - -/** - * Default screen width, in pixels. - */ -#define RDP_DEFAULT_WIDTH 1024 - -/** - * Default screen height, in pixels. - */ -#define RDP_DEFAULT_HEIGHT 768 - -/** - * Default color depth, in bits. - */ -#define RDP_DEFAULT_DEPTH 16 /** * Client data that will remain accessible through the guac_client. @@ -82,10 +64,9 @@ typedef struct rdp_guac_client_data { freerdp* rdp_inst; /** - * The settings structure associated with the FreeRDP client instance - * handling the current connection. + * All settings associated with the current or pending RDP connection. */ - rdpSettings* settings; + guac_rdp_settings settings; /** * Button mask containing the OR'd value of all currently pressed buttons. @@ -171,16 +152,6 @@ typedef struct rdp_guac_client_data { */ char* clipboard; - /** - * Whether audio is enabled. - */ - int audio_enabled; - - /** - * Whether printing is enabled. - */ - int printing_enabled; - /** * Audio output, if any. */ diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c new file mode 100644 index 00000000..6cf797ca --- /dev/null +++ b/src/protocols/rdp/rdp_settings.c @@ -0,0 +1,127 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "rdp_settings.h" + +#ifdef LEGACY_RDPSETTINGS + +void guac_rdp_commit_settings(guac_rdp_settings* guac_settings, rdpSettings* rdp_settings) { + /* STUB */ + + /* + settings->authentication + settings->autologon + settings->bitmap_cache + settings->color_depth + settings->console_audio + settings->console_session + settings->domain + settings->encryption + settings->encryption_level + settings->encryption_method + settings->height + settings->hostname + settings->kbd_layout + settings->nla_security + settings->order_support + settings->os_major_type + settings->os_minor_type + settings->password + settings->port + settings->rdp_security + settings->shell + settings->tls_security + settings->username + settings->width + settings->window_title + */ + +#if 0 + + BOOL bitmap_cache; + + /* --no-auth */ + settings->authentication = FALSE; + + /* --sec rdp */ + settings->rdp_security = TRUE; + settings->tls_security = FALSE; + settings->nla_security = FALSE; + settings->encryption = TRUE; + settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; + settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; + + /* Order support */ + bitmap_cache = settings->bitmap_cache; + settings->os_major_type = OSMAJORTYPE_UNSPECIFIED; + settings->os_minor_type = OSMINORTYPE_UNSPECIFIED; + settings->order_support[NEG_DSTBLT_INDEX] = TRUE; + settings->order_support[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ + settings->order_support[NEG_SCRBLT_INDEX] = TRUE; + settings->order_support[NEG_OPAQUE_RECT_INDEX] = TRUE; + settings->order_support[NEG_DRAWNINEGRID_INDEX] = FALSE; + settings->order_support[NEG_MULTIDSTBLT_INDEX] = FALSE; + settings->order_support[NEG_MULTIPATBLT_INDEX] = FALSE; + settings->order_support[NEG_MULTISCRBLT_INDEX] = FALSE; + settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = FALSE; + settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; + settings->order_support[NEG_LINETO_INDEX] = FALSE; + settings->order_support[NEG_POLYLINE_INDEX] = FALSE; + settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; + settings->order_support[NEG_MEM3BLT_INDEX] = FALSE; + settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; + settings->order_support[NEG_MEM3BLT_V2_INDEX] = FALSE; + settings->order_support[NEG_SAVEBITMAP_INDEX] = FALSE; + settings->order_support[NEG_GLYPH_INDEX_INDEX] = TRUE; + settings->order_support[NEG_FAST_INDEX_INDEX] = TRUE; + settings->order_support[NEG_FAST_GLYPH_INDEX] = TRUE; + settings->order_support[NEG_POLYGON_SC_INDEX] = FALSE; + settings->order_support[NEG_POLYGON_CB_INDEX] = FALSE; + settings->order_support[NEG_ELLIPSE_SC_INDEX] = FALSE; + settings->order_support[NEG_ELLIPSE_CB_INDEX] = FALSE; +#endif + +} + +#else + +void guac_rdp_commit_settings(guac_rdp_settings* guac_settings, rdpSettings* rdp_settings) { + /* STUB */ +} + +#endif + diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h new file mode 100644 index 00000000..32159595 --- /dev/null +++ b/src/protocols/rdp/rdp_settings.h @@ -0,0 +1,148 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-rdp. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GUAC_RDP_SETTINGS_H +#define __GUAC_RDP_SETTINGS_H + +#include +#include + +/** + * The default RDP port. + */ +#define RDP_DEFAULT_PORT 3389 + +/** + * Default screen width, in pixels. + */ +#define RDP_DEFAULT_WIDTH 1024 + +/** + * Default screen height, in pixels. + */ +#define RDP_DEFAULT_HEIGHT 768 + +/** + * Default color depth, in bits. + */ +#define RDP_DEFAULT_DEPTH 16 + +/** + * All settings supported by the Guacamole RDP client. + */ +typedef struct guac_rdp_settings { + + /** + * The hostname to connect to. + */ + char* hostname; + + /** + * The port to connect to. + */ + int port; + + /** + * The domain of the user logging in. + */ + char* domain; + + /** + * The username of the user logging in. + */ + char* username; + + /** + * The password of the user logging in. + */ + char* password; + + /** + * The color depth of the display to request, in bits. + */ + int color_depth; + + /** + * The width of the display to request, in pixels. + */ + int width; + + /** + * The height of the display to request, in pixels. + */ + int height; + + /** + * Whether audio is enabled. + */ + int audio_enabled; + + /** + * Whether printing is enabled. + */ + int printing_enabled; + + /** + * Whether this session is a console session. + */ + int console; + + /** + * Whether to allow audio in the console session. + */ + int console_audio; + + /** + * The keymap chosen as the layout of the server. + */ + const guac_rdp_keymap* server_layout; + + /** + * The initial program to run, if any. + */ + char* initial_program; + +} guac_rdp_settings; + + +/** + * Save all given settings to the given rdpSettings object. + */ +void guac_rdp_commit_settings(guac_rdp_settings* guac_settings, rdpSettings* rdp_settings); + +#endif +