GUACAMOLE-623: Add support for terminal resize. Redraw Kubernetes container upon connect.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/fe7edce5 Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/fe7edce5 Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/fe7edce5 Branch: refs/heads/master Commit: fe7edce5694a718ce233b4d4c85b386be4240262 Parents: b7c938c Author: Michael Jumper <mjum...@apache.org> Authored: Mon Sep 10 02:50:15 2018 -0700 Committer: Michael Jumper <mjum...@apache.org> Committed: Tue Sep 25 21:30:51 2018 -0700 ---------------------------------------------------------------------- src/protocols/kubernetes/input.c | 4 ++- src/protocols/kubernetes/kubernetes.c | 55 +++++++++++++++++++++++++++++- src/protocols/kubernetes/kubernetes.h | 38 +++++++++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/fe7edce5/src/protocols/kubernetes/input.c ---------------------------------------------------------------------- diff --git a/src/protocols/kubernetes/input.c b/src/protocols/kubernetes/input.c index 9bf5b71..e73772e 100644 --- a/src/protocols/kubernetes/input.c +++ b/src/protocols/kubernetes/input.c @@ -88,7 +88,9 @@ int guac_kubernetes_user_size_handler(guac_user* user, int width, int height) { /* Resize terminal */ guac_terminal_resize(terminal, width, height); - /* TODO: Update Kubernetes terminal window size if connected */ + /* Update Kubernetes terminal window size if connected */ + guac_kubernetes_resize(client, terminal->term_height, + terminal->term_width); return 0; } http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/fe7edce5/src/protocols/kubernetes/kubernetes.c ---------------------------------------------------------------------- diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index aadb448..53a8580 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -246,6 +246,11 @@ static int guac_kubernetes_lws_callback(struct lws* wsi, case LWS_CALLBACK_CLIENT_ESTABLISHED: guac_client_log(client, GUAC_LOG_INFO, "Kubernetes connection successful."); + + /* Schedule check for pending messages in case messages were added + * to the outbound message buffer prior to the connection being + * fully established */ + lws_callback_on_writable(wsi); break; /* Data received via WebSocket */ @@ -260,7 +265,6 @@ static int guac_kubernetes_lws_callback(struct lws* wsi, * yet more messages remain */ if (guac_kubernetes_write_pending_message(client)) lws_callback_on_writable(wsi); - break; /* TODO: Add configure test */ @@ -451,6 +455,11 @@ void* guac_kubernetes_client_thread(void* data) { goto fail; } + /* Force a redraw of the attached display (there will be no content + * otherwise, given the stream nature of attaching to a running + * container) */ + guac_kubernetes_force_redraw(client); + /* As long as client is connected, continue polling libwebsockets */ while (client->state == GUAC_CLIENT_RUNNING) { @@ -485,3 +494,47 @@ fail: } +void guac_kubernetes_resize(guac_client* client, int rows, int columns) { + + char buffer[64]; + + guac_kubernetes_client* kubernetes_client = + (guac_kubernetes_client*) client->data; + + /* Send request only if different from last request */ + if (kubernetes_client->rows != rows || + kubernetes_client->columns != columns) { + + kubernetes_client->rows = rows; + kubernetes_client->columns = columns; + + /* Construct terminal resize message for Kubernetes */ + int length = snprintf(buffer, sizeof(buffer), + "{\"Width\":%i,\"Height\":%i}", columns, rows); + + /* Schedule message for sending */ + guac_kubernetes_send_message(client, GUAC_KUBERNETES_CHANNEL_RESIZE, + buffer, length); + + } + +} + +void guac_kubernetes_force_redraw(guac_client* client) { + + guac_kubernetes_client* kubernetes_client = + (guac_kubernetes_client*) client->data; + + /* Get current terminal dimensions */ + guac_terminal* term = kubernetes_client->term; + int rows = term->term_height; + int columns = term->term_width; + + /* Force a redraw by increasing the terminal size by one character in + * each dimension and then resizing it back to normal (the same technique + * used by kubectl */ + guac_kubernetes_resize(client, rows + 1, columns + 1); + guac_kubernetes_resize(client, rows, columns); + +} + http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/fe7edce5/src/protocols/kubernetes/kubernetes.h ---------------------------------------------------------------------- diff --git a/src/protocols/kubernetes/kubernetes.h b/src/protocols/kubernetes/kubernetes.h index 761a897..fedf77a 100644 --- a/src/protocols/kubernetes/kubernetes.h +++ b/src/protocols/kubernetes/kubernetes.h @@ -168,6 +168,18 @@ typedef struct guac_kubernetes_client { guac_terminal* term; /** + * The number of rows last sent to Kubernetes in a terminal resize + * request. + */ + int rows; + + /** + * The number of columns last sent to Kubernetes in a terminal resize + * request. + */ + int columns; + + /** * The in-progress session recording, or NULL if no recording is in * progress. */ @@ -181,5 +193,31 @@ typedef struct guac_kubernetes_client { */ void* guac_kubernetes_client_thread(void* data); +/** + * Sends a message to the Kubernetes server requesting that the terminal be + * resized to the given dimensions. This message may be queued until the + * underlying WebSocket connection is ready to send. + * + * @param client + * The guac_client associated with the Kubernetes connection. + * + * @param rows + * The new terminal size in rows. + * + * @param columns + * The new terminal size in columns. + */ +void guac_kubernetes_resize(guac_client* client, int rows, int columns); + +/** + * Sends messages to the Kubernetes server such that the terminal is forced + * to redraw. This function should be invoked at the beginning of each + * session in order to restore expected display state. + * + * @param client + * The guac_client associated with the Kubernetes connection. + */ +void guac_kubernetes_force_redraw(guac_client* client); + #endif