Repository: incubator-guacamole-server
Updated Branches:
  refs/heads/master 396eaa21f -> 5d2c9676f


GUACAMOLE-175: Move common core of guacd into libguacd utility library.


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

Branch: refs/heads/master
Commit: d7a604c8b29574be21002ad5c90ff27d76301824
Parents: a1886f5
Author: Michael Jumper <[email protected]>
Authored: Fri Sep 9 10:44:16 2016 -0700
Committer: Michael Jumper <[email protected]>
Committed: Tue Jan 24 15:44:51 2017 -0800

----------------------------------------------------------------------
 Makefile.am               |   8 +-
 configure.ac              |   5 ++
 src/guacd/Makefile.am     |  20 ++---
 src/guacd/log.c           | 168 -----------------------------------------
 src/guacd/log.h           |  80 --------------------
 src/guacd/socket-ssl.c    | 153 -------------------------------------
 src/guacd/socket-ssl.h    |  71 -----------------
 src/guacd/user.c          | 113 ---------------------------
 src/guacd/user.h          |  98 ------------------------
 src/libguacd/Makefile.am  |  50 ++++++++++++
 src/libguacd/log.c        | 168 +++++++++++++++++++++++++++++++++++++++++
 src/libguacd/log.h        |  80 ++++++++++++++++++++
 src/libguacd/socket-ssl.c | 153 +++++++++++++++++++++++++++++++++++++
 src/libguacd/socket-ssl.h |  71 +++++++++++++++++
 src/libguacd/user.c       | 113 +++++++++++++++++++++++++++
 src/libguacd/user.h       |  98 ++++++++++++++++++++++++
 16 files changed, 749 insertions(+), 700 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index 54899e9..78f76e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,6 +22,7 @@ ACLOCAL_AMFLAGS = -I m4
 # Subprojects
 DIST_SUBDIRS =           \
     src/libguac          \
+    src/libguacd         \
     src/common           \
     src/common-ssh       \
     src/terminal         \
@@ -33,9 +34,10 @@ DIST_SUBDIRS =           \
     src/protocols/vnc    \
     tests
 
-SUBDIRS =       \
-    src/libguac \
-    src/common  \
+SUBDIRS =        \
+    src/libguac  \
+    src/common   \
+    src/libguacd \
     tests
 
 if ENABLE_COMMON_SSH

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 4c43359..a763d6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,6 +119,10 @@ AC_SUBST([LIBGUAC_INCLUDE], '-I$(top_srcdir)/src/libguac')
 AC_SUBST([COMMON_LTLIB],   '$(top_builddir)/src/common/libguac_common.la')
 AC_SUBST([COMMON_INCLUDE], '-I$(top_srcdir)/src/common')
 
