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/01/25 00:39:42 UTC

[3/4] incubator-guacamole-server git commit: GUACAMOLE-175: Move guacd_handle_user() to libguacd.

GUACAMOLE-175: Move guacd_handle_user() to libguacd.


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/4c06d755
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/4c06d755
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/4c06d755

Branch: refs/heads/master
Commit: 4c06d755f95bfacaa6f1b5f435b6a94ef2d8a608
Parents: 45adc63
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Sep 11 13:18:27 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Tue Jan 24 15:44:59 2017 -0800

----------------------------------------------------------------------
 src/guacd/proc.c             | 210 --------------------------------------
 src/libguacd/libguacd/log.h  |   6 ++
 src/libguacd/libguacd/user.h |  15 +++
 src/libguacd/log.c           |  17 +++
 src/libguacd/user.c          | 208 +++++++++++++++++++++++++++++++++++++
 5 files changed, 246 insertions(+), 210 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/4c06d755/src/guacd/proc.c
----------------------------------------------------------------------
diff --git a/src/guacd/proc.c b/src/guacd/proc.c
index f4d7f2a..74ba146 100644
--- a/src/guacd/proc.c
+++ b/src/guacd/proc.c
@@ -41,216 +41,6 @@
 #include <sys/socket.h>
 
 /**
- * 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);
-
-}
-
-/**
- * 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.
- *
- * @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.
- */
-static int guacd_handle_user(guac_user* user) {
-
-    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_log_handshake_failure();
-        guacd_log_guac_error(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, GUACD_USEC_TIMEOUT, "size")) {
-
-        /* Log error */
-        guacd_log_handshake_failure();
-        guacd_log_guac_error(GUAC_LOG_DEBUG, "Error reading \"size\"");
-
-        guac_parser_free(parser);
-        return 1;
-    }
-
-    /* Validate content of size instruction */
-    if (parser->argc < 2) {
-        guacd_log(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, GUACD_USEC_TIMEOUT, "audio")) {
-
-        /* Log error */
-        guacd_log_handshake_failure();
-        guacd_log_guac_error(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, GUACD_USEC_TIMEOUT, "video")) {
-
-        /* Log error */
-        guacd_log_handshake_failure();
-        guacd_log_guac_error(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, GUACD_USEC_TIMEOUT, "image")) {
-
-        /* Log error */
-        guacd_log_handshake_failure();
-        guacd_log_guac_error(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, GUACD_USEC_TIMEOUT, "connect")) {
-
-        /* Log error */
-        guacd_log_handshake_failure();
-        guacd_log_guac_error(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))
-        guacd_log(GUAC_LOG_ERROR, "User \"%s\" could NOT join connection \"%s\"", user->user_id, client->connection_id);
-
-    /* Begin user connection if join successful */
-    else {
-
-        guacd_log(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);
-
-        /* Remove/free user */
-        guac_client_remove_user(client, user);
-        guacd_log(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;
-
-}
-
-/**
  * Parameters for the user thread.
  */
 typedef struct guacd_user_thread_params {

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/4c06d755/src/libguacd/libguacd/log.h
----------------------------------------------------------------------
diff --git a/src/libguacd/libguacd/log.h b/src/libguacd/libguacd/log.h
index 2e65f5a..76509e3 100644
--- a/src/libguacd/libguacd/log.h
+++ b/src/libguacd/libguacd/log.h
@@ -32,5 +32,11 @@
 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/4c06d755/src/libguacd/libguacd/user.h
----------------------------------------------------------------------
diff --git a/src/libguacd/libguacd/user.h b/src/libguacd/libguacd/user.h
index a872f14..cb2a8b3 100644
--- a/src/libguacd/libguacd/user.h
+++ b/src/libguacd/libguacd/user.h
@@ -81,6 +81,21 @@ typedef struct guacd_user_input_thread_params {
 int guacd_user_start(guac_parser* parser, guac_user* user);
 
 /**
+ * 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.
+ *
+ * @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);
+
+/**
  * The thread which handles all user input, calling event handlers for received
  * instructions.
  *

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/4c06d755/src/libguacd/log.c
----------------------------------------------------------------------
diff --git a/src/libguacd/log.c b/src/libguacd/log.c
index 26b24e4..e746373 100644
--- a/src/libguacd/log.c
+++ b/src/libguacd/log.c
@@ -53,3 +53,20 @@ void guacd_client_log_guac_error(guac_client* client,
 
 }
 
+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/4c06d755/src/libguacd/user.c
----------------------------------------------------------------------
diff --git a/src/libguacd/user.c b/src/libguacd/user.c
index e9f73be..db39fce 100644
--- a/src/libguacd/user.c
+++ b/src/libguacd/user.c
@@ -31,6 +31,65 @@
 
 #include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
+
+/**
+ * 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);
+
+}
 
 void* guacd_user_input_thread(void* data) {
 
@@ -111,3 +170,152 @@ int guacd_user_start(guac_parser* parser, guac_user* user) {
 
 }
 
+int guacd_handle_user(guac_user* user) {
+
+    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, GUACD_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, GUACD_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, GUACD_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, GUACD_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, GUACD_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);
+
+        /* 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;
+
+}
+