You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/09/26 12:44:26 UTC

[05/19] guacamole-server git commit: GUACAMOLE-623: Add base skeleton for Kubernetes protocol support.

GUACAMOLE-623: Add base skeleton for Kubernetes protocol support.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-server/commit/b8bd0e4c
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-server/tree/b8bd0e4c
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-server/diff/b8bd0e4c

Branch: refs/heads/master
Commit: b8bd0e4c6a63995c18050fa4f88fa09b97f7a90c
Parents: 54fda21
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Sep 9 20:03:40 2018 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Sep 25 21:30:51 2018 -0700

----------------------------------------------------------------------
 Makefile.am                           |   4 +
 configure.ac                          |  60 ++++-
 src/protocols/kubernetes/Makefile.am  |  57 +++++
 src/protocols/kubernetes/client.c     |  91 +++++++
 src/protocols/kubernetes/client.h     |  41 ++++
 src/protocols/kubernetes/clipboard.c  |  67 ++++++
 src/protocols/kubernetes/clipboard.h  |  43 ++++
 src/protocols/kubernetes/input.c      |  95 ++++++++
 src/protocols/kubernetes/input.h      |  46 ++++
 src/protocols/kubernetes/kubernetes.c | 136 +++++++++++
 src/protocols/kubernetes/kubernetes.h |  71 ++++++
 src/protocols/kubernetes/pipe.c       |  51 ++++
 src/protocols/kubernetes/pipe.h       |  42 ++++
 src/protocols/kubernetes/settings.c   | 366 +++++++++++++++++++++++++++++
 src/protocols/kubernetes/settings.h   | 256 ++++++++++++++++++++
 src/protocols/kubernetes/user.c       | 116 +++++++++
 src/protocols/kubernetes/user.h       |  38 +++
 17 files changed, 1572 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index e923376..91c8abe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,10 @@ if ENABLE_PULSE
 SUBDIRS += src/pulse
 endif
 
+if ENABLE_KUBERNETES
+SUBDIRS += src/protocols/kubernetes
+endif
+
 if ENABLE_RDP
 SUBDIRS += src/protocols/rdp
 endif

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 6b20c97..ae78324 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1173,6 +1173,46 @@ AM_CONDITIONAL([ENABLE_WEBP], [test "x${have_webp}" = "xyes"])
 AC_SUBST(WEBP_LIBS)
 
 #
+# libwebsockets
+#
+
+have_libwebsockets=disabled
+WEBSOCKETS_LIBS=
+AC_ARG_WITH([websockets],
+            [AS_HELP_STRING([--with-websockets],
+                            [support WebSockets @<:@default=check@:>@])],
+            [],
+            [with_websockets=check])
+
+if test "x$with_websockets" != "xno"
+then
+    have_libwebsockets=yes
+    AC_CHECK_LIB([websockets],
+                 [lws_create_context],
+                 [WEBSOCKETS_LIBS="$WEBSOCKETS_LIBS -lwebsockets"],
+                 [have_libwebsockets=no])
+fi
+
+AM_CONDITIONAL([ENABLE_WEBSOCKETS],
+               [test "x${have_libwebsockets}"  = "xyes"])
+
+AC_SUBST(WEBSOCKETS_LIBS)
+
+#
+# Kubernetes
+#
+
+AC_ARG_ENABLE([kubernetes],
+              [AS_HELP_STRING([--disable-kubernetes],
+                              [do not build support for attaching to Kubernetes pods])],
+              [],
+              [enable_kubernetes=yes])
+
+AM_CONDITIONAL([ENABLE_KUBERNETES], [test "x${enable_kubernetes}"  = "xyes" \
+                                       -a "x${have_libwebsockets}" = "xyes" \
+                                       -a "x${have_terminal}"      = "xyes"])
+
+#
 # guacd
 #
 