+# 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')
@@ -1101,6 +1105,7 @@ AC_CONFIG_FILES([Makefile
                  src/common-ssh/Makefile
                  src/terminal/Makefile
                  src/libguac/Makefile
+                 src/libguacd/Makefile
                  src/guacd/Makefile
                  src/guacenc/Makefile
                  src/protocols/rdp/Makefile

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/Makefile.am
----------------------------------------------------------------------
diff --git a/src/guacd/Makefile.am b/src/guacd/Makefile.am
index 51e5f87..e25a101 100644
--- a/src/guacd/Makefile.am
+++ b/src/guacd/Makefile.am
@@ -30,11 +30,9 @@ noinst_HEADERS =  \
     conf-file.h   \
     conf-parse.h  \
     connection.h  \
-    log.h         \
     move-fd.h     \
     proc.h        \
-    proc-map.h    \
-    user.h
+    proc-map.h
 
 guacd_SOURCES =  \
     conf-args.c  \
@@ -42,19 +40,19 @@ guacd_SOURCES =  \
     conf-parse.c \
     connection.c \
     daemon.c     \
-    log.c        \
     move-fd.c    \
     proc.c       \
-    proc-map.c   \
-    user.c
+    proc-map.c
 
 guacd_CFLAGS =              \
     -Werror -Wall -pedantic \
     @COMMON_INCLUDE@        \
+    @LIBGUACD_INCLUDE@      \
     @LIBGUAC_INCLUDE@
 
-guacd_LDADD =       \
-    @COMMON_LTLIB@  \
+guacd_LDADD =        \
+    @COMMON_LTLIB@   \
+    @LIBGUACD_LTLIB@ \
     @LIBGUAC_LTLIB@
 
 guacd_LDFLAGS =    \
@@ -68,12 +66,6 @@ EXTRA_DIST =         \
 
 CLEANFILES = $(init_SCRIPTS)
 
-# SSL support
-if ENABLE_SSL
-noinst_HEADERS += socket-ssl.h
-guacd_SOURCES  += socket-ssl.c
-endif
-
 # Init script
 if ENABLE_INIT
 initdir = @init_dir@

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/log.c
----------------------------------------------------------------------
diff --git a/src/guacd/log.c b/src/guacd/log.c
deleted file mode 100644
index 229d2f9..0000000
--- a/src/guacd/log.c
+++ /dev/null
@@ -1,168 +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 <syslog.h>
-#include <unistd.h>
-
-int guacd_log_level = GUAC_LOG_INFO;
-
-void vguacd_log(guac_client_log_level level, const char* format,
-        va_list args) {
-
-    const char* priority_name;
-    int priority;
-
-    char message[2048];
-
-    /* Don't bother if the log level is too high */
-    if (level > guacd_log_level)
-        return;
-
-    /* Copy log message into buffer */
-    vsnprintf(message, sizeof(message), format, args);
-
-    /* Convert log level to syslog priority */
-    switch (level) {
-
-        /* Error log level */
-        case GUAC_LOG_ERROR:
-            priority = LOG_ERR;
-            priority_name = "ERROR";
-            break;
-
-        /* Warning log level */
-        case GUAC_LOG_WARNING:
-            priority = LOG_WARNING;
-            priority_name = "WARNING";
-            break;
-
-        /* Informational log level */
-        case GUAC_LOG_INFO:
-            priority = LOG_INFO;
-            priority_name = "INFO";
-            break;
-
-        /* Debug log level */
-        case GUAC_LOG_DEBUG:
-            priority = LOG_DEBUG;
-            priority_name = "DEBUG";
-            break;
-
-        /* Any unknown/undefined log level */
-        default:
-            priority = LOG_INFO;
-            priority_name = "UNKNOWN";
-            break;
-    }
-
-    /* Log to syslog */
-    syslog(priority, "%s", message);
-
-    /* Log to STDERR */
-    fprintf(stderr, GUACD_LOG_NAME "[%i]: %s:\t%s\n",
-            getpid(), priority_name, message);
-
-}
-
-void guacd_log(guac_client_log_level level, const char* format, ...) {
-    va_list args;
-    va_start(args, format);
-    vguacd_log(level, format, args);
-    va_end(args);
-}
-
-void guacd_client_log(guac_client* client, guac_client_log_level level,
-        const char* format, va_list args) {
-    vguacd_log(level, format, args);
-}
-
-void guacd_log_guac_error(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)
-            guacd_log(level, "%s: %s",
-                    message,
-                    guac_error_message);
-
-        /* Otherwise just log with standard status string */
-        else
-            guacd_log(level, "%s: %s",
-                    message,
-                    guac_status_string(guac_error));
-
-    }
-
-    /* Just log message if no status code */
-    else
-        guacd_log(level, "%s", message);
-
-}
-
-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_log_handshake_failure() {
-
-    if (guac_error == GUAC_STATUS_CLOSED)
-        guacd_log(GUAC_LOG_INFO,
-                "Guacamole connection closed during handshake");
-    else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR)
-        guacd_log(GUAC_LOG_ERROR,
-                "Guacamole protocol violation. Perhaps the version of "
-                "guacamole-client is incompatible with this version of "
-                "guacd?");
-    else
-        guacd_log(GUAC_LOG_WARNING,
-                "Guacamole handshake failed: %s",
-                guac_status_string(guac_error));
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/log.h
----------------------------------------------------------------------
diff --git a/src/guacd/log.h b/src/guacd/log.h
deleted file mode 100644
index 09fe152..0000000
--- a/src/guacd/log.h
+++ /dev/null
@@ -1,80 +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 __GUACD_LOG_H
-#define __GUACD_LOG_H
-
-#include "config.h"
-
-#include <guacamole/client.h>
-
-/**
- * The maximum level at which to log messages. All other messages will be
- * dropped.
- */
-extern int guacd_log_level;
-
-/**
- * The string to prepend to all log messages.
- */
-#define GUACD_LOG_NAME "guacd"
-
-/**
- * Writes a message to guacd's logs. This function takes a format and va_list,
- * similar to vprintf.
- */
-void vguacd_log(guac_client_log_level level, const char* format, va_list args);
-
-/**
- * Writes a message to guacd's logs. This function accepts parameters
- * identically to printf.
- */
-void guacd_log(guac_client_log_level level, const char* format, ...);
-
-/**
- * Writes a message using the logging facilities of the given client. This
- * function accepts parameters identically to printf.
- */
-void guacd_client_log(guac_client* client, guac_client_log_level level,
-        const char* format, va_list args);
-
-/**
- * Prints an error message to guacd's logs, automatically including any
- * information present in guac_error. This function accepts parameters
- * identically to printf.
- */
-void guacd_log_guac_error(guac_client_log_level level, const char* message);
-
-/**
- * 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_log_handshake_failure();
-
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/socket-ssl.c
----------------------------------------------------------------------
diff --git a/src/guacd/socket-ssl.c b/src/guacd/socket-ssl.c
deleted file mode 100644
index 4f19442..0000000
--- a/src/guacd/socket-ssl.c
+++ /dev/null
@@ -1,153 +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 "socket-ssl.h"
-
-#include <poll.h>
-#include <stdlib.h>
-
-#include <guacamole/error.h>
-#include <guacamole/socket.h>
-#include <openssl/ssl.h>
-
-static ssize_t __guac_socket_ssl_read_handler(guac_socket* socket,
-        void* buf, size_t count) {
-
-    /* Read from socket */
-    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
-    int retval;
-
-    retval = SSL_read(data->ssl, buf, count);
-
-    /* Record errors in guac_error */
-    if (retval <= 0) {
-        guac_error = GUAC_STATUS_SEE_ERRNO;
-        guac_error_message = "Error reading data from secure socket";
-    }
-
-    return retval;
-
-}
-
-static ssize_t __guac_socket_ssl_write_handler(guac_socket* socket,
-        const void* buf, size_t count) {
-
-    /* Write data to socket */
-    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
-    int retval;
-
-    retval = SSL_write(data->ssl, buf, count);
-
-    /* Record errors in guac_error */
-    if (retval <= 0) {
-        guac_error = GUAC_STATUS_SEE_ERRNO;
-        guac_error_message = "Error writing data to secure socket";
-    }
-
-    return retval;
-
-}
-
-static int __guac_socket_ssl_select_handler(guac_socket* socket, int 
usec_timeout) {
-
-    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
-
-    int retval;
-
-    /* Initialize with single underlying file descriptor */
-    struct pollfd fds[1] = {{
-        .fd      = data->fd,
-        .events  = POLLIN,
-        .revents = 0,
-    }};
-
-    /* No timeout if usec_timeout is negative */
-    if (usec_timeout < 0)
-        retval = poll(fds, 1, -1);
-
-    /* Handle timeout if specified, rounding up to poll()'s granularity */
-    else
-        retval = poll(fds, 1, (usec_timeout + 999) / 1000);
-
-    /* Properly set guac_error */
-    if (retval <  0) {
-        guac_error = GUAC_STATUS_SEE_ERRNO;
-        guac_error_message = "Error while waiting for data on secure socket";
-    }
-
-    if (retval == 0) {
-        guac_error = GUAC_STATUS_TIMEOUT;
-        guac_error_message = "Timeout while waiting for data on secure socket";
-    }
-
-    return retval;
-
-}
-
-static int __guac_socket_ssl_free_handler(guac_socket* socket) {
-
-    /* Shutdown SSL */
-    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
-    SSL_shutdown(data->ssl);
-
-    /* Close file descriptor */
-    close(data->fd);
-
-    free(data);
-    return 0;
-}
-
-guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) {
-
-    /* Allocate socket and associated data */
-    guac_socket* socket = guac_socket_alloc();
-    guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data));
-
-    /* Init SSL */
-    data->context = context;
-    data->ssl = SSL_new(context);
-    SSL_set_fd(data->ssl, fd);
-
-    /* Accept SSL connection, handle errors */
-    if (SSL_accept(data->ssl) <= 0) {
-
-        guac_error = GUAC_STATUS_INTERNAL_ERROR;
-        guac_error_message = "SSL accept failed";
-
-        free(data);
-        guac_socket_free(socket);
-        return NULL;
-    }
-
-    /* Store file descriptor as socket data */
-    data->fd = fd;
-    socket->data = data;
-
-    /* Set read/write handlers */
-    socket->read_handler   = __guac_socket_ssl_read_handler;
-    socket->write_handler  = __guac_socket_ssl_write_handler;
-    socket->select_handler = __guac_socket_ssl_select_handler;
-    socket->free_handler   = __guac_socket_ssl_free_handler;
-
-    return socket;
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/socket-ssl.h
----------------------------------------------------------------------
diff --git a/src/guacd/socket-ssl.h b/src/guacd/socket-ssl.h
deleted file mode 100644
index e1a341e..0000000
--- a/src/guacd/socket-ssl.h
+++ /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.
- */
-
-
-#ifndef __GUACD_SOCKET_SSL_H
-#define __GUACD_SOCKET_SSL_H
-
-#include "config.h"
-
-#include <guacamole/socket.h>
-#include <openssl/ssl.h>
-
-/**
- * SSL socket-specific data.
- */
-typedef struct guac_socket_ssl_data {
-
-    /**
-     * The file descriptor that SSL communication will take place
-     * over.
-     */
-    int fd;
-
-    /**
-     * The current SSL context.
-     */
-    SSL_CTX* context;
-
-    /**
-     * The SSL connection, created automatically via
-     * guac_socket_open_secure().
-     */
-    SSL* ssl;
-
-} guac_socket_ssl_data;
-
-/**
- * Creates a new guac_socket which will use SSL for all communication. Freeing
- * this guac_socket will automatically close the associated file descriptor.
- *
- * @param context
- *     The SSL_CTX structure describing the desired SSL configuration.
- *
- * @param fd
- *     The file descriptor to use for the SSL connection underlying the
- *     created guac_socket.
- *
- * @return
- *     A newly-allocated guac_socket which will transparently use SSL for
- *     all communication.
- */
-guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd);
-
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/user.c
----------------------------------------------------------------------
diff --git a/src/guacd/user.c b/src/guacd/user.c
deleted file mode 100644
index 0a37147..0000000
--- a/src/guacd/user.c
+++ /dev/null
@@ -1,113 +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 "user.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>
-
-void* guacd_user_input_thread(void* data) {
-
-    guacd_user_input_thread_params* params = (guacd_user_input_thread_params*) 
data;
-    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, GUACD_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;
-
-}
-
-int guacd_user_start(guac_parser* parser, guac_user* user) {
-
-    guacd_user_input_thread_params params = {
-        .parser = parser,
-        .user = user
-    };
-
-    pthread_t input_thread;
-
-    if (pthread_create(&input_thread, NULL, guacd_user_input_thread, (void*) 
&params)) {
-        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;
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/guacd/user.h
----------------------------------------------------------------------
diff --git a/src/guacd/user.h b/src/guacd/user.h
deleted file mode 100644
index 65eef70..0000000
--- a/src/guacd/user.h
+++ /dev/null
@@ -1,98 +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 _GUACD_USER_H
-#define _GUACD_USER_H
-
-#include "config.h"
-
-#include <guacamole/parser.h>
-#include <guacamole/socket.h>
-#include <guacamole/user.h>
-
-/**
- * The number of milliseconds to wait for messages in any phase before
- * timing out and closing the connection with an error.
- */
-#define GUACD_TIMEOUT      15000
-
-/**
- * The number of microseconds to wait for messages in any phase before
- * timing out and closing the conncetion with an error. This is always
- * equal to GUACD_TIMEOUT * 1000.
- */
-#define GUACD_USEC_TIMEOUT (GUACD_TIMEOUT*1000)
-
-/**
- * The maximum number of concurrent connections to a single instance
- * of guacd.
- */
-#define GUACD_CLIENT_MAX_CONNECTIONS 65536
-
-/**
- * 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;
-
-} guacd_user_input_thread_params;
-
-/**
- * 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.
- *
- * @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.
- */
-int guacd_user_start(guac_parser* parser, guac_user* user);
-
-/**
- * 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.
- */
-void* guacd_user_input_thread(void* data);
-
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/Makefile.am
----------------------------------------------------------------------
diff --git a/src/libguacd/Makefile.am b/src/libguacd/Makefile.am
new file mode 100644
index 0000000..9e20cec
--- /dev/null
+++ b/src/libguacd/Makefile.am
@@ -0,0 +1,50 @@
+#
+# 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 
+
+noinst_LTLIBRARIES = libguacd.la
+
+noinst_HEADERS =  \
+    log.h         \
+    user.h
+
+libguacd_la_SOURCES = \
+    log.c             \
+    user.c
+
+libguacd_la_CFLAGS =        \
+    -Werror -Wall -pedantic \
+    @COMMON_INCLUDE@        \
+    @LIBGUAC_INCLUDE@
+
+libguacd_la_LIBADD = \
+    @COMMON_LTLIB@   \
+    @LIBGUAC_LTLIB@
+
+libguacd_la_LDFLAGS = \
+    @PTHREAD_LIBS@    \
+    @SSL_LIBS@
+
+# SSL support
+if ENABLE_SSL
+noinst_HEADERS      += socket-ssl.h
+libguacd_la_SOURCES += socket-ssl.c
+endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/log.c
----------------------------------------------------------------------
diff --git a/src/libguacd/log.c b/src/libguacd/log.c
new file mode 100644
index 0000000..229d2f9
--- /dev/null
+++ b/src/libguacd/log.c
@@ -0,0 +1,168 @@
+/*
+ * 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 <syslog.h>
+#include <unistd.h>
+
+int guacd_log_level = GUAC_LOG_INFO;
+
+void vguacd_log(guac_client_log_level level, const char* format,
+        va_list args) {
+
+    const char* priority_name;
+    int priority;
+
+    char message[2048];
+
+    /* Don't bother if the log level is too high */
+    if (level > guacd_log_level)
+        return;
+
+    /* Copy log message into buffer */
+    vsnprintf(message, sizeof(message), format, args);
+
+    /* Convert log level to syslog priority */
+    switch (level) {
+
+        /* Error log level */
+        case GUAC_LOG_ERROR:
+            priority = LOG_ERR;
+            priority_name = "ERROR";
+            break;
+
+        /* Warning log level */
+        case GUAC_LOG_WARNING:
+            priority = LOG_WARNING;
+            priority_name = "WARNING";
+            break;
+
+        /* Informational log level */
+        case GUAC_LOG_INFO:
+            priority = LOG_INFO;
+            priority_name = "INFO";
+            break;
+
+        /* Debug log level */
+        case GUAC_LOG_DEBUG:
+            priority = LOG_DEBUG;
+            priority_name = "DEBUG";
+            break;
+
+        /* Any unknown/undefined log level */
+        default:
+            priority = LOG_INFO;
+            priority_name = "UNKNOWN";
+            break;
+    }
+
+    /* Log to syslog */
+    syslog(priority, "%s", message);
+
+    /* Log to STDERR */
+    fprintf(stderr, GUACD_LOG_NAME "[%i]: %s:\t%s\n",
+            getpid(), priority_name, message);
+
+}
+
+void guacd_log(guac_client_log_level level, const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    vguacd_log(level, format, args);
+    va_end(args);
+}
+
+void guacd_client_log(guac_client* client, guac_client_log_level level,
+        const char* format, va_list args) {
+    vguacd_log(level, format, args);
+}
+
+void guacd_log_guac_error(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)
+            guacd_log(level, "%s: %s",
+                    message,
+                    guac_error_message);
+
+        /* Otherwise just log with standard status string */
+        else
+            guacd_log(level, "%s: %s",
+                    message,
+                    guac_status_string(guac_error));
+
+    }
+
+    /* Just log message if no status code */
+    else
+        guacd_log(level, "%s", message);
+
+}
+
+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_log_handshake_failure() {
+
+    if (guac_error == GUAC_STATUS_CLOSED)
+        guacd_log(GUAC_LOG_INFO,
+                "Guacamole connection closed during handshake");
+    else if (guac_error == GUAC_STATUS_PROTOCOL_ERROR)
+        guacd_log(GUAC_LOG_ERROR,
+                "Guacamole protocol violation. Perhaps the version of "
+                "guacamole-client is incompatible with this version of "
+                "guacd?");
+    else
+        guacd_log(GUAC_LOG_WARNING,
+                "Guacamole handshake failed: %s",
+                guac_status_string(guac_error));
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/log.h
----------------------------------------------------------------------
diff --git a/src/libguacd/log.h b/src/libguacd/log.h
new file mode 100644
index 0000000..09fe152
--- /dev/null
+++ b/src/libguacd/log.h
@@ -0,0 +1,80 @@
+/*
+ * 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 __GUACD_LOG_H
+#define __GUACD_LOG_H
+
+#include "config.h"
+
+#include <guacamole/client.h>
+
+/**
+ * The maximum level at which to log messages. All other messages will be
+ * dropped.
+ */
+extern int guacd_log_level;
+
+/**
+ * The string to prepend to all log messages.
+ */
+#define GUACD_LOG_NAME "guacd"
+
+/**
+ * Writes a message to guacd's logs. This function takes a format and va_list,
+ * similar to vprintf.
+ */
+void vguacd_log(guac_client_log_level level, const char* format, va_list args);
+
+/**
+ * Writes a message to guacd's logs. This function accepts parameters
+ * identically to printf.
+ */
+void guacd_log(guac_client_log_level level, const char* format, ...);
+
+/**
+ * Writes a message using the logging facilities of the given client. This
+ * function accepts parameters identically to printf.
+ */
+void guacd_client_log(guac_client* client, guac_client_log_level level,
+        const char* format, va_list args);
+
+/**
+ * Prints an error message to guacd's logs, automatically including any
+ * information present in guac_error. This function accepts parameters
+ * identically to printf.
+ */
+void guacd_log_guac_error(guac_client_log_level level, const char* message);
+
+/**
+ * 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_log_handshake_failure();
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/socket-ssl.c
----------------------------------------------------------------------
diff --git a/src/libguacd/socket-ssl.c b/src/libguacd/socket-ssl.c
new file mode 100644
index 0000000..4f19442
--- /dev/null
+++ b/src/libguacd/socket-ssl.c
@@ -0,0 +1,153 @@
+/*
+ * 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 "socket-ssl.h"
+
+#include <poll.h>
+#include <stdlib.h>
+
+#include <guacamole/error.h>
+#include <guacamole/socket.h>
+#include <openssl/ssl.h>
+
+static ssize_t __guac_socket_ssl_read_handler(guac_socket* socket,
+        void* buf, size_t count) {
+
+    /* Read from socket */
+    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
+    int retval;
+
+    retval = SSL_read(data->ssl, buf, count);
+
+    /* Record errors in guac_error */
+    if (retval <= 0) {
+        guac_error = GUAC_STATUS_SEE_ERRNO;
+        guac_error_message = "Error reading data from secure socket";
+    }
+
+    return retval;
+
+}
+
+static ssize_t __guac_socket_ssl_write_handler(guac_socket* socket,
+        const void* buf, size_t count) {
+
+    /* Write data to socket */
+    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
+    int retval;
+
+    retval = SSL_write(data->ssl, buf, count);
+
+    /* Record errors in guac_error */
+    if (retval <= 0) {
+        guac_error = GUAC_STATUS_SEE_ERRNO;
+        guac_error_message = "Error writing data to secure socket";
+    }
+
+    return retval;
+
+}
+
+static int __guac_socket_ssl_select_handler(guac_socket* socket, int 
usec_timeout) {
+
+    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
+
+    int retval;
+
+    /* Initialize with single underlying file descriptor */
+    struct pollfd fds[1] = {{
+        .fd      = data->fd,
+        .events  = POLLIN,
+        .revents = 0,
+    }};
+
+    /* No timeout if usec_timeout is negative */
+    if (usec_timeout < 0)
+        retval = poll(fds, 1, -1);
+
+    /* Handle timeout if specified, rounding up to poll()'s granularity */
+    else
+        retval = poll(fds, 1, (usec_timeout + 999) / 1000);
+
+    /* Properly set guac_error */
+    if (retval <  0) {
+        guac_error = GUAC_STATUS_SEE_ERRNO;
+        guac_error_message = "Error while waiting for data on secure socket";
+    }
+
+    if (retval == 0) {
+        guac_error = GUAC_STATUS_TIMEOUT;
+        guac_error_message = "Timeout while waiting for data on secure socket";
+    }
+
+    return retval;
+
+}
+
+static int __guac_socket_ssl_free_handler(guac_socket* socket) {
+
+    /* Shutdown SSL */
+    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
+    SSL_shutdown(data->ssl);
+
+    /* Close file descriptor */
+    close(data->fd);
+
+    free(data);
+    return 0;
+}
+
+guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) {
+
+    /* Allocate socket and associated data */
+    guac_socket* socket = guac_socket_alloc();
+    guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data));
+
+    /* Init SSL */
+    data->context = context;
+    data->ssl = SSL_new(context);
+    SSL_set_fd(data->ssl, fd);
+
+    /* Accept SSL connection, handle errors */
+    if (SSL_accept(data->ssl) <= 0) {
+
+        guac_error = GUAC_STATUS_INTERNAL_ERROR;
+        guac_error_message = "SSL accept failed";
+
+        free(data);
+        guac_socket_free(socket);
+        return NULL;
+    }
+
+    /* Store file descriptor as socket data */
+    data->fd = fd;
+    socket->data = data;
+
+    /* Set read/write handlers */
+    socket->read_handler   = __guac_socket_ssl_read_handler;
+    socket->write_handler  = __guac_socket_ssl_write_handler;
+    socket->select_handler = __guac_socket_ssl_select_handler;
+    socket->free_handler   = __guac_socket_ssl_free_handler;
+
+    return socket;
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/socket-ssl.h
----------------------------------------------------------------------
diff --git a/src/libguacd/socket-ssl.h b/src/libguacd/socket-ssl.h
new file mode 100644
index 0000000..e1a341e
--- /dev/null
+++ b/src/libguacd/socket-ssl.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 __GUACD_SOCKET_SSL_H
+#define __GUACD_SOCKET_SSL_H
+
+#include "config.h"
+
+#include <guacamole/socket.h>
+#include <openssl/ssl.h>
+
+/**
+ * SSL socket-specific data.
+ */
+typedef struct guac_socket_ssl_data {
+
+    /**
+     * The file descriptor that SSL communication will take place
+     * over.
+     */
+    int fd;
+
+    /**
+     * The current SSL context.
+     */
+    SSL_CTX* context;
+
+    /**
+     * The SSL connection, created automatically via
+     * guac_socket_open_secure().
+     */
+    SSL* ssl;
+
+} guac_socket_ssl_data;
+
+/**
+ * Creates a new guac_socket which will use SSL for all communication. Freeing
+ * this guac_socket will automatically close the associated file descriptor.
+ *
+ * @param context
+ *     The SSL_CTX structure describing the desired SSL configuration.
+ *
+ * @param fd
+ *     The file descriptor to use for the SSL connection underlying the
+ *     created guac_socket.
+ *
+ * @return
+ *     A newly-allocated guac_socket which will transparently use SSL for
+ *     all communication.
+ */
+guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/user.c
----------------------------------------------------------------------
diff --git a/src/libguacd/user.c b/src/libguacd/user.c
new file mode 100644
index 0000000..0a37147
--- /dev/null
+++ b/src/libguacd/user.c
@@ -0,0 +1,113 @@
+/*
+ * 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 "user.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>
+
+void* guacd_user_input_thread(void* data) {
+
+    guacd_user_input_thread_params* params = (guacd_user_input_thread_params*) 
data;
+    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, GUACD_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;
+
+}
+
+int guacd_user_start(guac_parser* parser, guac_user* user) {
+
+    guacd_user_input_thread_params params = {
+        .parser = parser,
+        .user = user
+    };
+
+    pthread_t input_thread;
+
+    if (pthread_create(&input_thread, NULL, guacd_user_input_thread, (void*) 
&params)) {
+        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;
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d7a604c8/src/libguacd/user.h
----------------------------------------------------------------------
diff --git a/src/libguacd/user.h b/src/libguacd/user.h
new file mode 100644
index 0000000..65eef70
--- /dev/null
+++ b/src/libguacd/user.h
@@ -0,0 +1,98 @@
+/*
+ * 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 _GUACD_USER_H
+#define _GUACD_USER_H
+
+#include "config.h"
+
+#include <guacamole/parser.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+
+/**
+ * The number of milliseconds to wait for messages in any phase before
+ * timing out and closing the connection with an error.
+ */
+#define GUACD_TIMEOUT      15000
+
+/**
+ * The number of microseconds to wait for messages in any phase before
+ * timing out and closing the conncetion with an error. This is always
+ * equal to GUACD_TIMEOUT * 1000.
+ */
+#define GUACD_USEC_TIMEOUT (GUACD_TIMEOUT*1000)
+
+/**
+ * The maximum number of concurrent connections to a single instance
+ * of guacd.
+ */
+#define GUACD_CLIENT_MAX_CONNECTIONS 65536
+
+/**
+ * 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;
+
+} guacd_user_input_thread_params;
+
+/**
+ * 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.
+ *
+ * @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.
+ */
+int guacd_user_start(guac_parser* parser, guac_user* user);
+
+/**
+ * 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.
+ */
+void* guacd_user_input_thread(void* data);
+
+#endif
+

Reply via email to