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;
+
+}
+