diff --git a/README-windows-build.md b/README-windows-build.md index fda9cc36eb..81a8eb3c87 100644 --- a/README-windows-build.md +++ b/README-windows-build.md @@ -2,22 +2,21 @@ The `guacamole-server` Windows build relies on compatibility features provided by Cygwin (most notably, a `fork()` implmentation), and therefore _must_ be built using Cygwin tools. Since no Cygwin cross-compilation environment exists, this means that `guacamole-server` can only be built for Windows using the Windows OS. This document describes a build that produces a working `guacd.exe`, as well as shared libraries for every supported protocol. ## Build Specifics -In this example, `guacamole-server` was built under Cygwin, on a Windows Server 2022 x86_64 build node. Dependencies were installed using packages from Cygwin and MSYS2 (and built from source where no package is available, in the case of `libtelnet`). +In this example, `guacamole-server` was built under Cygwin, on a Windows Server 2022 x86_64 build node. Dependencies were installed using packages from Cygwin and MSYS2 (and built from source where no suitable package is available, in the case of `libtelnet` and `libfreerdp2`). ### Build Steps 1. Install Cygwin (version 2.926 used here) 2. Install MSYS2 (version 20230718 used here) 3. Install Cygwin packages: - * git - * make - * automake * autoconf + * automake + * cmake + * git * gcc-core * libtool - * pkg-config * libuuid-devel - * libwinpr2-devel - * libfreerdp2-devel + * make + * pkg-config 4. Install MSYS2 packages: * autoconf-wrapper * automake-wrapper @@ -54,7 +53,54 @@ In this example, `guacamole-server` was built under Cygwin, on a Windows Server # Required for the Cygwin build to understand how to link against this DLL ln -s /usr/bin/msys-telnet-2.dll /usr/bin/libtelnet.dll ``` -6. Build `guacamole-server` from source using Cygwin bash shell +5. Build `libfreerdp2` from source using Cygwin bash shell + ``` + curl -s -L https://github.com/FreeRDP/FreeRDP/archive/2.10.0/FreeRDP-2.10.0.tar.gz | tar xz + cd FreeRDP-2.10.0 + + cmake \ + -DWITH_ALSA=OFF \ + -DWITH_CUPS=OFF \ + -DWITH_CHANNELS=ON \ + -DBUILTIN_CHANNELS=OFF \ + -DCHANNEL_URBDRC=OFF \ + -DWITH_CLIENT=ON \ + -DWITH_DIRECTFB=OFF \ + -DWITH_FFMPEG=OFF \ + -DWITH_GSM=OFF \ + -DWITH_GSSAPI=OFF \ + -DWITH_GSTREAMER_1_0=OFF \ + -DWITH_GSTREAMER_0_10=OFF \ + -DWITH_IPP=OFF \ + -DWITH_JPEG=ON \ + -DWITH_MANPAGES=ON \ + -DWITH_OPENH264=OFF \ + -DWITH_OPENSSL=ON \ + -DWITH_PCSC=OFF \ + -DWITH_PULSE=OFF \ + -DWITH_SERVER=OFF \ + -DWITH_SERVER_INTERFACE=OFF \ + -DWITH_SHADOW_X11=OFF \ + -DWITH_SHADOW_MAC=OFF \ + -DWITH_SSE2=$SSE2_SETTING \ + -DWITH_WAYLAND=OFF \ + -DWITH_X11=OFF \ + -DWITH_X264=OFF \ + -DWITH_XCURSOR=ON \ + -DWITH_XEXT=ON \ + -DWITH_XKBFILE=ON \ + -DWITH_XI=OFF \ + -DWITH_XINERAMA=OFF \ + -DWITH_XRENDER=OFF \ + -DWITH_XTEST=OFF \ + -DWITH_XV=OFF \ + -DWITH_ZLIB=ON \ + . + cmake . -G"Unix Makefiles" + make + make install + ``` +7. Build `guacamole-server` from source using Cygwin bash shell ``` # FIXME: Update this to check out master once this PR is ready for merge git clone https://github.com/jmuehlner/guacamole-server.git @@ -63,12 +109,9 @@ In this example, `guacamole-server` was built under Cygwin, on a Windows Server autoreconf -fi export LDFLAGS="-L/usr/bin/ -L/usr/lib/ -L/usr/local/lib -L/usr/local/bin -L/cygdrive/c/msys64/mingw64/bin -L/cygdrive/c/msys64/mingw64/lib -L/cygdrive/c/msys64/usr/bin" - export CFLAGS="-idirafter /cygdrive/c/msys64/mingw64/include/winpr2 -idirafter /usr/include/ -idirafter /cygdrive/c/msys64/mingw64/include -idirafter /cygdrive/c/msys64/mingw64/include/pango-1.0 -idirafter /cygdrive/c/msys64/mingw64/include/cairo -idirafter /cygdrive/c/msys64/mingw64/include/freerdp2 -idirafter /cygdrive/c/msys64/mingw64/include/glib-2.0 -idirafter /cygdrive/c/msys64/mingw64/include/harfbuzz -idirafter /cygdrive/c/msys64/mingw64/lib/glib-2.0/include -idirafter /cygdrive/c/msys64/usr/include" - export PKG_CONFIG_PATH="/cygdrive/c/msys64/mingw64/lib/pkgconfig/" - - # NOTE: The libfreerdp2-devel package provided by Cygwin is detected as a snapshot version, and must be explicitly allowed - ./configure --with-cygwin --enable-allow-freerdp-snapshots || cat config.log - + export CFLAGS="-idirafter /cygdrive/c/msys64/mingw64/include/winpr2 -idirafter /usr/include/ -idirafter /cygdrive/c/msys64/mingw64/include -idirafter /cygdrive/c/msys64/mingw64/include/pango-1.0 -idirafter /cygdrive/c/msys64/mingw64/include/cairo -idirafter /usr/local/include/freerdp2 -idirafter /cygdrive/c/msys64/mingw64/include/glib-2.0 -idirafter /cygdrive/c/msys64/mingw64/include/harfbuzz -idirafter /cygdrive/c/msys64/mingw64/lib/glib-2.0/include -idirafter /cygdrive/c/msys64/usr/include" + export PKG_CONFIG_PATH="/cygdrive/c/msys64/mingw64/lib/pkgconfig/:/usr/local/lib/pkgconfig" + ./configure --with-cygwin || cat config.log make ``` diff --git a/src/libguac/client.c b/src/libguac/client.c index b904fb7e42..cd43816292 100644 --- a/src/libguac/client.c +++ b/src/libguac/client.c @@ -252,6 +252,8 @@ static void guac_client_promote_pending_users(union sigval data) { guac_client* guac_client_alloc() { + fprintf(stderr, "guac_client_alloc start\n"); + int i; /* Allocate new client */ @@ -308,12 +310,16 @@ guac_client* guac_client_alloc() { client->socket = guac_socket_broadcast(client); client->pending_socket = guac_socket_broadcast_pending(client); + fprintf(stderr, "guac_client_alloc end\n"); + return client; } void guac_client_free(guac_client* client) { + fprintf(stderr, "guac_client_free start\n"); + /* Acquire write locks before referencing user pointers */ guac_rwlock_acquire_write_lock(&(client->__pending_users_lock)); guac_rwlock_acquire_write_lock(&(client->__users_lock)); @@ -376,6 +382,8 @@ void guac_client_free(guac_client* client) { free(client->connection_id); free(client); + + fprintf(stderr, "guac_client_free end\n"); } void vguac_client_log(guac_client* client, guac_client_log_level level, @@ -450,6 +458,8 @@ void guac_client_abort(guac_client* client, guac_protocol_status status, static void guac_client_add_pending_user( guac_client* client, guac_user* user) { + fprintf(stderr, "guac_client_add_pending_user start\n"); + /* Acquire the lock for modifying the list of pending users */ guac_rwlock_acquire_write_lock(&(client->__pending_users_lock)); @@ -467,6 +477,8 @@ static void guac_client_add_pending_user( /* Release the lock */ guac_rwlock_release_lock(&(client->__pending_users_lock)); + fprintf(stderr, "guac_client_add_pending_user end\n"); + } /** @@ -484,6 +496,8 @@ static void guac_client_add_pending_user( */ static int guac_client_start_pending_users_timer(guac_client* client) { + fprintf(stderr, "guac_client_start_pending_users_timer start\n"); + pthread_mutex_lock(&(client->__pending_users_timer_mutex)); /* Return success if the timer is already created and running */ @@ -526,12 +540,17 @@ static int guac_client_start_pending_users_timer(guac_client* client) { client->__pending_users_timer_state = GUAC_CLIENT_PENDING_TIMER_REGISTERED; pthread_mutex_unlock(&(client->__pending_users_timer_mutex)); + + fprintf(stderr, "guac_client_start_pending_users_timer end\n"); + return 0; } int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** argv) { + fprintf(stderr, "guac_client_add_user start\n"); + /* Create and start the timer if it hasn't already been initialized */ if (guac_client_start_pending_users_timer(client)) { @@ -569,12 +588,16 @@ int guac_client_add_user(guac_client* client, guac_user* user, int argc, char** if (retval == 0 && !user->owner) guac_client_owner_notify_join(client, user); + fprintf(stderr, "guac_client_add_user end\n"); + return retval; } void guac_client_remove_user(guac_client* client, guac_user* user) { + fprintf(stderr, "guac_client_remove_user start\n"); + guac_rwlock_acquire_write_lock(&(client->__pending_users_lock)); guac_rwlock_acquire_write_lock(&(client->__users_lock)); @@ -609,10 +632,14 @@ void guac_client_remove_user(guac_client* client, guac_user* user) { else if (client->leave_handler) client->leave_handler(user); + fprintf(stderr, "guac_client_remove_user end\n"); + } void guac_client_foreach_user(guac_client* client, guac_user_callback* callback, void* data) { + fprintf(stderr, "guac_client_foreach_user start\n"); + guac_user* current; guac_rwlock_acquire_read_lock(&(client->__users_lock)); @@ -626,11 +653,15 @@ void guac_client_foreach_user(guac_client* client, guac_user_callback* callback, guac_rwlock_release_lock(&(client->__users_lock)); + fprintf(stderr, "guac_client_foreach_user end\n"); + } void guac_client_foreach_pending_user( guac_client* client, guac_user_callback* callback, void* data) { + fprintf(stderr, "guac_client_foreach_pending_user start\n"); + guac_user* current; guac_rwlock_acquire_read_lock(&(client->__pending_users_lock)); @@ -644,11 +675,15 @@ void guac_client_foreach_pending_user( guac_rwlock_release_lock(&(client->__pending_users_lock)); + fprintf(stderr, "guac_client_foreach_pending_user end\n"); + } void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, void* data) { + fprintf(stderr, "guac_client_for_owner start\n"); + void* retval; guac_rwlock_acquire_read_lock(&(client->__users_lock)); @@ -658,6 +693,8 @@ void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, guac_rwlock_release_lock(&(client->__users_lock)); + fprintf(stderr, "guac_client_for_owner end\n"); + /* Return value from callback */ return retval; @@ -666,6 +703,8 @@ void* guac_client_for_owner(guac_client* client, guac_user_callback* callback, void* guac_client_for_user(guac_client* client, guac_user* user, guac_user_callback* callback, void* data) { + fprintf(stderr, "guac_client_for_user start\n"); + guac_user* current; int user_valid = 0; @@ -695,6 +734,8 @@ void* guac_client_for_user(guac_client* client, guac_user* user, guac_rwlock_release_lock(&(client->__users_lock)); + fprintf(stderr, "guac_client_for_user end\n"); + /* Return value from callback */ return retval; @@ -706,6 +747,8 @@ int guac_client_end_frame(guac_client* client) { int guac_client_end_multiple_frames(guac_client* client, int frames) { + fprintf(stderr, "guac_client_end_multiple_frames start\n"); + /* Update and send timestamp */ client->last_sent_timestamp = guac_timestamp_current(); @@ -713,12 +756,16 @@ int guac_client_end_multiple_frames(guac_client* client, int frames) { guac_client_log(client, GUAC_LOG_TRACE, "Server completed " "frame %" PRIu64 "ms (%i logical frames)", client->last_sent_timestamp, frames); + fprintf(stderr, "guac_client_end_multiple_frames end\n"); + return guac_protocol_send_sync(client->socket, client->last_sent_timestamp, frames); } int guac_client_load_plugin(guac_client* client, const char* protocol) { + fprintf(stderr, "guac_client_load_plugin start\n"); + /* Reference to dlopen()'d plugin */ void* client_plugin_handle; @@ -766,6 +813,8 @@ int guac_client_load_plugin(guac_client* client, const char* protocol) { /* Init client */ client->__plugin_handle = client_plugin_handle; + fprintf(stderr, "guac_client_load_plugin end\n"); + return alias.client_init(client); } @@ -1043,6 +1092,8 @@ int guac_client_owner_supports_required(guac_client* client) { */ static void* guac_client_owner_notify_join_callback(guac_user* user, void* data) { + fprintf(stderr, "guac_client_owner_notify_join_callback start\n"); + const guac_user* joiner = (const guac_user *) data; if (user == NULL) @@ -1064,6 +1115,8 @@ static void* guac_client_owner_notify_join_callback(guac_user* user, void* data) /* Send user joined notification to owner. */ const char* args[] = { (const char*)joiner->user_id, (const char*)send_joiner, NULL }; + + fprintf(stderr, "guac_client_owner_notify_join_callback end\n"); return (void*) ((intptr_t) guac_protocol_send_msg(user->socket, GUAC_MESSAGE_USER_JOINED, args)); } diff --git a/src/protocols/vnc/client.c b/src/protocols/vnc/client.c index ea7d44b3cb..d0331920e1 100644 --- a/src/protocols/vnc/client.c +++ b/src/protocols/vnc/client.c @@ -55,10 +55,14 @@ */ static void* guac_vnc_sync_pending_user_audio(guac_user* user, void* data) { + fprintf(stderr, "guac_vnc_sync_pending_user_audio start\n"); + /* Add the user to the stream */ guac_pa_stream* audio = (guac_pa_stream*) data; guac_pa_stream_add_user(audio, user); + fprintf(stderr, "guac_vnc_sync_pending_user_audio end\n"); + return NULL; } @@ -76,6 +80,8 @@ static void* guac_vnc_sync_pending_user_audio(guac_user* user, void* data) { */ static int guac_vnc_join_pending_handler(guac_client* client) { + fprintf(stderr, "guac_vnc_sync_pending_user_audio start\n"); + guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; guac_socket* broadcast_socket = client->pending_socket; @@ -92,12 +98,16 @@ static int guac_vnc_join_pending_handler(guac_client* client) { guac_socket_flush(broadcast_socket); } + fprintf(stderr, "guac_vnc_sync_pending_user_audio end\n"); + return 0; } int guac_client_init(guac_client* client) { + fprintf(stderr, "guac_client_init (VNC) start\n"); + /* Set client args */ client->args = GUAC_VNC_CLIENT_ARGS; @@ -211,6 +221,8 @@ int guac_vnc_client_free_handler(guac_client* client) { /* Free generic data struct */ free(client->data); + fprintf(stderr, "guac_client_init (VNC) end\n"); + return 0; }