@@ -1230,6 +1270,7 @@ AC_CONFIG_FILES([Makefile
                  src/guaclog/Makefile
                  src/guaclog/man/guaclog.1
                  src/pulse/Makefile
+                 src/protocols/kubernetes/Makefile
                  src/protocols/rdp/Makefile
                  src/protocols/ssh/Makefile
                  src/protocols/telnet/Makefile
@@ -1240,10 +1281,11 @@ AC_OUTPUT
 # Protocol build status
 #
 
-AM_COND_IF([ENABLE_RDP],    [build_rdp=yes],    [build_rdp=no])
-AM_COND_IF([ENABLE_SSH],    [build_ssh=yes],    [build_ssh=no])
-AM_COND_IF([ENABLE_TELNET], [build_telnet=yes], [build_telnet=no])
-AM_COND_IF([ENABLE_VNC],    [build_vnc=yes],    [build_vnc=no])
+AM_COND_IF([ENABLE_KUBERNETES], [build_kubernetes=yes], [build_kubernetes=no])
+AM_COND_IF([ENABLE_RDP],        [build_rdp=yes],        [build_rdp=no])
+AM_COND_IF([ENABLE_SSH],        [build_ssh=yes],        [build_ssh=no])
+AM_COND_IF([ENABLE_TELNET],     [build_telnet=yes],     [build_telnet=no])
+AM_COND_IF([ENABLE_VNC],        [build_vnc=yes],        [build_vnc=no])
 
 #
 # Service / tool build status
@@ -1287,15 +1329,17 @@ $PACKAGE_NAME version $PACKAGE_VERSION
      libVNCServer ........ ${have_libvncserver}
      libvorbis ........... ${have_vorbis}
      libpulse ............ ${have_pulse}
+     libwebsockets ....... ${have_websockets}
      libwebp ............. ${have_webp}
      wsock32 ............. ${have_winsock}
 
    Protocol support:
 
-      RDP ....... ${build_rdp}
-      SSH ....... ${build_ssh}
-      Telnet .... ${build_telnet}
-      VNC ....... ${build_vnc}
+      Kubernetes .... ${build_kubernetes}
+      RDP ........... ${build_rdp}
+      SSH ........... ${build_ssh}
+      Telnet ........ ${build_telnet}
+      VNC ........... ${build_vnc}
 
    Services / tools:
 

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/Makefile.am
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/Makefile.am b/src/protocols/kubernetes/Makefile.am
new file mode 100644
index 0000000..d864967
--- /dev/null
+++ b/src/protocols/kubernetes/Makefile.am
@@ -0,0 +1,57 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+AUTOMAKE_OPTIONS = foreign
+ACLOCAL_AMFLAGS = -I m4
+
+lib_LTLIBRARIES = libguac-client-kubernetes.la
+
+libguac_client_kubernetes_la_SOURCES = \
+    client.c                           \
+    clipboard.c                        \
+    input.c                            \
+    pipe.c                             \
+    settings.c                         \
+    kubernetes.c                       \
+    user.c
+
+noinst_HEADERS = \
+    client.h     \
+    clipboard.h  \
+    input.h      \
+    pipe.h       \
+    settings.h   \
+    kubernetes.h \
+    user.h
+
+libguac_client_kubernetes_la_CFLAGS = \
+    -Werror -Wall -Iinclude           \
+    @LIBGUAC_INCLUDE@                 \
+    @TERMINAL_INCLUDE@
+
+libguac_client_kubernetes_la_LIBADD = \
+    @COMMON_LTLIB@                    \
+    @LIBGUAC_LTLIB@                   \
+    @TERMINAL_LTLIB@
+
+libguac_client_kubernetes_la_LDFLAGS = \
+    -version-info 0:0:0                \
+    @PTHREAD_LIBS@                     \
+    @WEBSOCKETS_LIBS@
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/client.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/client.c b/src/protocols/kubernetes/client.c
new file mode 100644
index 0000000..1b5d175
--- /dev/null
+++ b/src/protocols/kubernetes/client.c
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "client.h"
+#include "common/recording.h"
+#include "kubernetes.h"
+#include "settings.h"
+#include "terminal/terminal.h"
+#include "user.h"
+
+#include <langinfo.h>
+#include <locale.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <guacamole/client.h>
+
+int guac_client_init(guac_client* client) {
+
+    /* Set client args */
+    client->args = GUAC_KUBERNETES_CLIENT_ARGS;
+
+    /* Allocate client instance data */
+    guac_kubernetes_client* kubernetes_client = calloc(1, sizeof(guac_kubernetes_client));
+    client->data = kubernetes_client;
+
+    /* Init clipboard */
+    kubernetes_client->clipboard = guac_common_clipboard_alloc(GUAC_KUBERNETES_CLIPBOARD_MAX_LENGTH);
+
+    /* Set handlers */
+    client->join_handler = guac_kubernetes_user_join_handler;
+    client->free_handler = guac_kubernetes_client_free_handler;
+
+    /* Set locale and warn if not UTF-8 */
+    setlocale(LC_CTYPE, "");
+    if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) {
+        guac_client_log(client, GUAC_LOG_INFO,
+                "Current locale does not use UTF-8. Some characters may "
+                "not render correctly.");
+    }
+
+    /* Success */
+    return 0;
+
+}
+
+int guac_kubernetes_client_free_handler(guac_client* client) {
+
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Clean up recording, if in progress */
+    if (kubernetes_client->recording != NULL)
+        guac_common_recording_free(kubernetes_client->recording);
+
+    /* Kill terminal */
+    guac_terminal_free(kubernetes_client->term);
+
+    /* TODO: Wait for and free WebSocket session, if connected */
+    /*if (kubernetes_client->websocket != NULL) {
+        pthread_join(kubernetes_client->client_thread, NULL);
+    }*/
+
+    /* Free settings */
+    if (kubernetes_client->settings != NULL)
+        guac_kubernetes_settings_free(kubernetes_client->settings);
+
+    guac_common_clipboard_free(kubernetes_client->clipboard);
+    free(kubernetes_client);
+    return 0;
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/client.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/client.h b/src/protocols/kubernetes/client.h
new file mode 100644
index 0000000..2e96d10
--- /dev/null
+++ b/src/protocols/kubernetes/client.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_CLIENT_H
+#define GUAC_KUBERNETES_CLIENT_H
+
+#include "config.h"
+#include "terminal/terminal.h"
+
+#include <pthread.h>
+#include <sys/types.h>
+
+/**
+ * The maximum number of bytes to allow within the clipboard.
+ */
+#define GUAC_KUBERNETES_CLIPBOARD_MAX_LENGTH 262144
+
+/**
+ * Free handler. Required by libguac and called when the guac_client is
+ * disconnected and must be cleaned up.
+ */
+guac_client_free_handler guac_kubernetes_client_free_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/clipboard.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/clipboard.c b/src/protocols/kubernetes/clipboard.c
new file mode 100644
index 0000000..87a34b0
--- /dev/null
+++ b/src/protocols/kubernetes/clipboard.c
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "clipboard.h"
+#include "common/clipboard.h"
+#include "kubernetes.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+
+int guac_kubernetes_clipboard_handler(guac_user* user, guac_stream* stream,
+        char* mimetype) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Clear clipboard and prepare for new data */
+    guac_common_clipboard_reset(kubernetes_client->clipboard, mimetype);
+
+    /* Set handlers for clipboard stream */
+    stream->blob_handler = guac_kubernetes_clipboard_blob_handler;
+    stream->end_handler = guac_kubernetes_clipboard_end_handler;
+
+    return 0;
+}
+
+int guac_kubernetes_clipboard_blob_handler(guac_user* user,
+        guac_stream* stream, void* data, int length) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Append new data */
+    guac_common_clipboard_append(kubernetes_client->clipboard, data, length);
+
+    return 0;
+}
+
+int guac_kubernetes_clipboard_end_handler(guac_user* user,
+        guac_stream* stream) {
+
+    /* Nothing to do - clipboard is implemented within client */
+
+    return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/clipboard.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/clipboard.h b/src/protocols/kubernetes/clipboard.h
new file mode 100644
index 0000000..009219c
--- /dev/null
+++ b/src/protocols/kubernetes/clipboard.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_CLIPBOARD_H
+#define GUAC_KUBERNETES_CLIPBOARD_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * Handler for inbound clipboard streams.
+ */
+guac_user_clipboard_handler guac_kubernetes_clipboard_handler;
+
+/**
+ * Handler for data received along clipboard streams.
+ */
+guac_user_blob_handler guac_kubernetes_clipboard_blob_handler;
+
+/**
+ * Handler for end-of-stream related to clipboard.
+ */
+guac_user_end_handler guac_kubernetes_clipboard_end_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/input.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/input.c b/src/protocols/kubernetes/input.c
new file mode 100644
index 0000000..9bf5b71
--- /dev/null
+++ b/src/protocols/kubernetes/input.c
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "common/recording.h"
+#include "kubernetes.h"
+#include "input.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/client.h>
+#include <guacamole/user.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int guac_kubernetes_user_mouse_handler(guac_user* user,
+        int x, int y, int mask) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Skip if terminal not yet ready */
+    guac_terminal* term = kubernetes_client->term;
+    if (term == NULL)
+        return 0;
+
+    /* Report mouse position within recording */
+    if (kubernetes_client->recording != NULL)
+        guac_common_recording_report_mouse(kubernetes_client->recording, x, y,
+                mask);
+
+    guac_terminal_send_mouse(term, user, x, y, mask);
+    return 0;
+
+}
+
+int guac_kubernetes_user_key_handler(guac_user* user, int keysym, int pressed) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Report key state within recording */
+    if (kubernetes_client->recording != NULL)
+        guac_common_recording_report_key(kubernetes_client->recording,
+                keysym, pressed);
+
+    /* Skip if terminal not yet ready */
+    guac_terminal* term = kubernetes_client->term;
+    if (term == NULL)
+        return 0;
+
+    guac_terminal_send_key(term, keysym, pressed);
+    return 0;
+
+}
+
+int guac_kubernetes_user_size_handler(guac_user* user, int width, int height) {
+
+    /* Get terminal */
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Skip if terminal not yet ready */
+    guac_terminal* terminal = kubernetes_client->term;
+    if (terminal == NULL)
+        return 0;
+
+    /* Resize terminal */
+    guac_terminal_resize(terminal, width, height);
+
+    /* TODO: Update Kubernetes terminal window size if connected */
+
+    return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/input.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/input.h b/src/protocols/kubernetes/input.h
new file mode 100644
index 0000000..ac65835
--- /dev/null
+++ b/src/protocols/kubernetes/input.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_INPUT_H
+#define GUAC_KUBERNETES_INPUT_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * Handler for key events. Required by libguac and called whenever key events
+ * are received.
+ */
+guac_user_key_handler guac_kubernetes_user_key_handler;
+
+/**
+ * Handler for mouse events. Required by libguac and called whenever mouse
+ * events are received.
+ */
+guac_user_mouse_handler guac_kubernetes_user_mouse_handler;
+
+/**
+ * Handler for size events. Required by libguac and called whenever the remote
+ * display (window) is resized.
+ */
+guac_user_size_handler guac_kubernetes_user_size_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/kubernetes.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c
new file mode 100644
index 0000000..231d78d
--- /dev/null
+++ b/src/protocols/kubernetes/kubernetes.c
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "common/recording.h"
+#include "kubernetes.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/client.h>
+#include <guacamole/protocol.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+/**
+ * Input thread, started by the main Kubernetes client thread. This thread
+ * continuously reads from the terminal's STDIN and transfers all read
+ * data to the Kubernetes connection.
+ *
+ * @param data
+ *     The current guac_client instance.
+ *
+ * @return
+ *     Always NULL.
+ */
+static void* guac_kubernetes_input_thread(void* data) {
+
+    guac_client* client = (guac_client*) data;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    char buffer[8192];
+    int bytes_read;
+
+    /* Write all data read */
+    while ((bytes_read = guac_terminal_read_stdin(kubernetes_client->term, buffer, sizeof(buffer))) > 0) {
+
+        /* TODO: Send to Kubernetes */
+        guac_terminal_write(kubernetes_client->term, buffer, bytes_read);
+
+    }
+
+    return NULL;
+
+}
+
+void* guac_kubernetes_client_thread(void* data) {
+
+    guac_client* client = (guac_client*) data;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    guac_kubernetes_settings* settings = kubernetes_client->settings;
+
+    pthread_t input_thread;
+
+    /* Set up screen recording, if requested */
+    if (settings->recording_path != NULL) {
+        kubernetes_client->recording = guac_common_recording_create(client,
+                settings->recording_path,
+                settings->recording_name,
+                settings->create_recording_path,
+                !settings->recording_exclude_output,
+                !settings->recording_exclude_mouse,
+                settings->recording_include_keys);
+    }
+
+    /* Create terminal */
+    kubernetes_client->term = guac_terminal_create(client,
+            kubernetes_client->clipboard,
+            settings->max_scrollback, settings->font_name, settings->font_size,
+            settings->resolution, settings->width, settings->height,
+            settings->color_scheme, settings->backspace);
+
+    /* Fail if terminal init failed */
+    if (kubernetes_client->term == NULL) {
+        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
+                "Terminal initialization failed");
+        return NULL;
+    }
+
+    /* Set up typescript, if requested */
+    if (settings->typescript_path != NULL) {
+        guac_terminal_create_typescript(kubernetes_client->term,
+                settings->typescript_path,
+                settings->typescript_name,
+                settings->create_typescript_path);
+    }
+
+    /* TODO: Open WebSocket connection to Kubernetes */
+
+    /* Logged in */
+    guac_client_log(client, GUAC_LOG_INFO,
+            "Kubernetes connection successful.");
+
+    /* Start input thread */
+    if (pthread_create(&(input_thread), NULL, guac_kubernetes_input_thread, (void*) client)) {
+        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
+        return NULL;
+    }
+
+    /* TODO: While data available, write to terminal */
+
+    /* Kill client and Wait for input thread to die */
+    guac_client_stop(client);
+    pthread_join(input_thread, NULL);
+
+    guac_client_log(client, GUAC_LOG_INFO, "Kubernetes connection ended.");
+    return NULL;
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/kubernetes.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/kubernetes.h b/src/protocols/kubernetes/kubernetes.h
new file mode 100644
index 0000000..f8035ae
--- /dev/null
+++ b/src/protocols/kubernetes/kubernetes.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_H
+#define GUAC_KUBERNETES_H
+
+#include "config.h"
+#include "common/clipboard.h"
+#include "common/recording.h"
+#include "settings.h"
+#include "terminal/terminal.h"
+
+#include <stdint.h>
+
+/**
+ * Kubernetes-specific client data.
+ */
+typedef struct guac_kubernetes_client {
+
+    /**
+     * Kubernetes connection settings.
+     */
+    guac_kubernetes_settings* settings;
+
+    /**
+     * The Kubernetes client thread.
+     */
+    pthread_t client_thread;
+
+    /**
+     * The current clipboard contents.
+     */
+    guac_common_clipboard* clipboard;
+
+    /**
+     * The terminal which will render all output from the Kubernetes pod.
+     */
+    guac_terminal* term;
+
+    /**
+     * The in-progress session recording, or NULL if no recording is in
+     * progress.
+     */
+    guac_common_recording* recording;
+
+} guac_kubernetes_client;
+
+/**
+ * Main Kubernetes client thread, handling transfer of STDOUT/STDERR of an
+ * attached Kubernetes pod to STDOUT of the terminal.
+ */
+void* guac_kubernetes_client_thread(void* data);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/pipe.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/pipe.c b/src/protocols/kubernetes/pipe.c
new file mode 100644
index 0000000..242105b
--- /dev/null
+++ b/src/protocols/kubernetes/pipe.c
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+#include "kubernetes.h"
+#include "pipe.h"
+#include "terminal/terminal.h"
+
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+
+#include <string.h>
+
+int guac_kubernetes_pipe_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* name) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Redirect STDIN if pipe has required name */
+    if (strcmp(name, GUAC_KUBERNETES_STDIN_PIPE_NAME) == 0) {
+        guac_terminal_send_stream(kubernetes_client->term, user, stream);
+        return 0;
+    }
+
+    /* No other inbound pipe streams are supported */
+    guac_protocol_send_ack(user->socket, stream, "No such input stream.",
+            GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/pipe.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/pipe.h b/src/protocols/kubernetes/pipe.h
new file mode 100644
index 0000000..7acae3c
--- /dev/null
+++ b/src/protocols/kubernetes/pipe.h
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#ifndef GUAC_KUBERNETES_PIPE_H
+#define GUAC_KUBERNETES_PIPE_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * The name reserved for the inbound pipe stream which forces the terminal
+ * emulator's STDIN to be received from the pipe.
+ */
+#define GUAC_KUBERNETES_STDIN_PIPE_NAME "STDIN"
+
+/**
+ * Handles an incoming stream from a Guacamole "pipe" instruction. If the pipe
+ * is named "STDIN", the the contents of the pipe stream are redirected to
+ * STDIN of the terminal emulator for as long as the pipe is open.
+ */
+guac_user_pipe_handler guac_kubernetes_pipe_handler;
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/settings.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/settings.c b/src/protocols/kubernetes/settings.c
new file mode 100644
index 0000000..1f04b40
--- /dev/null
+++ b/src/protocols/kubernetes/settings.c
@@ -0,0 +1,366 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+
+#include "settings.h"
+
+#include <guacamole/user.h>
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* Client plugin arguments */
+const char* GUAC_KUBERNETES_CLIENT_ARGS[] = {
+    "hostname",
+    "port",
+    "use-ssl",
+    "client-cert-file",
+    "client-key-file",
+    "ca-cert-file",
+    "ignore-cert",
+    "font-name",
+    "font-size",
+    "color-scheme",
+    "typescript-path",
+    "typescript-name",
+    "create-typescript-path",
+    "recording-path",
+    "recording-name",
+    "recording-exclude-output",
+    "recording-exclude-mouse",
+    "recording-include-keys",
+    "create-recording-path",
+    "read-only",
+    "backspace",
+    "scrollback",
+    NULL
+};
+
+enum KUBERNETES_ARGS_IDX {
+
+    /**
+     * The hostname to connect to. Required.
+     */
+    IDX_HOSTNAME,
+
+    /**
+     * The port to connect to. Optional.
+     */
+    IDX_PORT,
+
+    /**
+     * Whether SSL/TLS should be used. SSL is used by default.
+     */
+    IDX_USE_SSL,
+
+    /**
+     * The filename of the certificate to use if performing SSL/TLS client
+     * authentication to authenticate with the Kubernetes server. If omitted,
+     * SSL client authentication will not be performed. 
+     */
+    IDX_CLIENT_CERT_FILE,
+
+    /**
+     * The filename of the key to use if performing SSL/TLS client
+     * authentication to authenticate with the Kubernetes server. If omitted,
+     * SSL client authentication will not be performed. 
+     */
+    IDX_CLIENT_KEY_FILE,
+
+    /**
+     * The filename of the certificate of the certificate authority that signed
+     * the certificate of the Kubernetes server.
+     */
+    IDX_CA_CERT_FILE,
+
+    /**
+     * Whether the certificate used by the Kubernetes server for SSL/TLS should
+     * be ignored if it cannot be validated.
+     */
+    IDX_IGNORE_CERT,
+
+    /**
+     * The name of the font to use within the terminal.
+     */
+    IDX_FONT_NAME,
+
+    /**
+     * The size of the font to use within the terminal, in points.
+     */
+    IDX_FONT_SIZE,
+
+    /**
+     * The color scheme to use, as a series of semicolon-separated color-value
+     * pairs: "background: <color>", "foreground: <color>", or
+     * "color<n>: <color>", where <n> is a number from 0 to 255, and <color> is
+     * "color<n>" or an X11 color code (e.g. "aqua" or "rgb:12/34/56").
+     * The color scheme can also be one of the special values: "black-white",
+     * "white-black", "gray-black", or "green-black".
+     */
+    IDX_COLOR_SCHEME,
+
+    /**
+     * The full absolute path to the directory in which typescripts should be
+     * written.
+     */
+    IDX_TYPESCRIPT_PATH,
+
+    /**
+     * The name that should be given to typescripts which are written in the
+     * given path. Each typescript will consist of two files: "NAME" and
+     * "NAME.timing".
+     */
+    IDX_TYPESCRIPT_NAME,
+
+    /**
+     * Whether the specified typescript path should automatically be created
+     * if it does not yet exist.
+     */
+    IDX_CREATE_TYPESCRIPT_PATH,
+
+    /**
+     * The full absolute path to the directory in which screen recordings
+     * should be written.
+     */
+    IDX_RECORDING_PATH,
+
+    /**
+     * The name that should be given to screen recordings which are written in
+     * the given path.
+     */
+    IDX_RECORDING_NAME,
+
+    /**
+     * Whether output which is broadcast to each connected client (graphics,
+     * streams, etc.) should NOT be included in the session recording. Output
+     * is included by default, as it is necessary for any recording which must
+     * later be viewable as video.
+     */
+    IDX_RECORDING_EXCLUDE_OUTPUT,
+
+    /**
+     * Whether changes to mouse state, such as position and buttons pressed or
+     * released, should NOT be included in the session recording. Mouse state
+     * is included by default, as it is necessary for the mouse cursor to be
+     * rendered in any resulting video.
+     */
+    IDX_RECORDING_EXCLUDE_MOUSE,
+
+    /**
+     * Whether keys pressed and released should be included in the session
+     * recording. Key events are NOT included by default within the recording,
+     * as doing so has privacy and security implications.  Including key events
+     * may be necessary in certain auditing contexts, but should only be done
+     * with caution. Key events can easily contain sensitive information, such
+     * as passwords, credit card numbers, etc.
+     */
+    IDX_RECORDING_INCLUDE_KEYS,
+
+    /**
+     * Whether the specified screen recording path should automatically be
+     * created if it does not yet exist.
+     */
+    IDX_CREATE_RECORDING_PATH,
+
+    /**
+     * "true" if this connection should be read-only (user input should be
+     * dropped), "false" or blank otherwise.
+     */
+    IDX_READ_ONLY,
+
+    /**
+     * ASCII code, as an integer to use for the backspace key, or 127
+     * if not specified.
+     */
+    IDX_BACKSPACE,
+
+    /**
+     * The maximum size of the scrollback buffer in rows.
+     */
+    IDX_SCROLLBACK,
+
+    KUBERNETES_ARGS_COUNT
+};
+
+guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user,
+        int argc, const char** argv) {
+
+    /* Validate arg count */
+    if (argc != KUBERNETES_ARGS_COUNT) {
+        guac_user_log(user, GUAC_LOG_WARNING, "Incorrect number of connection "
+                "parameters provided: expected %i, got %i.",
+                KUBERNETES_ARGS_COUNT, argc);
+        return NULL;
+    }
+
+    guac_kubernetes_settings* settings =
+        calloc(1, sizeof(guac_kubernetes_settings));
+
+    /* Read parameters */
+    settings->hostname =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_HOSTNAME, "");
+
+    /* Parse whether SSL should be used */
+    settings->use_ssl =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_USE_SSL, true);
+
+    /* Read SSL/TLS connection details only if enabled */
+    if (settings->use_ssl) {
+
+        settings->client_cert_file =
+            guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS,
+                    argv, IDX_CLIENT_CERT_FILE, NULL);
+
+        settings->client_key_file =
+            guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS,
+                    argv, IDX_CLIENT_KEY_FILE, NULL);
+
+        settings->ca_cert_file =
+            guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS,
+                    argv, IDX_CA_CERT_FILE, NULL);
+
+        settings->ignore_cert =
+            guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS,
+                    argv, IDX_IGNORE_CERT, false);
+
+    }
+
+    /* Read-only mode */
+    settings->read_only =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_READ_ONLY, false);
+
+    /* Read maximum scrollback size */
+    settings->max_scrollback =
+        guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_SCROLLBACK, GUAC_KUBERNETES_DEFAULT_MAX_SCROLLBACK);
+
+    /* Read font name */
+    settings->font_name =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_FONT_NAME, GUAC_KUBERNETES_DEFAULT_FONT_NAME);
+
+    /* Read font size */
+    settings->font_size =
+        guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_FONT_SIZE, GUAC_KUBERNETES_DEFAULT_FONT_SIZE);
+
+    /* Copy requested color scheme */
+    settings->color_scheme =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_COLOR_SCHEME, "");
+
+    /* Pull width/height/resolution directly from user */
+    settings->width      = user->info.optimal_width;
+    settings->height     = user->info.optimal_height;
+    settings->resolution = user->info.optimal_resolution;
+
+    /* Read port */
+    settings->port =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_PORT, GUAC_KUBERNETES_DEFAULT_PORT);
+
+    /* Read typescript path */
+    settings->typescript_path =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_TYPESCRIPT_PATH, NULL);
+
+    /* Read typescript name */
+    settings->typescript_name =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_TYPESCRIPT_NAME, GUAC_KUBERNETES_DEFAULT_TYPESCRIPT_NAME);
+
+    /* Parse path creation flag */
+    settings->create_typescript_path =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_CREATE_TYPESCRIPT_PATH, false);
+
+    /* Read recording path */
+    settings->recording_path =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_RECORDING_PATH, NULL);
+
+    /* Read recording name */
+    settings->recording_name =
+        guac_user_parse_args_string(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_RECORDING_NAME, GUAC_KUBERNETES_DEFAULT_RECORDING_NAME);
+
+    /* Parse output exclusion flag */
+    settings->recording_exclude_output =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_RECORDING_EXCLUDE_OUTPUT, false);
+
+    /* Parse mouse exclusion flag */
+    settings->recording_exclude_mouse =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_RECORDING_EXCLUDE_MOUSE, false);
+
+    /* Parse key event inclusion flag */
+    settings->recording_include_keys =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_RECORDING_INCLUDE_KEYS, false);
+
+    /* Parse path creation flag */
+    settings->create_recording_path =
+        guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_CREATE_RECORDING_PATH, false);
+
+    /* Parse backspace key code */
+    settings->backspace =
+        guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
+                IDX_BACKSPACE, 127);
+
+    /* Parsing was successful */
+    return settings;
+
+}
+
+void guac_kubernetes_settings_free(guac_kubernetes_settings* settings) {
+
+    /* Free network connection information */
+    free(settings->hostname);
+    free(settings->port);
+
+    /* Free SSL/TLS details */
+    free(settings->client_cert_file);
+    free(settings->client_key_file);
+    free(settings->ca_cert_file);
+
+    /* Free display preferences */
+    free(settings->font_name);
+    free(settings->color_scheme);
+
+    /* Free typescript settings */
+    free(settings->typescript_name);
+    free(settings->typescript_path);
+
+    /* Free screen recording settings */
+    free(settings->recording_name);
+    free(settings->recording_path);
+
+    /* Free overall structure */
+    free(settings);
+
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/settings.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/settings.h b/src/protocols/kubernetes/settings.h
new file mode 100644
index 0000000..3e89ce5
--- /dev/null
+++ b/src/protocols/kubernetes/settings.h
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_SETTINGS_H
+#define GUAC_KUBERNETES_SETTINGS_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+
+/**
+ * The name of the font to use for the terminal if no name is specified.
+ */
+#define GUAC_KUBERNETES_DEFAULT_FONT_NAME "monospace" 
+
+/**
+ * The size of the font to use for the terminal if no font size is specified,
+ * in points.
+ */
+#define GUAC_KUBERNETES_DEFAULT_FONT_SIZE 12
+
+/**
+ * The port to connect to when initiating any Kubernetes connection, if no
+ * other port is specified.
+ */
+#define GUAC_KUBERNETES_DEFAULT_PORT "8443"
+
+/**
+ * The filename to use for the typescript, if not specified.
+ */
+#define GUAC_KUBERNETES_DEFAULT_TYPESCRIPT_NAME "typescript" 
+
+/**
+ * The filename to use for the screen recording, if not specified.
+ */
+#define GUAC_KUBERNETES_DEFAULT_RECORDING_NAME "recording"
+
+/**
+ * The default maximum scrollback size in rows.
+ */
+#define GUAC_KUBERNETES_DEFAULT_MAX_SCROLLBACK 1000
+
+/**
+ * Settings for the Kubernetes connection. The values for this structure are
+ * parsed from the arguments given during the Guacamole protocol handshake
+ * using the guac_kubernetes_parse_args() function.
+ */
+typedef struct guac_kubernetes_settings {
+
+    /**
+     * The hostname of the Kubernetes server to connect to.
+     */
+    char* hostname;
+
+    /**
+     * The port of the Kubernetes server to connect to.
+     */
+    char* port;
+
+    /**
+     * Whether SSL/TLS should be used.
+     */
+    bool use_ssl;
+
+    /**
+     * The filename of the certificate to use if performing SSL/TLS client
+     * authentication to authenticate with the Kubernetes server. If omitted,
+     * SSL client authentication will not be performed.
+     */
+    char* client_cert_file;
+
+    /**
+     * The filename of the key to use if performing SSL/TLS client
+     * authentication to authenticate with the Kubernetes server. If omitted,
+     * SSL client authentication will not be performed. 
+     */
+    char* client_key_file;
+
+    /**
+     * The filename of the certificate of the certificate authority that signed
+     * the certificate of the Kubernetes server.
+     */
+    char* ca_cert_file;
+
+    /**
+     * Whether the certificate used by the Kubernetes server for SSL/TLS should
+     * be ignored if it cannot be validated.
+     */
+    bool ignore_cert;
+
+    /**
+     * Whether this connection is read-only, and user input should be dropped.
+     */
+    bool read_only;
+
+    /**
+     * The maximum size of the scrollback buffer in rows.
+     */
+    int max_scrollback;
+
+    /**
+     * The name of the font to use for display rendering.
+     */
+    char* font_name;
+
+    /**
+     * The size of the font to use, in points.
+     */
+    int font_size;
+
+    /**
+     * The name of the color scheme to use.
+     */
+    char* color_scheme; 
+
+    /**
+     * The desired width of the terminal display, in pixels.
+     */
+    int width;
+
+    /**
+     * The desired height of the terminal display, in pixels.
+     */
+    int height;
+
+    /**
+     * The desired screen resolution, in DPI.
+     */
+    int resolution;
+
+    /**
+     * The path in which the typescript should be saved, if enabled. If no
+     * typescript should be saved, this will be NULL.
+     */
+    char* typescript_path;
+
+    /**
+     * The filename to use for the typescript, if enabled.
+     */
+    char* typescript_name;
+
+    /**
+     * Whether the typescript path should be automatically created if it does
+     * not already exist.
+     */
+    bool create_typescript_path;
+
+    /**
+     * The path in which the screen recording should be saved, if enabled. If
+     * no screen recording should be saved, this will be NULL.
+     */
+    char* recording_path;
+
+    /**
+     * The filename to use for the screen recording, if enabled.
+     */
+    char* recording_name;
+
+    /**
+     * Whether the screen recording path should be automatically created if it
+     * does not already exist.
+     */
+    bool create_recording_path;
+
+    /**
+     * Whether output which is broadcast to each connected client (graphics,
+     * streams, etc.) should NOT be included in the session recording. Output
+     * is included by default, as it is necessary for any recording which must
+     * later be viewable as video.
+     */
+    bool recording_exclude_output;
+
+    /**
+     * Whether changes to mouse state, such as position and buttons pressed or
+     * released, should NOT be included in the session recording. Mouse state
+     * is included by default, as it is necessary for the mouse cursor to be
+     * rendered in any resulting video.
+     */
+    bool recording_exclude_mouse;
+
+    /**
+     * Whether keys pressed and released should be included in the session
+     * recording. Key events are NOT included by default within the recording,
+     * as doing so has privacy and security implications.  Including key events
+     * may be necessary in certain auditing contexts, but should only be done
+     * with caution. Key events can easily contain sensitive information, such
+     * as passwords, credit card numbers, etc.
+     */
+    bool recording_include_keys;
+
+    /**
+     * The ASCII code, as an integer, that the Kubernetes client will use when
+     * the backspace key is pressed. By default, this is 127, ASCII delete, if
+     * not specified in the client settings.
+     */
+    int backspace;
+
+} guac_kubernetes_settings;
+
+/**
+ * Parses all given args, storing them in a newly-allocated settings object. If
+ * the args fail to parse, NULL is returned.
+ *
+ * @param user
+ *     The user who submitted the given arguments while joining the
+ *     connection.
+ *
+ * @param argc
+ *     The number of arguments within the argv array.
+ *
+ * @param argv
+ *     The values of all arguments provided by the user.
+ *
+ * @return
+ *     A newly-allocated settings object which must be freed with
+ *     guac_kubernetes_settings_free() when no longer needed. If the arguments
+ *     fail to parse, NULL is returned.
+ */
+guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user,
+        int argc, const char** argv);
+
+/**
+ * Frees the given guac_kubernetes_settings object, having been previously
+ * allocated via guac_kubernetes_parse_args().
+ *
+ * @param settings
+ *     The settings object to free.
+ */
+void guac_kubernetes_settings_free(guac_kubernetes_settings* settings);
+
+/**
+ * NULL-terminated array of accepted client args.
+ */
+extern const char* GUAC_KUBERNETES_CLIENT_ARGS[];
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/user.c
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/user.c b/src/protocols/kubernetes/user.c
new file mode 100644
index 0000000..62666cb
--- /dev/null
+++ b/src/protocols/kubernetes/user.c
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+
+#include "clipboard.h"
+#include "input.h"
+#include "kubernetes.h"
+#include "pipe.h"
+#include "settings.h"
+#include "terminal/terminal.h"
+#include "user.h"
+
+#include <guacamole/client.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+
+#include <pthread.h>
+#include <string.h>
+
+int guac_kubernetes_user_join_handler(guac_user* user, int argc, char** argv) {
+
+    guac_client* client = user->client;
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) client->data;
+
+    /* Parse provided arguments */
+    guac_kubernetes_settings* settings = guac_kubernetes_parse_args(user,
+            argc, (const char**) argv);
+
+    /* Fail if settings cannot be parsed */
+    if (settings == NULL) {
+        guac_user_log(user, GUAC_LOG_INFO,
+                "Badly formatted client arguments.");
+        return 1;
+    }
+
+    /* Store settings at user level */
+    user->data = settings;
+
+    /* Connect to Kubernetes if owner */
+    if (user->owner) {
+
+        /* Store owner's settings at client level */
+        kubernetes_client->settings = settings;
+
+        /* Start client thread */
+        if (pthread_create(&(kubernetes_client->client_thread), NULL,
+                    guac_kubernetes_client_thread, (void*) client)) {
+            guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
+                    "Unable to start Kubernetes client thread");
+            return 1;
+        }
+
+    }
+
+    /* If not owner, synchronize with current display */
+    else {
+        guac_terminal_dup(kubernetes_client->term, user, user->socket);
+        guac_socket_flush(user->socket);
+    }
+
+    /* Only handle events if not read-only */
+    if (!settings->read_only) {
+
+        /* General mouse/keyboard/clipboard events */
+        user->key_handler       = guac_kubernetes_user_key_handler;
+        user->mouse_handler     = guac_kubernetes_user_mouse_handler;
+        user->clipboard_handler = guac_kubernetes_clipboard_handler;
+
+        /* STDIN redirection */
+        user->pipe_handler = guac_kubernetes_pipe_handler;
+
+        /* Display size change events */
+        user->size_handler = guac_kubernetes_user_size_handler;
+
+    }
+
+    return 0;
+
+}
+
+int guac_kubernetes_user_leave_handler(guac_user* user) {
+
+    guac_kubernetes_client* kubernetes_client =
+        (guac_kubernetes_client*) user->client->data;
+
+    /* Update shared cursor state */
+    guac_common_cursor_remove_user(kubernetes_client->term->cursor, user);
+
+    /* Free settings if not owner (owner settings will be freed with client) */
+    if (!user->owner) {
+        guac_kubernetes_settings* settings =
+            (guac_kubernetes_settings*) user->data;
+        guac_kubernetes_settings_free(settings);
+    }
+
+    return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/guacamole-server/blob/b8bd0e4c/src/protocols/kubernetes/user.h
----------------------------------------------------------------------
diff --git a/src/protocols/kubernetes/user.h b/src/protocols/kubernetes/user.h
new file mode 100644
index 0000000..d235b2b
--- /dev/null
+++ b/src/protocols/kubernetes/user.h
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_KUBERNETES_USER_H
+#define GUAC_KUBERNETES_USER_H
+
+#include "config.h"
+
+#include <guacamole/user.h>
+
+/**
+ * Handler for joining users.
+ */
+guac_user_join_handler guac_kubernetes_user_join_handler;
+
+/**
+ * Handler for leaving users.
+ */
+guac_user_leave_handler guac_kubernetes_user_leave_handler;
+
+#endif
+