From 30a31d07cf94252599c81d0f02dece5b2dc41c72 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 7 May 2014 14:19:17 -0700 Subject: [PATCH] GUAC-654: Add negotiation and handling of NAWS (window size). --- src/protocols/telnet/client.c | 1 + src/protocols/telnet/client.h | 5 +++++ src/protocols/telnet/guac_handlers.c | 12 ++++------- src/protocols/telnet/telnet_client.c | 30 ++++++++++++++++++++++++++-- src/protocols/telnet/telnet_client.h | 6 ++++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/protocols/telnet/client.c b/src/protocols/telnet/client.c index 92754733..23aff3f6 100644 --- a/src/protocols/telnet/client.c +++ b/src/protocols/telnet/client.c @@ -85,6 +85,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { client->data = client_data; client_data->telnet = NULL; client_data->socket_fd = -1; + client_data->naws_enabled = 0; if (argc != TELNET_ARGS_COUNT) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Wrong number of arguments"); diff --git a/src/protocols/telnet/client.h b/src/protocols/telnet/client.h index 9b002f87..fe518702 100644 --- a/src/protocols/telnet/client.h +++ b/src/protocols/telnet/client.h @@ -72,6 +72,11 @@ typedef struct telnet_client_data { */ telnet_t* telnet; + /** + * Whether window size should be sent when the window is resized. + */ + int naws_enabled; + /** * The terminal which will render all output from the telnet client. */ diff --git a/src/protocols/telnet/guac_handlers.c b/src/protocols/telnet/guac_handlers.c index 1b364ee4..aa1860f0 100644 --- a/src/protocols/telnet/guac_handlers.c +++ b/src/protocols/telnet/guac_handlers.c @@ -25,6 +25,7 @@ #include "client.h" #include "guac_handlers.h" #include "terminal.h" +#include "telnet_client.h" #include #include @@ -70,9 +71,6 @@ int telnet_guac_client_key_handler(guac_client* client, int keysym, int pressed) int telnet_guac_client_size_handler(guac_client* client, int width, int height) { - /* STUB */ - -#if 0 /* Get terminal */ telnet_client_data* guac_client_data = (telnet_client_data*) client->data; guac_terminal* terminal = guac_client_data->term; @@ -80,11 +78,9 @@ int telnet_guac_client_size_handler(guac_client* client, int width, int height) /* Resize terminal */ guac_terminal_resize(terminal, width, height); - /* Update SSH pty size if connected */ - if (guac_client_data->term_channel != NULL) - libssh2_channel_request_pty_size(guac_client_data->term_channel, - terminal->term_width, terminal->term_height); -#endif + /* Update terminal window size if connected */ + if (guac_client_data->telnet != NULL && guac_client_data->naws_enabled) + guac_telnet_send_naws(guac_client_data->telnet, terminal->term_width, terminal->term_height); return 0; } diff --git a/src/protocols/telnet/telnet_client.c b/src/protocols/telnet/telnet_client.c index 2a322d11..46982d68 100644 --- a/src/protocols/telnet/telnet_client.c +++ b/src/protocols/telnet/telnet_client.c @@ -24,12 +24,12 @@ #include "client.h" #include "guac_handlers.h" +#include "telnet_client.h" #include #include #include #include -#include #include #include #include @@ -46,6 +46,7 @@ static const telnet_telopt_t __telnet_options[] = { { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, + { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, { -1, 0, 0 } }; @@ -87,6 +88,14 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, guac_client_stop(client); break; + /* Feature enable */ + case TELNET_EV_DO: + if (event->neg.telopt == TELNET_TELOPT_NAWS) { + client_data->naws_enabled = 1; + guac_telnet_send_naws(telnet, client_data->term->term_width, client_data->term->term_height); + } + break; + /* Terminal type request */ case TELNET_EV_TTYPE: if (event->ttype.cmd == TELNET_TTYPE_SEND) @@ -112,7 +121,7 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, } -void* telnet_input_thread(void* data) { +static void* telnet_input_thread(void* data) { guac_client* client = (guac_client*) data; telnet_client_data* client_data = (telnet_client_data*) client->data; @@ -218,6 +227,23 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) { } +static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) { + + unsigned char buffer[2]; + buffer[0] = (value >> 8) & 0xFF; + buffer[1] = value & 0xFF; + + telnet_send(telnet, (char*) buffer, 2); + +} + +void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { + telnet_begin_sb(telnet, TELNET_TELOPT_NAWS); + __guac_telnet_send_uint16(telnet, width); + __guac_telnet_send_uint16(telnet, height); + telnet_finish_sb(telnet); +} + void* telnet_client_thread(void* data) { guac_client* client = (guac_client*) data; diff --git a/src/protocols/telnet/telnet_client.h b/src/protocols/telnet/telnet_client.h index bf5823a4..396768a8 100644 --- a/src/protocols/telnet/telnet_client.h +++ b/src/protocols/telnet/telnet_client.h @@ -33,5 +33,11 @@ */ void* telnet_client_thread(void* data); +/** + * Send a telnet NAWS message indicating the given terminal window dimensions + * in characters. + */ +void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height); + #endif