You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2017/07/06 02:59:43 UTC
[09/13] incubator-guacamole-server git commit: GUACAMOLE-337: Move
libguacd functionality into libguac.
GUACAMOLE-337: Move libguacd functionality into libguac.
Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/f504b1a5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/f504b1a5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/f504b1a5
Branch: refs/heads/master
Commit: f504b1a5e883ac99a6c3f4058a150fb8c2b59c52
Parents: 5b748a4
Author: Michael Jumper <mj...@apache.org>
Authored: Sat Jul 1 15:51:15 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Sat Jul 1 18:50:03 2017 -0700
----------------------------------------------------------------------
Makefile.am | 2 -
configure.ac | 5 -
src/guacd/Makefile.am | 2 -
src/guacd/connection.c | 1 -
src/guacd/daemon.c | 1 -
src/guacd/proc-map.c | 1 -
src/guacd/proc-map.h | 1 -
src/guacd/proc.c | 3 +-
src/libguac/Makefile.am | 3 +-
src/libguac/guacamole/user.h | 24 +++
src/libguac/user-handshake.c | 437 ++++++++++++++++++++++++++++++++++++++
src/libguacd/Makefile.am | 47 ----
src/libguacd/libguacd/user.h | 48 -----
src/libguacd/log.c | 71 -------
src/libguacd/log.h | 42 ----
src/libguacd/user.c | 380 ---------------------------------
16 files changed, 464 insertions(+), 604 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index d67db2a..3ba1e34 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,6 @@ ACLOCAL_AMFLAGS = -I m4
# Subprojects
DIST_SUBDIRS = \
src/libguac \
- src/libguacd \
src/common \
src/common-ssh \
src/terminal \
@@ -38,7 +37,6 @@ DIST_SUBDIRS = \
SUBDIRS = \
src/libguac \
src/common \
- src/libguacd \
tests
if ENABLE_COMMON_SSH
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index b4cc2d3..0800250 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,10 +123,6 @@ AC_SUBST([COMMON_INCLUDE], '-I$(top_srcdir)/src/common')
AC_SUBST([PULSE_LTLIB], '$(top_builddir)/src/pulse/libguac_pulse.la')
AC_SUBST([PULSE_INCLUDE], '-I$(top_srcdir)/src/pulse')
-# Common utility library for guacd implementations
-AC_SUBST([LIBGUACD_LTLIB], '$(top_builddir)/src/libguacd/libguacd.la')
-AC_SUBST([LIBGUACD_INCLUDE], '-I$(top_srcdir)/src/libguacd')
-
# Common base SSH client
AC_SUBST([COMMON_SSH_LTLIB], '$(top_builddir)/src/common-ssh/libguac_common_ssh.la')
AC_SUBST([COMMON_SSH_INCLUDE], '-I$(top_srcdir)/src/common-ssh')
@@ -1172,7 +1168,6 @@ AC_CONFIG_FILES([Makefile
src/common-ssh/Makefile
src/terminal/Makefile
src/libguac/Makefile
- src/libguacd/Makefile
src/guacd/Makefile
src/guacenc/Makefile
src/pulse/Makefile
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/Makefile.am
----------------------------------------------------------------------
diff --git a/src/guacd/Makefile.am b/src/guacd/Makefile.am
index b9433e8..14ab5db 100644
--- a/src/guacd/Makefile.am
+++ b/src/guacd/Makefile.am
@@ -49,12 +49,10 @@ guacd_SOURCES = \
guacd_CFLAGS = \
-Werror -Wall -pedantic \
@COMMON_INCLUDE@ \
- @LIBGUACD_INCLUDE@ \
@LIBGUAC_INCLUDE@
guacd_LDADD = \
@COMMON_LTLIB@ \
- @LIBGUACD_LTLIB@ \
@LIBGUAC_LTLIB@
guacd_LDFLAGS = \
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/connection.c
----------------------------------------------------------------------
diff --git a/src/guacd/connection.c b/src/guacd/connection.c
index 6c517bf..ef767ac 100644
--- a/src/guacd/connection.c
+++ b/src/guacd/connection.c
@@ -22,7 +22,6 @@
#include "connection.h"
#include "log.h"
#include "move-fd.h"
-#include "libguacd/user.h"
#include "proc.h"
#include "proc-map.h"
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/daemon.c
----------------------------------------------------------------------
diff --git a/src/guacd/daemon.c b/src/guacd/daemon.c
index 3adf433..2e80ef3 100644
--- a/src/guacd/daemon.c
+++ b/src/guacd/daemon.c
@@ -22,7 +22,6 @@
#include "connection.h"
#include "conf-args.h"
#include "conf-file.h"
-#include "libguacd/user.h"
#include "log.h"
#include "proc-map.h"
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/proc-map.c
----------------------------------------------------------------------
diff --git a/src/guacd/proc-map.c b/src/guacd/proc-map.c
index bbe50b3..ac87196 100644
--- a/src/guacd/proc-map.c
+++ b/src/guacd/proc-map.c
@@ -19,7 +19,6 @@
#include "config.h"
#include "common/list.h"
-#include "libguacd/user.h"
#include "proc.h"
#include "proc-map.h"
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/proc-map.h
----------------------------------------------------------------------
diff --git a/src/guacd/proc-map.h b/src/guacd/proc-map.h
index 5d8ce97..a242188 100644
--- a/src/guacd/proc-map.h
+++ b/src/guacd/proc-map.h
@@ -23,7 +23,6 @@
#include "config.h"
#include "common/list.h"
-#include "libguacd/user.h"
#include "proc.h"
#include <guacamole/client.h>
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/guacd/proc.c
----------------------------------------------------------------------
diff --git a/src/guacd/proc.c b/src/guacd/proc.c
index e5e9586..0a35910 100644
--- a/src/guacd/proc.c
+++ b/src/guacd/proc.c
@@ -19,7 +19,6 @@
#include "config.h"
-#include "libguacd/user.h"
#include "log.h"
#include "move-fd.h"
#include "proc.h"
@@ -92,7 +91,7 @@ static void* guacd_user_thread(void* data) {
user->owner = params->owner;
/* Handle user connection from handshake until disconnect/completion */
- guacd_handle_user(user, GUACD_USEC_TIMEOUT);
+ guac_user_handle_connection(user, GUACD_USEC_TIMEOUT);
/* Stop client and prevent future users if all users are disconnected */
if (client->connected_users == 0) {
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguac/Makefile.am
----------------------------------------------------------------------
diff --git a/src/libguac/Makefile.am b/src/libguac/Makefile.am
index 0bfa409..a1f47ed 100644
--- a/src/libguac/Makefile.am
+++ b/src/libguac/Makefile.am
@@ -91,7 +91,8 @@ libguac_la_SOURCES = \
timestamp.c \
unicode.c \
user.c \
- user-handlers.c
+ user-handlers.c \
+ user-handshake.c
# Compile WebP support if available
if ENABLE_WEBP
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguac/guacamole/user.h
----------------------------------------------------------------------
diff --git a/src/libguac/guacamole/user.h b/src/libguac/guacamole/user.h
index c791c2d..b445f62 100644
--- a/src/libguac/guacamole/user.h
+++ b/src/libguac/guacamole/user.h
@@ -493,6 +493,30 @@ guac_user* guac_user_alloc();
void guac_user_free(guac_user* user);
/**
+ * Handles the portion of a user's Guacamole protocol handshake following the
+ * "select" instruction all subsequent I/O, automatically populating the
+ * handshake-related properties of the given guac_user and invoking
+ * guac_user_handle_instruction() for received instructions after the handshake
+ * has completed. This function blocks until the connection/user is aborted or
+ * the user disconnects.
+ *
+ * @param user
+ * The user whose handshake and entire Guacamole protocol exchange should
+ * be handled. The user must already be associated with a guac_socket and
+ * guac_client, and the guac_client must already be fully initialized.
+ *
+ * @param usec_timeout
+ * The number of microseconds to wait for instructions from the given
+ * user before closing the connection with an error.
+ *
+ * @return
+ * Zero if the user's Guacamole connection was successfully handled and
+ * the user has disconnected, or non-zero if an error prevented the user's
+ * connection from being handled properly.
+ */
+int guac_user_handle_connection(guac_user* user, int usec_timeout);
+
+/**
* Call the appropriate handler defined by the given user for the given
* instruction. A comparison is made between the instruction opcode and the
* initial handler lookup table defined in user-handlers.c. The intial handlers
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguac/user-handshake.c
----------------------------------------------------------------------
diff --git a/src/libguac/user-handshake.c b/src/libguac/user-handshake.c
new file mode 100644
index 0000000..b601888
--- /dev/null
+++ b/src/libguac/user-handshake.c
@@ -0,0 +1,437 @@
+/*
+ * 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 "error.h"
+#include "parser.h"
+#include "protocol.h"
+#include "socket.h"
+#include "user.h"
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Parameters required by the user input thread.
+ */
+typedef struct guac_user_input_thread_params {
+
+ /**
+ * The parser which will be used throughout the user's session.
+ */
+ guac_parser* parser;
+
+ /**
+ * A reference to the connected user.
+ */
+ guac_user* user;
+
+ /**
+ * The number of microseconds to wait for instructions from a connected
+ * user before closing the connection with an error.
+ */
+ int usec_timeout;
+
+} guac_user_input_thread_params;
+
+/**
+ * Prints an error message using the logging facilities of the given user,
+ * automatically including any information present in guac_error.
+ *
+ * @param user
+ * The guac_user associated with the error that occurred.
+ *
+ * @param level
+ * The level at which to log this message.
+ *
+ * @param message
+ * The message to log.
+ */
+static void guac_user_log_guac_error(guac_user* user,
+ guac_client_log_level level, const char* message) {
+
+ if (guac_error != GUAC_STATUS_SUCCESS) {
+
+ /* If error message provided, include in log */
+ if (guac_error_message != NULL)
+ guac_user_log(user, level, "%s: %s", message,
+ guac_error_message);
+
+ /* Otherwise just log with standard status string */
+ else
+ guac_user_log(user, level, "%s: %s", message,
+ guac_status_string(guac_error));
+
+ }
+
+ /* Just log message if no status code */
+ else
+ guac_user_log(user, level, "%s", message);
+
+}
+
+/**
+ * Logs a reasonable explanatory message regarding handshake failure based on
+ * the current value of guac_error.
+ *
+ * @param user
+ * The guac_user associated with the failed Guacamole protocol handshake.
+ */
+static void guac_user_log_handshake_failure(guac_user* user) {
+
+ if (guac_error == GUAC_STATUS_CLOSED)
+ guac_user_log(user, GUAC_LOG_INFO,
+ "Guacamole connection closed during handshake");
+ else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR)
+ guac_user_log(user, GUAC_LOG_ERROR,
+ "Guacamole protocol violation. Perhaps the version of "
+ "guacamole-client is incompatible with this version of "
+ "libguac?");
+ else
+ guac_user_log(user, GUAC_LOG_WARNING,
+ "Guacamole handshake failed: %s",
+ guac_status_string(guac_error));
+
+}
+
+/**
+ * Copies the given array of mimetypes (strings) into a newly-allocated NULL-
+ * terminated array of strings. Both the array and the strings within the array
+ * are newly-allocated and must be later freed via guac_free_mimetypes().
+ *
+ * @param mimetypes
+ * The array of mimetypes to copy.
+ *
+ * @param count
+ * The number of mimetypes in the given array.
+ *
+ * @return
+ * A newly-allocated, NULL-terminated array containing newly-allocated
+ * copies of each of the mimetypes provided in the original mimetypes
+ * array.
+ */
+static char** guac_copy_mimetypes(char** mimetypes, int count) {
+
+ int i;
+
+ /* Allocate sufficient space for NULL-terminated array of mimetypes */
+ char** mimetypes_copy = malloc(sizeof(char*) * (count+1));
+
+ /* Copy each provided mimetype */
+ for (i = 0; i < count; i++)
+ mimetypes_copy[i] = strdup(mimetypes[i]);
+
+ /* Terminate with NULL */
+ mimetypes_copy[count] = NULL;
+
+ return mimetypes_copy;
+
+}
+
+/**
+ * Frees the given array of mimetypes, including the space allocated to each
+ * mimetype string within the array. The provided array of mimetypes MUST have
+ * been allocated with guac_copy_mimetypes().
+ *
+ * @param mimetypes
+ * The NULL-terminated array of mimetypes to free. This array MUST have
+ * been previously allocated with guac_copy_mimetypes().
+ */
+static void guac_free_mimetypes(char** mimetypes) {
+
+ char** current_mimetype = mimetypes;
+
+ /* Free all strings within NULL-terminated mimetype array */
+ while (*current_mimetype != NULL) {
+ free(*current_mimetype);
+ current_mimetype++;
+ }
+
+ /* Free the array itself, now that its contents have been freed */
+ free(mimetypes);
+
+}
+
+/**
+ * The thread which handles all user input, calling event handlers for received
+ * instructions.
+ *
+ * @param data
+ * A pointer to a guac_user_input_thread_params structure describing the
+ * user whose input is being handled and the guac_parser with which to
+ * handle it.
+ *
+ * @return
+ * Always NULL.
+ */
+static void* guac_user_input_thread(void* data) {
+
+ guac_user_input_thread_params* params =
+ (guac_user_input_thread_params*) data;
+
+ int usec_timeout = params->usec_timeout;
+ guac_user* user = params->user;
+ guac_parser* parser = params->parser;
+ guac_client* client = user->client;
+ guac_socket* socket = user->socket;
+
+ /* Guacamole user input loop */
+ while (client->state == GUAC_CLIENT_RUNNING && user->active) {
+
+ /* Read instruction, stop on error */
+ if (guac_parser_read(parser, socket, usec_timeout)) {
+
+ if (guac_error == GUAC_STATUS_TIMEOUT)
+ guac_user_abort(user, GUAC_PROTOCOL_STATUS_CLIENT_TIMEOUT, "User is not responding.");
+
+ else {
+ if (guac_error != GUAC_STATUS_CLOSED)
+ guac_user_log_guac_error(user, GUAC_LOG_WARNING,
+ "Guacamole connection failure");
+ guac_user_stop(user);
+ }
+
+ return NULL;
+ }
+
+ /* Reset guac_error and guac_error_message (user/client handlers are not
+ * guaranteed to set these) */
+ guac_error = GUAC_STATUS_SUCCESS;
+ guac_error_message = NULL;
+
+ /* Call handler, stop on error */
+ if (guac_user_handle_instruction(user, parser->opcode, parser->argc, parser->argv) < 0) {
+
+ /* Log error */
+ guac_user_log_guac_error(user, GUAC_LOG_WARNING,
+ "User connection aborted");
+
+ /* Log handler details */
+ guac_user_log(user, GUAC_LOG_DEBUG, "Failing instruction handler in user was \"%s\"", parser->opcode);
+
+ guac_user_stop(user);
+ return NULL;
+ }
+
+ }
+
+ return NULL;
+
+}
+
+/**
+ * Starts the input/output threads of a new user. This function will block
+ * until the user disconnects. If an error prevents the input/output threads
+ * from starting, guac_user_stop() will be invoked on the given user.
+ *
+ * @param parser
+ * The guac_parser to use to handle all input from the given user.
+ *
+ * @param user
+ * The user whose associated I/O transfer threads should be started.
+ *
+ * @param usec_timeout
+ * The number of microseconds to wait for instructions from the given
+ * user before closing the connection with an error.
+ *
+ * @return
+ * Zero if the I/O threads started successfully and user has disconnected,
+ * or non-zero if the I/O threads could not be started.
+ */
+static int guac_user_start(guac_parser* parser, guac_user* user,
+ int usec_timeout) {
+
+ guac_user_input_thread_params params = {
+ .parser = parser,
+ .user = user,
+ .usec_timeout = usec_timeout
+ };
+
+ pthread_t input_thread;
+
+ if (pthread_create(&input_thread, NULL, guac_user_input_thread, (void*) ¶ms)) {
+ guac_user_log(user, GUAC_LOG_ERROR, "Unable to start input thread");
+ guac_user_stop(user);
+ return -1;
+ }
+
+ /* Wait for I/O threads */
+ pthread_join(input_thread, NULL);
+
+ /* Explicitly signal disconnect */
+ guac_protocol_send_disconnect(user->socket);
+ guac_socket_flush(user->socket);
+
+ /* Done */
+ return 0;
+
+}
+
+int guac_user_handle_connection(guac_user* user, int usec_timeout) {
+
+ guac_socket* socket = user->socket;
+ guac_client* client = user->client;
+
+ /* Send args */
+ if (guac_protocol_send_args(socket, client->args)
+ || guac_socket_flush(socket)) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error sending \"args\" to new user");
+
+ return 1;
+ }
+
+ guac_parser* parser = guac_parser_alloc();
+
+ /* Get optimal screen size */
+ if (guac_parser_expect(parser, socket, usec_timeout, "size")) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error reading \"size\"");
+
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Validate content of size instruction */
+ if (parser->argc < 2) {
+ guac_user_log(user, GUAC_LOG_ERROR, "Received \"size\" "
+ "instruction lacked required arguments.");
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Parse optimal screen dimensions from size instruction */
+ user->info.optimal_width = atoi(parser->argv[0]);
+ user->info.optimal_height = atoi(parser->argv[1]);
+
+ /* If DPI given, set the user resolution */
+ if (parser->argc >= 3)
+ user->info.optimal_resolution = atoi(parser->argv[2]);
+
+ /* Otherwise, use a safe default for rough backwards compatibility */
+ else
+ user->info.optimal_resolution = 96;
+
+ /* Get supported audio formats */
+ if (guac_parser_expect(parser, socket, usec_timeout, "audio")) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error reading \"audio\"");
+
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Store audio mimetypes */
+ char** audio_mimetypes = guac_copy_mimetypes(parser->argv, parser->argc);
+ user->info.audio_mimetypes = (const char**) audio_mimetypes;
+
+ /* Get supported video formats */
+ if (guac_parser_expect(parser, socket, usec_timeout, "video")) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error reading \"video\"");
+
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Store video mimetypes */
+ char** video_mimetypes = guac_copy_mimetypes(parser->argv, parser->argc);
+ user->info.video_mimetypes = (const char**) video_mimetypes;
+
+ /* Get supported image formats */
+ if (guac_parser_expect(parser, socket, usec_timeout, "image")) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error reading \"image\"");
+
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Store image mimetypes */
+ char** image_mimetypes = guac_copy_mimetypes(parser->argv, parser->argc);
+ user->info.image_mimetypes = (const char**) image_mimetypes;
+
+ /* Get args from connect instruction */
+ if (guac_parser_expect(parser, socket, usec_timeout, "connect")) {
+
+ /* Log error */
+ guac_user_log_handshake_failure(user);
+ guac_user_log_guac_error(user, GUAC_LOG_DEBUG,
+ "Error reading \"connect\"");
+
+ guac_parser_free(parser);
+ return 1;
+ }
+
+ /* Acknowledge connection availability */
+ guac_protocol_send_ready(socket, client->connection_id);
+ guac_socket_flush(socket);
+
+ /* Attempt join */
+ if (guac_client_add_user(client, user, parser->argc, parser->argv))
+ guac_client_log(client, GUAC_LOG_ERROR, "User \"%s\" could NOT "
+ "join connection \"%s\"", user->user_id, client->connection_id);
+
+ /* Begin user connection if join successful */
+ else {
+
+ guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" joined connection "
+ "\"%s\" (%i users now present)", user->user_id,
+ client->connection_id, client->connected_users);
+
+ /* Handle user I/O, wait for connection to terminate */
+ guac_user_start(parser, user, usec_timeout);
+
+ /* Remove/free user */
+ guac_client_remove_user(client, user);
+ guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" disconnected (%i "
+ "users remain)", user->user_id, client->connected_users);
+
+ }
+
+ /* Free mimetype lists */
+ guac_free_mimetypes(audio_mimetypes);
+ guac_free_mimetypes(video_mimetypes);
+ guac_free_mimetypes(image_mimetypes);
+
+ guac_parser_free(parser);
+
+ /* Successful disconnect */
+ return 0;
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguacd/Makefile.am
----------------------------------------------------------------------
diff --git a/src/libguacd/Makefile.am b/src/libguacd/Makefile.am
deleted file mode 100644
index c0373f1..0000000
--- a/src/libguacd/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# 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
-
-lib_LTLIBRARIES = libguacd.la
-
-libguacdincdir = $(includedir)/libguacd
-
-libguacdinc_HEADERS = \
- libguacd/user.h
-
-noinst_HEADERS = \
- log.h
-
-libguacd_la_SOURCES = \
- log.c \
- user.c
-
-libguacd_la_CFLAGS = \
- -Werror -Wall -pedantic \
- @LIBGUAC_INCLUDE@
-
-libguacd_la_LIBADD = \
- @LIBGUAC_LTLIB@
-
-libguacd_la_LDFLAGS = \
- -version-info 0:0:0 \
- -no-undefined \
- @PTHREAD_LIBS@
-
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguacd/libguacd/user.h
----------------------------------------------------------------------
diff --git a/src/libguacd/libguacd/user.h b/src/libguacd/libguacd/user.h
deleted file mode 100644
index 4404a6c..0000000
--- a/src/libguacd/libguacd/user.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 LIBGUACD_USER_H
-#define LIBGUACD_USER_H
-
-#include <guacamole/parser.h>
-#include <guacamole/socket.h>
-#include <guacamole/user.h>
-
-/**
- * Handles the initial handshake of a user and all subsequent I/O. This
- * function blocks until the user disconnects.
- *
- * @param user
- * The user whose handshake and entire Guacamole protocol exchange should
- * be handled.
- *
- * @param usec_timeout
- * The number of microseconds to wait for instructions from the given
- * user before closing the connection with an error.
- *
- * @return
- * Zero if the user's Guacamole connection was successfully handled and
- * the user has disconnected, or non-zero if an error prevented the user's
- * connection from being handled properly.
- */
-int guacd_handle_user(guac_user* user, int usec_timeout);
-
-#endif
-
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguacd/log.c
----------------------------------------------------------------------
diff --git a/src/libguacd/log.c b/src/libguacd/log.c
deleted file mode 100644
index 180cc97..0000000
--- a/src/libguacd/log.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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 "log.h"
-
-#include <guacamole/client.h>
-#include <guacamole/error.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-
-void guacd_client_log_guac_error(guac_client* client,
- guac_client_log_level level, const char* message) {
-
- if (guac_error != GUAC_STATUS_SUCCESS) {
-
- /* If error message provided, include in log */
- if (guac_error_message != NULL)
- guac_client_log(client, level, "%s: %s",
- message,
- guac_error_message);
-
- /* Otherwise just log with standard status string */
- else
- guac_client_log(client, level, "%s: %s",
- message,
- guac_status_string(guac_error));
-
- }
-
- /* Just log message if no status code */
- else
- guac_client_log(client, level, "%s", message);
-
-}
-
-void guacd_client_log_handshake_failure(guac_client* client) {
-
- if (guac_error == GUAC_STATUS_CLOSED)
- guac_client_log(client, GUAC_LOG_INFO,
- "Guacamole connection closed during handshake");
- else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR)
- guac_client_log(client, GUAC_LOG_ERROR,
- "Guacamole protocol violation. Perhaps the version of "
- "guacamole-client is incompatible with this version of "
- "guacd?");
- else
- guac_client_log(client, GUAC_LOG_WARNING,
- "Guacamole handshake failed: %s",
- guac_status_string(guac_error));
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguacd/log.h
----------------------------------------------------------------------
diff --git a/src/libguacd/log.h b/src/libguacd/log.h
deleted file mode 100644
index 76509e3..0000000
--- a/src/libguacd/log.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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 LIBGUACD_LOG_H
-#define LIBGUACD_LOG_H
-
-#include "config.h"
-
-#include <guacamole/client.h>
-
-/**
- * Prints an error message using the logging facilities of the given client,
- * automatically including any information present in guac_error. This function
- * accepts parameters identically to printf.
- */
-void guacd_client_log_guac_error(guac_client* client,
- guac_client_log_level level, const char* message);
-
-/**
- * Logs a reasonable explanatory message regarding handshake failure based on
- * the current value of guac_error.
- */
-void guacd_client_log_handshake_failure(guac_client* client);
-
-#endif
-
http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/f504b1a5/src/libguacd/user.c
----------------------------------------------------------------------
diff --git a/src/libguacd/user.c b/src/libguacd/user.c
deleted file mode 100644
index 04f0f49..0000000
--- a/src/libguacd/user.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * 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 "libguacd/user.h"
-#include "log.h"
-
-#include <guacamole/client.h>
-#include <guacamole/error.h>
-#include <guacamole/parser.h>
-#include <guacamole/protocol.h>
-#include <guacamole/socket.h>
-#include <guacamole/user.h>
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-/**
- * Parameters required by the user input thread.
- */
-typedef struct guacd_user_input_thread_params {
-
- /**
- * The parser which will be used throughout the user's session.
- */
- guac_parser* parser;
-
- /**
- * A reference to the connected user.
- */
- guac_user* user;
-
- /**
- * The number of microseconds to wait for instructions from a connected
- * user before closing the connection with an error.
- */
- int usec_timeout;
-
-} guacd_user_input_thread_params;
-
-/**
- * Copies the given array of mimetypes (strings) into a newly-allocated NULL-
- * terminated array of strings. Both the array and the strings within the array
- * are newly-allocated and must be later freed via guacd_free_mimetypes().
- *
- * @param mimetypes
- * The array of mimetypes to copy.
- *
- * @param count
- * The number of mimetypes in the given array.
- *
- * @return
- * A newly-allocated, NULL-terminated array containing newly-allocated
- * copies of each of the mimetypes provided in the original mimetypes
- * array.
- */
-static char** guacd_copy_mimetypes(char** mimetypes, int count) {
-
- int i;
-
- /* Allocate sufficient space for NULL-terminated array of mimetypes */
- char** mimetypes_copy = malloc(sizeof(char*) * (count+1));
-
- /* Copy each provided mimetype */
- for (i = 0; i < count; i++)
- mimetypes_copy[i] = strdup(mimetypes[i]);
-
- /* Terminate with NULL */
- mimetypes_copy[count] = NULL;
-
- return mimetypes_copy;
-
-}
-
-/**
- * Frees the given array of mimetypes, including the space allocated to each
- * mimetype string within the array. The provided array of mimetypes MUST have
- * been allocated with guacd_copy_mimetypes().
- *
- * @param mimetypes
- * The NULL-terminated array of mimetypes to free. This array MUST have
- * been previously allocated with guacd_copy_mimetypes().
- */
-static void guacd_free_mimetypes(char** mimetypes) {
-
- char** current_mimetype = mimetypes;
-
- /* Free all strings within NULL-terminated mimetype array */
- while (*current_mimetype != NULL) {
- free(*current_mimetype);
- current_mimetype++;
- }
-
- /* Free the array itself, now that its contents have been freed */
- free(mimetypes);
-
-}
-
-/**
- * The thread which handles all user input, calling event handlers for received
- * instructions.
- *
- * @param data
- * A pointer to a guacd_user_input_thread_params structure describing the
- * user whose input is being handled and the guac_parser with which to
- * handle it.
- *
- * @return
- * Always NULL.
- */
-static void* guacd_user_input_thread(void* data) {
-
- guacd_user_input_thread_params* params =
- (guacd_user_input_thread_params*) data;
-
- int usec_timeout = params->usec_timeout;
- guac_user* user = params->user;
- guac_parser* parser = params->parser;
- guac_client* client = user->client;
- guac_socket* socket = user->socket;
-
- /* Guacamole user input loop */
- while (client->state == GUAC_CLIENT_RUNNING && user->active) {
-
- /* Read instruction, stop on error */
- if (guac_parser_read(parser, socket, usec_timeout)) {
-
- if (guac_error == GUAC_STATUS_TIMEOUT)
- guac_user_abort(user, GUAC_PROTOCOL_STATUS_CLIENT_TIMEOUT, "User is not responding.");
-
- else {
- if (guac_error != GUAC_STATUS_CLOSED)
- guacd_client_log_guac_error(client, GUAC_LOG_WARNING,
- "Guacamole connection failure");
- guac_user_stop(user);
- }
-
- return NULL;
- }
-
- /* Reset guac_error and guac_error_message (user/client handlers are not
- * guaranteed to set these) */
- guac_error = GUAC_STATUS_SUCCESS;
- guac_error_message = NULL;
-
- /* Call handler, stop on error */
- if (guac_user_handle_instruction(user, parser->opcode, parser->argc, parser->argv) < 0) {
-
- /* Log error */
- guacd_client_log_guac_error(client, GUAC_LOG_WARNING,
- "User connection aborted");
-
- /* Log handler details */
- guac_user_log(user, GUAC_LOG_DEBUG, "Failing instruction handler in user was \"%s\"", parser->opcode);
-
- guac_user_stop(user);
- return NULL;
- }
-
- }
-
- return NULL;
-
-}
-
-/**
- * Starts the input/output threads of a new user. This function will block
- * until the user disconnects. If an error prevents the input/output threads
- * from starting, guac_user_stop() will be invoked on the given user.
- *
- * @param parser
- * The guac_parser to use to handle all input from the given user.
- *
- * @param user
- * The user whose associated I/O transfer threads should be started.
- *
- * @param usec_timeout
- * The number of microseconds to wait for instructions from the given
- * user before closing the connection with an error.
- *
- * @return
- * Zero if the I/O threads started successfully and user has disconnected,
- * or non-zero if the I/O threads could not be started.
- */
-static int guacd_user_start(guac_parser* parser, guac_user* user,
- int usec_timeout) {
-
- guacd_user_input_thread_params params = {
- .parser = parser,
- .user = user,
- .usec_timeout = usec_timeout
- };
-
- pthread_t input_thread;
-
- if (pthread_create(&input_thread, NULL, guacd_user_input_thread, (void*) ¶ms)) {
- guac_user_log(user, GUAC_LOG_ERROR, "Unable to start input thread");
- guac_user_stop(user);
- return -1;
- }
-
- /* Wait for I/O threads */
- pthread_join(input_thread, NULL);
-
- /* Explicitly signal disconnect */
- guac_protocol_send_disconnect(user->socket);
- guac_socket_flush(user->socket);
-
- /* Done */
- return 0;
-
-}
-
-int guacd_handle_user(guac_user* user, int usec_timeout) {
-
- guac_socket* socket = user->socket;
- guac_client* client = user->client;
-
- /* Send args */
- if (guac_protocol_send_args(socket, client->args)
- || guac_socket_flush(socket)) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error sending \"args\" to new user");
-
- return 1;
- }
-
- guac_parser* parser = guac_parser_alloc();
-
- /* Get optimal screen size */
- if (guac_parser_expect(parser, socket, usec_timeout, "size")) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error reading \"size\"");
-
- guac_parser_free(parser);
- return 1;
- }
-
- /* Validate content of size instruction */
- if (parser->argc < 2) {
- guac_client_log(client, GUAC_LOG_ERROR, "Received \"size\" "
- "instruction lacked required arguments.");
- guac_parser_free(parser);
- return 1;
- }
-
- /* Parse optimal screen dimensions from size instruction */
- user->info.optimal_width = atoi(parser->argv[0]);
- user->info.optimal_height = atoi(parser->argv[1]);
-
- /* If DPI given, set the client resolution */
- if (parser->argc >= 3)
- user->info.optimal_resolution = atoi(parser->argv[2]);
-
- /* Otherwise, use a safe default for rough backwards compatibility */
- else
- user->info.optimal_resolution = 96;
-
- /* Get supported audio formats */
- if (guac_parser_expect(parser, socket, usec_timeout, "audio")) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error reading \"audio\"");
-
- guac_parser_free(parser);
- return 1;
- }
-
- /* Store audio mimetypes */
- char** audio_mimetypes = guacd_copy_mimetypes(parser->argv, parser->argc);
- user->info.audio_mimetypes = (const char**) audio_mimetypes;
-
- /* Get supported video formats */
- if (guac_parser_expect(parser, socket, usec_timeout, "video")) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error reading \"video\"");
-
- guac_parser_free(parser);
- return 1;
- }
-
- /* Store video mimetypes */
- char** video_mimetypes = guacd_copy_mimetypes(parser->argv, parser->argc);
- user->info.video_mimetypes = (const char**) video_mimetypes;
-
- /* Get supported image formats */
- if (guac_parser_expect(parser, socket, usec_timeout, "image")) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error reading \"image\"");
-
- guac_parser_free(parser);
- return 1;
- }
-
- /* Store image mimetypes */
- char** image_mimetypes = guacd_copy_mimetypes(parser->argv, parser->argc);
- user->info.image_mimetypes = (const char**) image_mimetypes;
-
- /* Get args from connect instruction */
- if (guac_parser_expect(parser, socket, usec_timeout, "connect")) {
-
- /* Log error */
- guacd_client_log_handshake_failure(client);
- guacd_client_log_guac_error(client, GUAC_LOG_DEBUG,
- "Error reading \"connect\"");
-
- guac_parser_free(parser);
- return 1;
- }
-
- /* Acknowledge connection availability */
- guac_protocol_send_ready(socket, client->connection_id);
- guac_socket_flush(socket);
-
- /* Attempt join */
- if (guac_client_add_user(client, user, parser->argc, parser->argv))
- guac_client_log(client, GUAC_LOG_ERROR, "User \"%s\" could NOT "
- "join connection \"%s\"", user->user_id, client->connection_id);
-
- /* Begin user connection if join successful */
- else {
-
- guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" joined connection "
- "\"%s\" (%i users now present)", user->user_id,
- client->connection_id, client->connected_users);
-
- /* Handle user I/O, wait for connection to terminate */
- guacd_user_start(parser, user, usec_timeout);
-
- /* Remove/free user */
- guac_client_remove_user(client, user);
- guac_client_log(client, GUAC_LOG_INFO, "User \"%s\" disconnected (%i "
- "users remain)", user->user_id, client->connected_users);
-
- }
-
- /* Free mimetype lists */
- guacd_free_mimetypes(audio_mimetypes);
- guacd_free_mimetypes(video_mimetypes);
- guacd_free_mimetypes(image_mimetypes);
-
- guac_parser_free(parser);
-
- /* Successful disconnect */
- return 0;
-
-}
-