You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@guacamole.apache.org by GitBox <gi...@apache.org> on 2020/01/04 22:34:07 UTC

[GitHub] [guacamole-server] mike-jumper opened a new pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

mike-jumper opened a new pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243
 
 
   This change refactors the entirety of Guacamole's RDP support to use FreeRDP 2.x, removing any remaining compatibility with older FreeRDP releases. These changes also:
   
   * Reorganize the source tree in the hopes of making things more maintainable going forward
   * Add missing documentation
   * Add support for the new "extended NLA" mode added by FreeRDP 2.x (I'm not entirely sure what this is, however) and switch over to "any" as the default security method (rather than "rdp").
   * Remove most plugins, replacing guacsvc/guacsnd/guacdr with a single common SVC plugin. The RDP support leverages that common plugin to provide a single API which the arbitrary SVC, RDPSND, and RDPDR support then use without having to make plugins for each.
   
   There are going to be conflicts with master for the following non-1.1.0 changes:
   
   * [GUACAMOLE-296](https://issues.apache.org/jira/browse/GUACAMOLE-296) - Migrating to FreeRDP 2.x removes the need for this, as libwinpr is now automatically linked using pkgconfig.
   * [GUACAMOLE-381](https://issues.apache.org/jira/browse/GUACAMOLE-381) - Support for clipboard copy/paste disable flags within CLIPRDR need to be manually re-added due to the number of changes made to CLIPRDR (see below). Much of this applies cleanly without conflict.
   * [GUACAMOLE-764](https://issues.apache.org/jira/browse/GUACAMOLE-764) - Most applied cleanly without conflict, however one `int` -> `uint64_t` change has to be reapplied manually (see below).
   * [GUACAMOLE-847](https://issues.apache.org/jira/browse/GUACAMOLE-847) - The RDPSND memory leak is now inherently resolved via the common SVC plugin and changes to channel memory handling in FreeRDP 2.x.
   
   To hopefully ease this, I've performed a test merge and manually resolved the above conflicts. I recommend resolving conflicts such that things match: https://github.com/mike-jumper/guacamole-server/tree/freerdp-migrate-2.x-resolve-merge-master
   
   ... Good luck.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364060743
 
 

 ##########
 File path: configure.ac
 ##########
 @@ -541,507 +540,17 @@ AC_ARG_WITH([rdp],
 
 if test "x$with_rdp" != "xno"
 then
-    have_winpr=yes
-    have_freerdp=yes
-    legacy_freerdp_extensions=no
-    rdpsettings_interface=unknown
-    rdpsettings_audiocapture=yes
-    rdpsettings_audioplayback=yes
-    rdpsettings_deviceredirection=yes
-    freerdp_interface=unknown
-    event_interface=unknown
-
-    # libfreerdp-core / libfreerdp
-    AC_CHECK_LIB([freerdp-core], [freerdp_new],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-core"],
-                 [AC_CHECK_LIB([freerdp], [freerdp_new],
-                               [RDP_LIBS="$RDP_LIBS -lfreerdp -lfreerdp-client"],
-                               [AC_MSG_WARN([
+    have_freerdp2=yes
+    PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],,
+                      [AC_MSG_WARN([
   --------------------------------------------
-   Unable to find libfreerdp-core / libfreerdp
+   Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2)
    RDP will be disabled.
   --------------------------------------------])
-                  have_freerdp=no])])
+                       have_freerdp2=no])
 fi
 
-
-# libfreerdp-cache
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-cache], [glyph_cache_register_callbacks],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-cache"])
-fi
-
-# libfreerdp-channels (1.0) / libfreerdp-client + libfreerdp-core (1.1)
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-client], [freerdp_channels_new],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-client"],
-                 [AC_CHECK_LIB([freerdp-channels], [freerdp_channels_new],
-                               [RDP_LIBS="$RDP_LIBS -lfreerdp-channels"
-                               legacy_freerdp_extensions=yes])],
-                 [-lfreerdp-core])
-fi
-
-# libfreerdp-utils
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-utils], [svc_plugin_init],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-utils"])
-fi
-
-# libfreerdp-codec
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-codec], [freerdp_image_convert],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-codec"])
-fi
-
-# Available color conversion functions
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([freerdp_convert_gdi_order_color],
-        [AC_DEFINE([HAVE_FREERDP_CONVERT_GDI_ORDER_COLOR],,
-                   [Whether freerdp_convert_gdi_order_color() is defined])],,
-        [#include <freerdp/codec/color.h>])
-
-    AC_CHECK_DECL([freerdp_color_convert_drawing_order_color_to_gdi_color],
-        [AC_DEFINE([HAVE_FREERDP_COLOR_CONVERT_DRAWING_ORDER_COLOR_TO_GDI_COLOR],,
-                   [Whether freerdp_color_convert_drawing_order_color_to_gdi_color() is defined])],,
-        [#include <freerdp/codec/color.h>])
-fi
-
-# Check for interval polling in plugins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSvcPlugin.interval_ms],,,
-                     [[#include <freerdp/utils/svc_plugin.h>]])
-fi
-
-# Keyboard layout header
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/locale/keyboard.h],,
-                      [AC_CHECK_HEADERS([freerdp/kbd/layouts.h],,
-                                       [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find keyboard layout headers
-   RDP will be disabled.
-  --------------------------------------------])
-                                        have_freerdp=no])])
-fi
-
-# New headers defining addins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/addin.h freerdp/client/channels.h])
-fi
-
-# Header defining cliprdr
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/client/cliprdr.h],,
-                     [AC_CHECK_HEADERS([freerdp/plugins/cliprdr.h],,
-                                       [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find cliprdr headers
-   RDP will be disabled.
-  --------------------------------------------])
-                                        have_freerdp=no],
-                                       [#include <freerdp/types.h>])],
-                     [#include <winpr/wtypes.h>
-                      #include <winpr/collections.h>])
-fi
-
-# Header defining display update channel
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/client/disp.h],
-                     [AC_DEFINE([HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT],,
-                                [Whether FreeRDP supports the display update channel])]
-                     [AC_CHECK_MEMBERS([rdpSettings.SupportDisplayControl],,,
-                                       [[#include <freerdp/freerdp.h>]])],,
-                     [#include <winpr/wtypes.h>
-                      #include <winpr/collections.h>])
-fi
-
-# Support for RDP gateways 
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSettings.GatewayEnabled],
-                     [AC_DEFINE([HAVE_FREERDP_GATEWAY_SUPPORT],,
-                                [Whether FreeRDP supports RDP gateways])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-# Support for load balancing via connection brokers 
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSettings.LoadBalanceInfo],
-                     [AC_DEFINE([HAVE_FREERDP_LOAD_BALANCER_SUPPORT],,
-                                [Whether FreeRDP supports load balancers])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-# Support for "PubSub" event system
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([PubSub_SubscribeChannelConnected],
-        [AC_DEFINE([HAVE_FREERDP_EVENT_PUBSUB],,
-                   [Whether this version of FreeRDP provides the PubSub event system])],,
-        [#include <freerdp/event.h>])
-fi
-
-# Addin registration variations
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([freerdp_register_addin_provider],
-        [AC_DEFINE([HAVE_FREERDP_REGISTER_ADDIN_PROVIDER],,
-                   [Whether freerdp_register_addin_provider() is defined])],,
-        [#include <freerdp/addin.h>])
-
-    AC_CHECK_DECL([freerdp_channels_global_init],
-        [AC_DEFINE([HAVE_FREERDP_CHANNELS_GLOBAL_INIT],,
-                   [Whether freerdp_channels_global_init() is defined])],,
-        [#include <freerdp/channels/channels.h>])
-fi
-
-# Availability of ADDIN_ARGV structure for configuring plugins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_TYPE([ADDIN_ARGV],
-        [AC_DEFINE([HAVE_ADDIN_ARGV],,
-                   [Whether the ADDIN_ARGV type is available])],,
-        [#include <freerdp/settings.h>])
-fi
-
-#
-# FreeRDP: WinPR
-#
-
-# Check for stream support via WinPR
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADER(winpr/stream.h,,
-                    [have_winpr=no,
-                     AC_CHECK_DECL([stream_write_uint8],,
-                                  [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find stream support
-   RDP will be disabled.
-  --------------------------------------------])
-                                   have_freerdp=no],
-                                  [#include <freerdp/utils/stream.h>])])
-fi
-
-# Check for types in WinPR
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADER(winpr/wtypes.h,,
-                    [have_winpr=no,
-                     AC_CHECK_HEADER(freerdp/types.h,,
-                                     [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find type definitions
-   RDP will be disabled.
-  --------------------------------------------])
-                                      have_freerdp=no])])
-fi
-
-if test "x${have_freerdp}" = "xyes" -a "x${have_winpr}" = "xyes"
-then
-    AC_DEFINE([ENABLE_WINPR],,
-              [Whether library support for WinPR types was found])
-fi
-
-#
-# FreeRDP: freerdp 
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    # Check for current (as of 1.1) freerdp interface
-    AC_CHECK_MEMBERS([freerdp.ContextSize],
-                     [freerdp_interface=stable],,
-                     [[#include <freerdp/freerdp.h>]])
-
-    # If not current, check for legacy interface
-    if test "x${freerdp_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([freerdp.context_size],
-                         [freerdp_interface=legacy],,
-                         [[#include <freerdp/freerdp.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${freerdp_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_FREERDP],,
-                  [Whether the older version of the FreeRDP API was found])
-    elif test "x${freerdp_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown FreeRDP interface
-   RDP will be disabled.
-  --------------------------------------------])
-        have_freerdp=no
-    fi
-fi
-
-#
-# FreeRDP: rdpSettings
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    # Check for current (as of 1.1) rdpSettings interface
-    AC_CHECK_MEMBERS([rdpSettings.Width,
-                      rdpSettings.Height,
-                      rdpSettings.FastPathInput,
-                      rdpSettings.FastPathOutput,
-                      rdpSettings.SendPreconnectionPdu,
-                      rdpSettings.OrderSupport],
-                     [rdpsettings_interface=stable],,
-                     [[#include <freerdp/freerdp.h>]])
-
-    # If not current, check for legacy interface
-    if test "x${rdpsettings_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([rdpSettings.width,
-                          rdpSettings.height,
-                          rdpSettings.order_support],
-                         [rdpsettings_interface=legacy],,
-                         [[#include <freerdp/freerdp.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${rdpsettings_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_RDPSETTINGS],,
-                  [Whether the legacy version of the rdpSettings API was found])
-
-        # Legacy interface may not have AudioPlayback settings
-        AC_CHECK_MEMBERS([rdpSettings.audio_playback],,
-                         [rdpsettings_audioplayback=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-        # Legacy interface may not have AudioCapture settings
-        AC_CHECK_MEMBERS([rdpSettings.audio_capture],,
-                         [rdpsettings_audiocapture=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-        # Legacy interface may not have DeviceRedirection settings
-        AC_CHECK_MEMBERS([rdpSettings.device_redirection],,
-                         [rdpsettings_deviceredirection=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-    elif test "x${rdpsettings_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown rdpSettings interface
-   RDP will be disabled.
-  --------------------------------------------]) 
-        have_freerdp=no
-    fi
-fi
-
-# Activate audio playback settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audioplayback}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_AUDIOPLAYBACK],,
-              [Whether the rdpSettings structure has AudioPlayback settings])
-fi
-
-# Activate audio capture settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audiocapture}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_AUDIOCAPTURE],,
-              [Whether the rdpSettings structure has AudioCapture settings])
-fi
-
-# Activate device redirection settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_deviceredirection}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_DEVICEREDIRECTION],,
-              [Whether the rdpSettings structure has DeviceRedirection settings])
-fi
-
-# Check if the type CHANNEL_ENTRY_POINTS_FREERDP exists, if not define it to CHANNEL_ENTRY_POINTS_EX
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_TYPE([CHANNEL_ENTRY_POINTS_FREERDP],,
-                  AC_DEFINE([CHANNEL_ENTRY_POINTS_FREERDP],[CHANNEL_ENTRY_POINTS_EX], [Type compatibility]),
-                  [[#include <freerdp/svc.h>]])
-fi
-
-# Check if the freerdp version header exists
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/version.h])
-fi
-
-#
-# FreeRDP: rdpBitmap
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether rdpBitmap.Decompress() requires the codec_id])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <winpr/wtypes.h>
-                                        #include <freerdp/freerdp.h>
-                                        void __decompress(rdpContext* context,
-                                                          rdpBitmap* bitmap,
-                                                          UINT8* data,
-                                                          int width,
-                                                          int height,
-                                                          int bpp,
-                                                          int length,
-                                                          BOOL compressed,
-                                                          int codec_id);
-                                        rdpBitmap b = { .Decompress = __decompress };]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_RDPBITMAP],,
-                                 [Whether the legacy rdpBitmap API was found])])
-fi
-
-#
-# FreeRDP: IWTSVirtualChannelCallback
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether IWTSVirtualChannelCallback.OnDataReceived() uses a wStream])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <winpr/wtypes.h>
-                                        #include <freerdp/dvc.h>
-                                        #include <freerdp/freerdp.h>
-                                        int __data_received(
-                                            IWTSVirtualChannelCallback* channel_callback,
-                                            wStream* stream);
-                                        IWTSVirtualChannelCallback cb = {
-                                            .OnDataReceived = __data_received
-                                        };
-                                        int main() {
-                                            return
-                                                cb.OnDataReceived(NULL, NULL);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_IWTSVIRTUALCHANNELCALLBACK],,
-                                 [Whether the legacy IWTSVirtualChannelCallback API was found])])
-fi
-
-#
-# FreeRDP: Decompression function variants
-#
-
-# Check whether interleaved_decompress() can handle the palette
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether interleaved_decompress() accepts an additional palette parameter])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/codec/interleaved.h>
-
-                                        int main() {
-                                            BYTE* palette = NULL;
-                                            interleaved_decompress(NULL, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, palette);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])
-                       AC_DEFINE([INTERLEAVED_DECOMPRESS_TAKES_PALETTE],,
-                                 [Whether interleaved_decompress() accepts an additional palette parameter])],
-                      [AC_MSG_RESULT([no])])
-fi
-
-# Check whether planar_decompress() will handle flipping
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether planar_decompress() can flip])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/codec/planar.h>
-
-                                        int main() {
-                                            BOOL* flip = TRUE;
-                                            planar_decompress(NULL, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, flip);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])
-                       AC_DEFINE([PLANAR_DECOMPRESS_CAN_FLIP],,
-                                 [Whether planar_decompress() can flip])],
-                      [AC_MSG_RESULT([no])])
-fi
-
-#
-# FreeRDP: rdpContext
-#
-
-# Check for rdpContext.codecs
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpContext.codecs],
-                     [AC_DEFINE([FREERDP_BITMAP_REQUIRES_ALIGNED_MALLOC],,
-                                [Whether this version of FreeRDP requires _aligned_malloc() for bitmap data])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-#
-# FreeRDP: rdpPalette
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether rdpPalette.entries is static])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/update.h>
-                                        rdpPalette p;
-                                        PALETTE_ENTRY* foo = p.entries;]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_RDPPALETTE],,
-                                 [Whether the legacy rdpPalette API was found])])
-fi
-
-#
-# FreeRDP: rdpPointer
-#
-
-# Check for SetDefault and SetNull members of rdpPointer
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpPointer.SetDefault,
-                      rdpPointer.SetNull],
-                     ,,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-#
-# FreeRDP: wMessage / RDP_EVENT
-#
-
-# Check for current (as of 1.1) wMessage interface
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([wMessage.id],
-                     [event_interface=stable],,
-                     [[#include <winpr/collections.h>]])
-
-    # If not current, check for legacy (RDP_EVENT) interface
-    if test "x${event_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([RDP_EVENT.event_class],
-                         [event_interface=legacy],,
-                         [[#include <freerdp/types.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${event_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_EVENT],,
-                  [Whether the legacy RDP_EVENT API was found])
-    elif test "x${event_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown event interface
-   RDP will be disabled.
-  --------------------------------------------])
-        have_freerdp=no
-    fi
-fi
-
-AM_CONDITIONAL([LEGACY_FREERDP_EXTENSIONS], [test "x${legacy_freerdp_extensions}" = "xyes"])
 
 Review comment:
   It's pretty awesome that all this stuff is going away!

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574134215
 
 
   Sounds good.  Giving @jmuehlner one last chance to throw in any input - otherwise I'll plan to merge it later today.
   
   You mentioned needing to deal with conflicts in the master - anything special that we need to worry about for that?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573888529
 
 
   Rerunning builds for all FreeRDP tags, it looks like the current code will build only against 2.0.0-rc4. Earlier tags suffer from the issues noted above for Bionic.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555182
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
 
 Review comment:
   My original thinking was that if `guac_rdp_cliprdr_send_capabilities()` fails, the following call to `guac_rdp_cliprdr_send_format_list()` should also fail. I'll add a check to handle both.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364972808
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   Should now be fixed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573458270
 
 
   > I'm not seeing those errors on my end. Which Linux distribution and version of FreeRDP are you building against?
   
   Just tried a fresh copy straight from Apache repo and same results.  I'm using CentOS7, freerdp-devel version is 2.0.0-1.rc4.el7 (latest, I think).  My process is:
   - Clone Apache repo
   - Checkout `staging/1.1.0`
   - Checkout pull/243/head to merge-243
   - Merge --no-ff merge-243
   - autoreconf -fi
   - ./configure --prefix=/opt/guac-test
   - make

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364364329
 
 

 ##########
 File path: src/protocols/rdp/download.c
 ##########
 @@ -0,0 +1,240 @@
+/*
+ * 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 "common/json.h"
+#include "download.h"
+#include "fs.h"
+#include "ls.h"
+#include "rdp.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/string.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+#include <winpr/shell.h>
+
+#include <stdlib.h>
+
+int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream,
+        char* message, guac_protocol_status status) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_download_status* download_status = (guac_rdp_download_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* If successful, read data */
+    if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
+
+        /* Attempt read into buffer */
+        char buffer[4096];
+        int bytes_read = guac_rdp_fs_read(fs,
+                download_status->file_id,
+                download_status->offset, buffer, sizeof(buffer));
+
+        /* If bytes read, send as blob */
+        if (bytes_read > 0) {
+            download_status->offset += bytes_read;
+            guac_protocol_send_blob(user->socket, stream,
+                    buffer, bytes_read);
+        }
+
+        /* If EOF, send end */
+        else if (bytes_read == 0) {
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        /* Otherwise, fail stream */
+        else {
+            guac_user_log(user, GUAC_LOG_ERROR,
+                    "Error reading file for download");
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        guac_socket_flush(user->socket);
+
+    }
+
+    /* Otherwise, return stream to user */
+    else
+        guac_user_free_stream(user, stream);
+
+    return 0;
+
+}
+
+int guac_rdp_download_get_handler(guac_user* user, guac_object* object,
+        char* name) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    /* Get filesystem, ignore request if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL)
+        return 0;
+
+    /* Attempt to open file for reading */
+    int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0);
+    if (file_id < 0) {
+        guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
+                name);
+        return 0;
+    }
+
+    /* Get opened file */
+    guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
+    if (file == NULL) {
+        guac_client_log(fs->client, GUAC_LOG_DEBUG,
+                "%s: Successful open produced bad file_id: %i",
+                __func__, file_id);
+        return 0;
+    }
+
+    /* If directory, send contents of directory */
+    if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) {
+
+        /* Create stream data */
+        guac_rdp_ls_status* ls_status = malloc(sizeof(guac_rdp_ls_status));
+        ls_status->fs = fs;
+        ls_status->file_id = file_id;
+        guac_strlcpy(ls_status->directory_name, name,
+                sizeof(ls_status->directory_name));
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->ack_handler = guac_rdp_ls_ack_handler;
+        stream->data = ls_status;
+
+        /* Init JSON object state */
+        guac_common_json_begin_object(user, stream,
+                &ls_status->json_state);
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                GUAC_USER_STREAM_INDEX_MIMETYPE, name);
+
+    }
+
+    /* Otherwise, send file contents */
+    else {
+
+        /* Create stream data */
+        guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status));
+        download_status->file_id = file_id;
+        download_status->offset = 0;
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->data = download_status;
+        stream->ack_handler = guac_rdp_download_ack_handler;
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                "application/octet-stream", name);
+
+    }
+
+    guac_socket_flush(user->socket);
+    return 0;
+}
+
+void* guac_rdp_download_to_user(guac_user* user, void* data) {
+
+    /* Do not bother attempting the download if the user has left */
+    if (user == NULL)
+        return NULL;
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_fs* filesystem = rdp_client->filesystem;
+
+    /* Ignore download if filesystem has been unloaded */
+    if (filesystem == NULL)
+        return NULL;
+
+    /* Attempt to open requested file */
+    char* path = (char*) data;
+    int file_id = guac_rdp_fs_open(filesystem, path,
+            FILE_READ_DATA, 0, FILE_OPEN, 0);
+
+    /* If file opened successfully, start stream */
+    if (file_id >= 0) {
+
+        guac_rdp_download_status* download_status;
+        const char* basename;
+
+        int i;
 
 Review comment:
   It was the coding style at the time that this function was originally written. The body of this function was actually moved from what used to be `rdpdr_service.c` and was originally called `guac_rdpdr_download_to_owner`:
   
   https://github.com/apache/guacamole-server/blob/f5b5ac718396b24352290d2fac976260f4b3829e/src/protocols/rdp/guac_rdpdr/rdpdr_service.c#L237-L303
   
   I can clean this up a bit now in the locations I can find such code.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365613342
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,605 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities ... */
+    int status = guac_rdp_cliprdr_send_capabilities(cliprdr);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    /* ... and supported format list */
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicates that clipboard data is available via a Format
+ * List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
 
 Review comment:
   `assert()` in C will cause SIGABRT to be sent to the process if the condition fails. If we were expecting `clipboard` to occasionally be `NULL`, then adding an `if` would be best here. In this case, it is reasoned that `clipboard` absolutely cannot be `NULL` under any circumstance where this code can be reached, and we declare that assumption with an `assert()`. Smart compilers, static checkers, etc. will take that `assert()` into account, and it allows the system to bail out if a required assumption ends up being false.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364085965
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-messages.c
 ##########
 @@ -0,0 +1,349 @@
+/*
+ * 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 "channels/rdpdr/rdpdr-messages.h"
+#include "channels/rdpdr/rdpdr.h"
+#include "rdp.h"
+#include "settings.h"
+
+#include <freerdp/channels/rdpdr.h>
+#include <guacamole/client.h>
+#include <winpr/stream.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Client Announce Reply message. The Client Announce Reply message is
+ * required to be sent in response to the Server Announce Request message. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param major
+ *     The major version of the RDPDR protocol in use. This value must always
+ *     be 1.
+ *
+ * @param minor
+ *     The minor version of the RDPDR protocol in use. This value must be
+ *     either 2, 5, 10, 12, or 13.
+ *
+ * @param client_id
+ *     The client ID received in the Server Announce Request, or a randomly
+ *     generated ID.
+ */
+static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc,
+        unsigned int major, unsigned int minor, unsigned int client_id) {
+
+    wStream* output_stream = Stream_New(NULL, 12);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENTID_CONFIRM);
+
+    /* Write content */
+    Stream_Write_UINT16(output_stream, major);
+    Stream_Write_UINT16(output_stream, minor);
+    Stream_Write_UINT32(output_stream, client_id);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+
+}
+
+/**
+ * Sends a Client Name Request message. The Client Name Request message is used
+ * by the client to announce its own name. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param name
+ *     The name that should be used for the client.
+ */
+static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc,
+        const char* name) {
+
+    int name_bytes = strlen(name) + 1;
+    wStream* output_stream = Stream_New(NULL, 16 + name_bytes);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_NAME);
+
+    /* Write content */
+    Stream_Write_UINT32(output_stream, 0); /* ASCII */
+    Stream_Write_UINT32(output_stream, 0); /* 0 required by RDPDR spec */
+    Stream_Write_UINT32(output_stream, name_bytes);
+    Stream_Write(output_stream, name, name_bytes);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+
+}
+
+/**
+ * Sends a Client Core Capability Response message. The Client Core Capability
+ * Response message is used to announce the client's capabilities, in response
+ * to receiving the server's capabilities via a Server Core Capability Request.
+ * See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/f513bf87-cca0-488a-ac5c-18cf18f4a7e1
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ */
+static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) {
+
+    wStream* output_stream = Stream_New(NULL, 256);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Sending capabilities...");
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_CAPABILITY);
+
+    /* Capability count + padding */
+    Stream_Write_UINT16(output_stream, 3);
+    Stream_Write_UINT16(output_stream, 0); /* Padding */
+
+    /* General capability header */
+    Stream_Write_UINT16(output_stream, CAP_GENERAL_TYPE);
+    Stream_Write_UINT16(output_stream, 44);
+    Stream_Write_UINT32(output_stream, GENERAL_CAPABILITY_VERSION_02);
+
+    /* General capability data */
+    Stream_Write_UINT32(output_stream, GUAC_OS_TYPE);                /* osType - required to be ignored */
+    Stream_Write_UINT32(output_stream, 0);                           /* osVersion */
+    Stream_Write_UINT16(output_stream, 1);                           /* protocolMajor - must be set to 1 */
+    Stream_Write_UINT16(output_stream, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinor */
+    Stream_Write_UINT32(output_stream, 0xFFFF);                      /* ioCode1 */
+    Stream_Write_UINT32(output_stream, 0);                           /* ioCode2 */
+    Stream_Write_UINT32(output_stream,
+                                      RDPDR_DEVICE_REMOVE_PDUS
+                                    | RDPDR_CLIENT_DISPLAY_NAME_PDU
+                                    | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
+    Stream_Write_UINT32(output_stream, 0);                      /* extraFlags1 */
+    Stream_Write_UINT32(output_stream, 0);                      /* extraFlags2 */
+    Stream_Write_UINT32(output_stream, 0);                      /* SpecialTypeDeviceCap */
+
+    /* Printer support header */
+    Stream_Write_UINT16(output_stream, CAP_PRINTER_TYPE);
+    Stream_Write_UINT16(output_stream, 8);
+    Stream_Write_UINT32(output_stream, PRINT_CAPABILITY_VERSION_01);
+
+    /* Drive support header */
+    Stream_Write_UINT16(output_stream, CAP_DRIVE_TYPE);
+    Stream_Write_UINT16(output_stream, 8);
+    Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Capabilities sent.");
+
+}
+
+/**
+ * Sends a Client Device List Announce Request message. The Client Device List
+ * Announce Request message is used by the client to enumerate all devices
+ * which should be made available within the RDP session via RDPDR. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ */
+static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) {
+
+    guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
+
+    /* Calculate number of bytes needed for the stream */
+    int streamBytes = 16;
+    for (int i=0; i < rdpdr->devices_registered; i++)
+        streamBytes += rdpdr->devices[i].device_announce_len;
+
+    /* Allocate the stream */
+    wStream* output_stream = Stream_New(NULL, streamBytes);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICELIST_ANNOUNCE);
+
+    /* Get the stream for each of the devices. */
+    Stream_Write_UINT32(output_stream, rdpdr->devices_registered);
+    for (int i=0; i<rdpdr->devices_registered; i++) {
+        
+        Stream_Write(output_stream,
+                Stream_Buffer(rdpdr->devices[i].device_announce),
+                rdpdr->devices[i].device_announce_len);
+
+        guac_client_log(svc->client, GUAC_LOG_DEBUG, "Registered device %i (%s)",
+                rdpdr->devices[i].device_id, rdpdr->devices[i].device_name);
+        
+    }
+
+    guac_rdp_common_svc_write(svc, output_stream);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "All supported devices sent.");
+
+}
+
+void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+
+    unsigned int major, minor, client_id;
+
+    Stream_Read_UINT16(input_stream, major);
+    Stream_Read_UINT16(input_stream, minor);
+    Stream_Read_UINT32(input_stream, client_id);
+
+    /* Must choose own client ID if minor not >= 12 */
+    if (minor < 12)
+        client_id = random() & 0xFFFF;
+
+    guac_client_log(svc->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id);
+
+    /* Respond to announce */
+    guac_rdpdr_send_client_announce_reply(svc, major, minor, client_id);
+
+    /* Name request */
+    guac_rdpdr_send_client_name_request(svc, ((guac_rdp_client*) svc->client->data)->settings->client_name);
+
+}
+
+void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Client ID confirmed");
+}
+
+void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+
+    guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
+
+    unsigned int device_id, ntstatus;
+    int severity, c, n, facility, code;
 
 Review comment:
   What are `c` and `n`? Are those standard field names in FreeRDP?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555108
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
+ * name as the pipe stream. Received pipe streams are associated with the
+ * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino
+ * handler (guac_rdp_pipe_svc_blob_handler).
 
 Review comment:
   @jmuehlner beat you to it - this should already be fixed via commit feb376e. ;)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573465109
 
 
   OK - I think I've fixed the issue, which seems to be the only build issue resulting from changes to the FreeRDP after CentOS produced their package. I encountered a different issue after that was addressed due to the way that I was checking platform endianness, but I think I've fixed that, too.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-570826139
 
 
   Forgot to mention: I've also leveraged FreeRDP 2.x's support for overriding the default logging to send all FreeRDP log messages to the debug level of Guacamole's logger, so there shouldn't be as much log spam, nor any need to run guacd in foreground to see debug messages from FreeRDP.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-572863303
 
 
   I’m working through a review, as well - will try to buckle down and get it
   submitted tomorrow...
   
   On Thu, Jan 9, 2020 at 17:19 Mike Jumper <no...@github.com> wrote:
   
   > OK, I believe I've addressed everything with the exception of the n and c
   > naming, which I've commented on above. Let me know if you still think that
   > needs fixing and I'll look around for possibilities.
   >
   > —
   > You are receiving this because you commented.
   >
   >
   > Reply to this email directly, view it on GitHub
   > <https://github.com/apache/guacamole-server/pull/243?email_source=notifications&email_token=ABD45UG4XCPGMSLLOX7AKFLQ46PF3A5CNFSM4KCYIBA2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIR7TNI#issuecomment-572783029>,
   > or unsubscribe
   > <https://github.com/notifications/unsubscribe-auth/ABD45UGRLIQMNHYZ4QCC3MLQ46PF3ANCNFSM4KCYIBAQ>
   > .
   >
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-572863883
 
 
   Thanks, guys.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-571334143
 
 
   OK - the only remaining things I managed to find are:
   
   * Pointer `SetNull` and `SetDefault` implementations were stubs. Don't know how long this has been the case, but since it's essentially one line to add these, I have done so.
   * I had manually set the `ReceiveChannelData` handler to `freerdp_channels_data()`, but this is the default and need not be manually set. I've now removed that line.
   * There was a potential segfault if the connection ends early enough that any of the various SVCs didn't actually connect before their termination handlers were invoked, as a couple of those implementations did not check whether they had actually allocated their internal structures before attempting to free them. Fixed this with commit 67c5bdf.
   * Security negotiation would fail apparently due to having the "extended mode" of NLA enabled by default. Checking the FreeRDP source, they do not do this, and disabling "extended mode" by default fixes things.
   * The new default of "any" for security mode is more convenient given that NLA is the new normal for RDP, but this breaks past usage where users may be relying on the lack of username/password to result in a traditional Windows login prompt. I've modified "any" such that it will not attempt to negotiate NLA if doing so would be impossible due to the lack of username/password (at least until parameter prompting is in there).

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364951731
 
 

 ##########
 File path: src/protocols/rdp/plugins/channels.c
 ##########
 @@ -0,0 +1,129 @@
+/*
+ * 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 "plugins/channels.h"
+
+#include <freerdp/channels/channels.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/addin.h>
+#include <winpr/wtypes.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+int guac_rdp_wrapped_entry_ex_count = 0;
+
+int guac_rdp_wrapped_entry_count = 0;
+
+PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS)
+        return entry_ex;
+
+    /* Generate wrapped version of provided entry point */
+    PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
+    guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
+    guac_rdp_wrapped_entry_ex_count++;
+
+    return wrapper;
+
+}
+
+PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS)
 
 Review comment:
   > No warning or anything if wrapping fails?
   
   To log a message using the normal logging subsystem exposed by libguac, we would need access to the `guac_client`, however the `guac_client` is unavailable at this level as the calling function (`guac_freerdp_channels_load_plugin()`) was meant to be a drop-in replacement for part of the FreeRDP API (`freerdp_channels_load_plugin()`) and none of the parameters received by these functions have a path for reaching the `guac_client`.
   
   We could work around this by:
   
   * *Not* having this function be a true drop-in replacement. There is arguably little utility to having the function be a drop-in replacement now that the code has been migrated. Passing different arguments (perhaps `rdpContext`) would allow access to the associated `guac_client`.
   * Using FreeRDP's logging subsystem (part of libwinpr). That subsystem is rerouted early on in the connection process such that all messages logged from FreeRDP actually get logged to the `guac_client` at the debug level.
   
   > What are the consequences if this happens?
   
   Generally, it shouldn't - there is an upper bound on the maximum number of static channels that can be loaded. This upper bound is set by RDP itself and by FreeRDP. The `GUAC_RDP_MAX_CHANNELS` constant is set to the maximum number of static channels that FreeRDP can load, and while we can't verify this at runtime, there is a compile-time check that will fail the build if the constant is set incorrectly:
   
   https://github.com/apache/guacamole-server/blob/55959b54564cd7ce8800225ed8d3741345eb90a2/src/protocols/rdp/plugins/channels.h#L39-L42
   
   The plugin would fail to load due to there not being a slot available to hold the plugin.
   
   Setting that aside, though, let's assume something strange is going on and the plugin does successfully load after the limit is reached:
   
   The first attempt to load a plugin X would succeed, as prior instances of X had their entry points wrapped and FreeRDP sees this load attempt as unique. After this point, further attempts to load copies of X would fail due to its entry point already being present, and FreeRDP would refuse to load the plugin.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman merged pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman merged pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243
 
 
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364073127
 
 

 ##########
 File path: src/protocols/rdp/channels/rail.c
 ##########
 @@ -0,0 +1,197 @@
+/*
+ * 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 "channels/rail.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+#include "settings.h"
+
+#include <freerdp/client/rail.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/rail.h>
+#include <guacamole/client.h>
+#include <winpr/wtypes.h>
+#include <winpr/wtsapi.h>
+
+#include <stddef.h>
+#include <string.h>
+
+/**
+ * Completes initialization of the RemoteApp session, sending client system
+ * parameters and executing the desired RemoteApp command using the Client
+ * System Parameters Update PDU and Client Execute PDU respectively. These PDUs
+ * MUST be sent for the desired RemoteApp to run, and MUST NOT be sent until
+ * after a Handshake or HandshakeEx PDU has been received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/60344497-883f-4711-8b9a-828d1c580195 (System Parameters Update PDU)
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/98a6e3c3-c2a9-42cc-ad91-0d9a6c211138 (Client Execute PDU)
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDUs were sent successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
+
+    guac_client* client = (guac_client*) rail->custom;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    RAIL_SYSPARAM_ORDER sysparam = {
+        .workArea = {
+            .left   = 0,
+            .top    = 0,
+            .right  = rdp_client->settings->width,
+            .bottom = rdp_client->settings->height
+        },
+        .dragFullWindows = FALSE
+    };
+
+    /* Send client system parameters */
+    UINT status = rail->ClientSystemParam(rail, &sysparam);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    RAIL_EXEC_ORDER exec = {
+        .RemoteApplicationProgram = rdp_client->settings->remote_app,
+        .RemoteApplicationWorkingDir = rdp_client->settings->remote_app_dir,
+        .RemoteApplicationArguments = rdp_client->settings->remote_app_args,
+    };
+
+    /* Execute desired RemoteApp command */
+    return rail->ClientExecute(rail, &exec);
+
+}
+
+/**
+ * Callback which is invoked when a Handshake PDU is received from the RDP
+ * server. No communication for RemoteApp may occur until the Handshake PDU
+ * (or, alternatively, the HandshakeEx PDU) is received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @param handshake
 
 Review comment:
   This isn't used for anything?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365608972
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
+ * Format List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format list.");
+
+    CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    /* Report successful processing of format list */
+    cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
+
+    /* Prefer Unicode (in this case, UTF-16) */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
+
+    /* Use Windows' CP-1252 if Unicode unavailable */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
+
+    /* Ignore any unsupported data */
+    guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
+            "clipboard data. Only Unicode and text clipboard formats are "
+            "currently supported.");
+
+    return CHANNEL_RC_OK;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Request PDUs. The Format Data Request PDU is sent by the RDP server when
+ * requesting that clipboard data be sent, in response to a received Format
+ * List PDU. The client is required to respond with a Format Data Response PDU
+ * containing the requested data.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_request
+ *     The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
+ *     Request PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data request.");
+
+    guac_iconv_write* writer;
+    const char* input = clipboard->clipboard->buffer;
+    char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    /* Map requested clipboard format to a guac_iconv writer */
+    switch (format_data_request->requestedFormatId) {
+
+        case CF_TEXT:
+            writer = GUAC_WRITE_CP1252;
+            break;
+
+        case CF_UNICODETEXT:
+            writer = GUAC_WRITE_UTF16;
+            break;
+
+        /* Warn if clipboard data cannot be sent as intended due to a violation
+         * of the CLIPRDR spec */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
+                    "clipboard data cannot be sent to the RDP server because "
+                    "the RDP server has requested a clipboard format which "
+                    "was not declared as available. This violates the "
+                    "specification for the CLIPRDR channel.");
+            free(output);
+            return CHANNEL_RC_OK;
+
+    }
+
+    /* Send received clipboard data to the RDP server in the format
+     * requested */
+    BYTE* start = (BYTE*) output;
+    guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
+               writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
+        .requestedFormatData = (BYTE*) start,
+        .dataLen = ((BYTE*) output) - start,
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data response.");
+
+    return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Response PDUs. The Format Data Response PDU is sent by the RDP server when
+ * fullfilling a request for clipboard data received via a Format Data Request
+ * PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_response
+ *     The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
+ *     Response PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data response.");
+
+    char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
+
+    guac_iconv_read* reader;
+    const char* input = (char*) format_data_response->requestedFormatData;
+    char* output = received_data;
+
+    /* Find correct source encoding */
+    switch (clipboard->requested_format) {
+
+        /* Non-Unicode (Windows CP-1252) */
+        case CF_TEXT:
+            reader = GUAC_READ_CP1252;
+            break;
+
+        /* Unicode (UTF-16) */
+        case CF_UNICODETEXT:
+            reader = GUAC_READ_UTF16;
+            break;
+
+        /* If the format ID stored within the guac_rdp_clipboard structure is actually
+         * not supported here, then something has been implemented incorrectly.
+         * Either incorrect values are (somehow) being stored, or support for
+         * the format indicated by that value is incomplete and must be added
+         * here. The values which may be stored within requested_format are
+         * completely within our control. */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested "
+                    "clipboard data in unsupported format (0x%X).",
+                    clipboard->requested_format);
+            return CHANNEL_RC_OK;
 
 Review comment:
   Okay, makes sense.  I'm good with it.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365610194
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,605 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities ... */
+    int status = guac_rdp_cliprdr_send_capabilities(cliprdr);
+    if (status != CHANNEL_RC_OK)
 
 Review comment:
   `if (!guac_rdp_cliprdr_send_capabilities(cliprdr))`
   
   ;-)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574319403
 
 
   Sounds good...I think it's go time...
   
   :shipit:

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363572357
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
+ * Format List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format list.");
+
+    CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    /* Report successful processing of format list */
+    cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
+
+    /* Prefer Unicode (in this case, UTF-16) */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
+
+    /* Use Windows' CP-1252 if Unicode unavailable */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
+
+    /* Ignore any unsupported data */
+    guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
+            "clipboard data. Only Unicode and text clipboard formats are "
+            "currently supported.");
+
+    return CHANNEL_RC_OK;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Request PDUs. The Format Data Request PDU is sent by the RDP server when
+ * requesting that clipboard data be sent, in response to a received Format
+ * List PDU. The client is required to respond with a Format Data Response PDU
+ * containing the requested data.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_request
+ *     The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
+ *     Request PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data request.");
+
+    guac_iconv_write* writer;
+    const char* input = clipboard->clipboard->buffer;
+    char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    /* Map requested clipboard format to a guac_iconv writer */
+    switch (format_data_request->requestedFormatId) {
+
+        case CF_TEXT:
+            writer = GUAC_WRITE_CP1252;
+            break;
+
+        case CF_UNICODETEXT:
+            writer = GUAC_WRITE_UTF16;
+            break;
+
+        /* Warn if clipboard data cannot be sent as intended due to a violation
+         * of the CLIPRDR spec */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
+                    "clipboard data cannot be sent to the RDP server because "
+                    "the RDP server has requested a clipboard format which "
+                    "was not declared as available. This violates the "
+                    "specification for the CLIPRDR channel.");
+            free(output);
+            return CHANNEL_RC_OK;
+
+    }
+
+    /* Send received clipboard data to the RDP server in the format
+     * requested */
+    BYTE* start = (BYTE*) output;
+    guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
+               writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
+        .requestedFormatData = (BYTE*) start,
+        .dataLen = ((BYTE*) output) - start,
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data response.");
+
+    return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Response PDUs. The Format Data Response PDU is sent by the RDP server when
+ * fullfilling a request for clipboard data received via a Format Data Request
+ * PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_response
+ *     The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
+ *     Response PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data response.");
+
+    char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
+
+    guac_iconv_read* reader;
+    const char* input = (char*) format_data_response->requestedFormatData;
+    char* output = received_data;
+
+    /* Find correct source encoding */
+    switch (clipboard->requested_format) {
+
+        /* Non-Unicode (Windows CP-1252) */
+        case CF_TEXT:
+            reader = GUAC_READ_CP1252;
+            break;
+
+        /* Unicode (UTF-16) */
+        case CF_UNICODETEXT:
+            reader = GUAC_READ_UTF16;
+            break;
+
+        /* If the format ID stored within the guac_rdp_clipboard structure is actually
+         * not supported here, then something has been implemented incorrectly.
+         * Either incorrect values are (somehow) being stored, or support for
+         * the format indicated by that value is incomplete and must be added
+         * here. The values which may be stored within requested_format are
+         * completely within our control. */
 
 Review comment:
   If this is the case, is silently ignoring this by returning `CHANNEL_RC_OK` still desirable?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364076478
 
 

 ##########
 File path: src/protocols/rdp/doc/svc-example/README.md
 ##########
 @@ -0,0 +1,169 @@
+Static Virtual Channel example
+==============================
+
+Guacamole supports use of static virtual channels (SVCs) for transmission of
+arbitrary data between the JavaScript client and applications running within
+RDP sessions. This example is intended to demonstrate how bidirectional
+communication between the Guacamole client and applications within the RDP
+server can be accomplished.
+
+Arbitrary SVCs are enabled on RDP connections by specfying their names as the
+value of [the `static-channels`
+parameter](http://guacamole.apache.org/doc/gug/configuring-guacamole.html#rdp-device-redirection).
+Each name is limited to a maximum of 7 characters. Multiple names may be listed
+by separating those names with commas.
+
+This example consists of a single file, [`svc-example.c`](svc-example.c), which
+leverages the terminal server API exposed by Windows to:
+
+ 1. Open a channel called "EXAMPLE"
+ 2. Wait for blocks of data to be received
+ 3. Send each received block of data back, unmodified.
+
+Building the example
+--------------------
+
+A `Makefile` is provided which uses MinGW to build the `svc-example.exe`
+executable, and thus can be used to produce the example application on Linux.
+The `Makefile` is not platform-independent, and changes may be needed for
+`make` to succeed with your installation of MinGW. If not using MinGW, the C
+source itself is standard and should compile with other tools.
+
+To build on Linux using `make`:
+
+```console
+$ make
+i686-w64-mingw32-gcc svc-example.c -lwtsapi32 \
+	-D_WIN32_WINNT=0x600   \
+	-DWINVER=0x600 -o svc-example.exe
+$
+```
+
+You can then copy the resulting `svc-example.exe` to the remote desktop that
+you wish to test and run it within a command prompt within the remote desktop
+session.
+
+Using the example (and SVCs in general)
+---------------------------------------
+
+On the remote desktop server side (within the Windows application leveraging
+SVCs to communicate with Guacamole), the following functions are used
+specifically for reading/writing to the SVC:
+
+ * [`WTSVirtualChannelOpenEx()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelopenex)
+ * [`WTSVirtualChannelRead()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelread)
+ * [`WTSVirtualChannelWrite()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelwrite)
+ * [`WTSVirtualChannelClose()`](https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelclose)
+
+On the Guacamole side, bidirectional communication is established using:
+
+ * The `static-channels` connection parameter (in the case of the example, this should be set to `EXAMPLE`).
+ * An [`onpipe`](http://guacamole.apache.org/doc/guacamole-common-js/Guacamole.Client.html#event:onpipe)
+   handler which handles inbound (server-to-client) pipe streams named identically
+   to the SVC. The inbound pipe stream will be received upon establishing the RDP
+   connection and is used to transmit any data sent along the SVC **from** within
 
 Review comment:
   Why is just the word `from` emphasized here?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364973223
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available.
+ */
+static void __generate_upload_path(const char* filename, char* path) {
+
+    int i;
+
+    /* Add initial backslash */
+    *(path++) = '\\';
+
+    for (i=1; i<GUAC_RDP_FS_MAX_PATH; i++) {
+
+        /* Get current, stop at end */
+        char c = *(filename++);
+        if (c == '\0')
+            break;
+
+        /* Replace special characters with underscores */
+        if (c == '/' || c == '\\')
+            c = '_';
+
+        *(path++) = c;
+
+    }
+
+    /* Terminate path */
+    *path = '\0';
+
+}
+
+int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* filename) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    int file_id;
+    char file_path[GUAC_RDP_FS_MAX_PATH];
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Translate name */
+    __generate_upload_path(filename, file_path);
+
+    /* Open file */
+    file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0,
+            FILE_OVERWRITE_IF, 0);
+    if (file_id < 0) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)",
+                GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Init upload status */
+    guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status));
+    upload_status->offset = 0;
+    upload_status->file_id = file_id;
+    stream->data = upload_status;
+    stream->blob_handler = guac_rdp_upload_blob_handler;
+    stream->end_handler = guac_rdp_upload_end_handler;
+
+    guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)",
+            GUAC_PROTOCOL_STATUS_SUCCESS);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+
+int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream,
+        void* data, int length) {
+
+    int bytes_written;
+    guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem 0*/
 
 Review comment:
   Fixed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364972380
 
 

 ##########
 File path: src/protocols/rdp/download.c
 ##########
 @@ -0,0 +1,240 @@
+/*
+ * 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 "common/json.h"
+#include "download.h"
+#include "fs.h"
+#include "ls.h"
+#include "rdp.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/string.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+#include <winpr/shell.h>
+
+#include <stdlib.h>
+
+int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream,
+        char* message, guac_protocol_status status) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_download_status* download_status = (guac_rdp_download_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* If successful, read data */
+    if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
+
+        /* Attempt read into buffer */
+        char buffer[4096];
+        int bytes_read = guac_rdp_fs_read(fs,
+                download_status->file_id,
+                download_status->offset, buffer, sizeof(buffer));
+
+        /* If bytes read, send as blob */
+        if (bytes_read > 0) {
+            download_status->offset += bytes_read;
+            guac_protocol_send_blob(user->socket, stream,
+                    buffer, bytes_read);
+        }
+
+        /* If EOF, send end */
+        else if (bytes_read == 0) {
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        /* Otherwise, fail stream */
+        else {
+            guac_user_log(user, GUAC_LOG_ERROR,
+                    "Error reading file for download");
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        guac_socket_flush(user->socket);
+
+    }
+
+    /* Otherwise, return stream to user */
+    else
+        guac_user_free_stream(user, stream);
+
+    return 0;
+
+}
+
+int guac_rdp_download_get_handler(guac_user* user, guac_object* object,
+        char* name) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    /* Get filesystem, ignore request if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL)
+        return 0;
+
+    /* Attempt to open file for reading */
+    int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0);
+    if (file_id < 0) {
+        guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
+                name);
+        return 0;
+    }
+
+    /* Get opened file */
+    guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
+    if (file == NULL) {
+        guac_client_log(fs->client, GUAC_LOG_DEBUG,
+                "%s: Successful open produced bad file_id: %i",
+                __func__, file_id);
+        return 0;
+    }
+
+    /* If directory, send contents of directory */
+    if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) {
+
+        /* Create stream data */
+        guac_rdp_ls_status* ls_status = malloc(sizeof(guac_rdp_ls_status));
+        ls_status->fs = fs;
+        ls_status->file_id = file_id;
+        guac_strlcpy(ls_status->directory_name, name,
+                sizeof(ls_status->directory_name));
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->ack_handler = guac_rdp_ls_ack_handler;
+        stream->data = ls_status;
+
+        /* Init JSON object state */
+        guac_common_json_begin_object(user, stream,
+                &ls_status->json_state);
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                GUAC_USER_STREAM_INDEX_MIMETYPE, name);
+
+    }
+
+    /* Otherwise, send file contents */
+    else {
+
+        /* Create stream data */
+        guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status));
+        download_status->file_id = file_id;
+        download_status->offset = 0;
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->data = download_status;
+        stream->ack_handler = guac_rdp_download_ack_handler;
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                "application/octet-stream", name);
+
+    }
+
+    guac_socket_flush(user->socket);
+    return 0;
+}
+
+void* guac_rdp_download_to_user(guac_user* user, void* data) {
+
+    /* Do not bother attempting the download if the user has left */
+    if (user == NULL)
+        return NULL;
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_fs* filesystem = rdp_client->filesystem;
+
+    /* Ignore download if filesystem has been unloaded */
+    if (filesystem == NULL)
+        return NULL;
+
+    /* Attempt to open requested file */
+    char* path = (char*) data;
+    int file_id = guac_rdp_fs_open(filesystem, path,
+            FILE_READ_DATA, 0, FILE_OPEN, 0);
+
+    /* If file opened successfully, start stream */
+    if (file_id >= 0) {
+
+        guac_rdp_download_status* download_status;
+        const char* basename;
+
+        int i;
 
 Review comment:
   OK - I've cleaned this up, moved the basename logic to its own function within `fs.h`, and added a unit test for said function.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363062567
 
 

 ##########
 File path: src/common/surface.c
 ##########
 @@ -260,58 +260,67 @@ static int __guac_common_surface_is_opaque(guac_common_surface* surface,
 
 /**
  * Returns whether the given rectangle should be combined into the existing
- * dirty rectangle, to be eventually flushed as a "png" instruction.
+ * dirty rectangle, to be eventually flushed as image data, or would be best
+ * kept independent of the current rectangle.
  *
- * @param surface The surface to be queried.
- * @param rect The update rectangle.
- * @param rect_only Non-zero if this update, by its nature, contains only
- *                  metainformation about the update's rectangle, zero if
- *                  the update also contains image data.
- * @return Non-zero if the update should be combined with any existing update,
- *         zero otherwise.
+ * @param surface
+ *     The surface being updated.
+ *
+ * @param rect
+ *     The bounding rectangle of the updating being made to the surface.
 
 Review comment:
   "of the updating being made" -> "of the update being made"

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364697728
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
+ * name as the pipe stream. Received pipe streams are associated with the
+ * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino
+ * handler (guac_rdp_pipe_svc_blob_handler).
 
 Review comment:
   *instruction

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365615714
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,605 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities ... */
+    int status = guac_rdp_cliprdr_send_capabilities(cliprdr);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    /* ... and supported format list */
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicates that clipboard data is available via a Format
+ * List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
 
 Review comment:
   Thx.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363565110
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
 
 Review comment:
   `guac_rdp_cliprdr_send_capabilities()` returns a value - are we ignoring it?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363565570
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
 
 Review comment:
   indicating -> indicates

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-572783029
 
 
   OK, I believe I've addressed everything with the exception of the `n` and `c` naming, which I've commented on above. Let me know if you still think that needs fixing and I'll look around for possibilities.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573481429
 
 
   Okay - I'm trying to finish up testing here tonight and might be able to get it merged tonight or tomorrow.  @jmuehlner Any other comments or objections prior to proceeding with the merge?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574428523
 
 
   Looks real solid. I just manually tried merging the previous `HEAD` of `master` onto my test merge resolution branch, resolved the conflicts manually, and the diff against current `master` showed no differences at all ... except for a new CLIPRDR-related log message.
   
   I think that log message should probably be removed, and I will open a PR to that effect in a moment.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573926508
 
 
   aHA! Manually setting `CPPFLAGS` within seems to allow tests to work, as it adds the needed `-I` flags globally:
   
   ```
       PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],
                         [CPPFLAGS="${RDP_CFLAGS} $CPPFLAGS"],
                         [AC_MSG_WARN([
   ```
   
   The downside is that it adds the flags globally. It shouldn't hurt the build, as part of the reason this is so cumbersome is that FreeRDP 2.x is double-namespaced, with headers being within `freerdp2/freerdp/`.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573913375
 
 
   > Lovely...so we're tied to a current RC of FreeRDP 2. That feels safe.
   
   Well, 2.0.0-rc4 and master, but yeah - I know what you mean.
   
   I'm not necessarily against trying to be compatible with rc0 through rc3, but I'm not sure how we would distinguish them. It doesn't seem possible to write configure tests because of pkg-config, and the version numbers are identical, even within FreeRDP's version.h.
   
   ### 2.0.0-rc0
   
   ```c
   #define FREERDP_VERSION_MAJOR 2
   #define FREERDP_VERSION_MINOR 0
   #define FREERDP_VERSION_REVISION 0
   #define FREERDP_VERSION_SUFFIX "dev5"
   #define FREERDP_API_VERSION "2"
   #define FREERDP_VERSION "2.0.0"
   #define FREERDP_VERSION_FULL "2.0.0-dev5"
   #define GIT_REVISION "326a44895"
   ```
   
   ### 2.0.0-rc4
   
   ```c
   #define FREERDP_VERSION_MAJOR 2
   #define FREERDP_VERSION_MINOR 0
   #define FREERDP_VERSION_REVISION 0
   #define FREERDP_VERSION_SUFFIX "dev5"
   #define FREERDP_API_VERSION "2"
   #define FREERDP_VERSION "2.0.0"
   #define FREERDP_VERSION_FULL "2.0.0-dev5"
   #define GIT_REVISION "326a44895"
   ```

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574330961
 
 
   Okay, merge to `staging/1.1.0` is done.  I have to step out for a little while, but will work through the merge to master here, shortly.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364084524
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available.
 
 Review comment:
   Typo: `hav`

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364972624
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr.h
 ##########
 @@ -0,0 +1,250 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_RDPDR_H
+#define GUAC_RDP_CHANNELS_RDPDR_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <winpr/stream.h>
+
+#include <stdint.h>
+
+/**
+ * The maximum number of bytes to allow for a device read.
+ */
+#define GUAC_RDP_MAX_READ_BUFFER 4194304
+
+/**
+ * Arbitrary device forwarded over the RDPDR channel.
+ */
+typedef struct guac_rdpdr_device guac_rdpdr_device;
+
+/**
+ * The contents of the header common to all RDPDR Device I/O Requests. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d
+ */
+typedef struct guac_rdpdr_iorequest {
+
+    /**
+     * The unique ID assigned to the device receiving this I/O request.
+     */
+    int device_id;
+
+    /**
+     * The unique ID which identifies the relevant file, as returned when the
+     * file was opened. This field may not be relevant to all requests.
+     */
+    int file_id;
+
+    /**
+     * The unique ID that should be used to refer to this I/O request in future
+     * responses.
+     */
+    int completion_id;
+
+    /**
+     * Integer ID which identifies the function being requested, such as
+     * IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write
+     * data to an open file).
+     */
+    int major_func;
+
+    /**
+     * Integer ID which identifies a variant of the function denoted by
+     * major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL.
+     */
+    int minor_func;
+
+} guac_rdpdr_iorequest;
+
+/**
+ * Handler for Device I/O Requests. RDPDR devices must provide an
+ * implementation of this function to be able to handle inbound I/O requests.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
+ *     the guac_rdpdr_iorequest structure, the deviceId field is stored within
+ *     device_id.
+ *
+ * @param iorequest
+ *     The contents of the common RDPDR Device I/O Request header shared by all
+ *     RDPDR devices.
+ *
+ * @param input_stream
+ *     The remaining data within the received PDU, following the common RDPDR
+ *     Device I/O Request header.
+ */
+typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
+        wStream* input_stream);
+
+/**
+ * Handler for cleaning up the dynamically-allocated portions of a device.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the device being freed.
+ */
+typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device);
+
+struct guac_rdpdr_device {
+
+    /**
+     * The ID assigned to this device by the RDPDR plugin.
+     */
+    int device_id;
+
+    /**
+     * Device name, used for logging and for passthrough to the
+     * server.
+     */
+    const char* device_name;
+
+    /**
+     * The type of RDPDR device that this represents.
+     */
+    uint32_t device_type;
+
+    /**
+     * The DOS name of the device.  Max 8 bytes, including terminator.
+     */
+    const char *dos_name;
+    
+    /**
+     * The stream that stores the RDPDR device announcement for this device.
+     */
+    wStream* device_announce;
+    
+    /**
+     * The length of the device_announce wStream.
+     */
+    int device_announce_len;
+
+    /**
+     * Handler which should be called for every I/O request received.
+     */
+    guac_rdpdr_device_iorequest_handler* iorequest_handler;
+
+    /**
+     * Handler which should be called when the device is being freed.
+     */
+    guac_rdpdr_device_free_handler* free_handler;
+
+    /**
+     * Arbitrary data, used internally by the handlers for this device.
+     */
+    void* data;
+
+};
+
+/**
+ * Structure representing the current state of the Guacamole RDPDR plugin for
+ * FreeRDP.
+ */
+typedef struct guac_rdpdr {
+
+    /**
+     * The number of devices registered within the devices array.
+     */
+    int devices_registered;
+
+    /**
+     * Array of registered devices.
+     */
+    guac_rdpdr_device devices[8];
+
+} guac_rdpdr;
+
+/**
+ * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
+ * used for virtually all responses. Depending on the specific I/O completion
+ * being sent, additional space may be reserved within the resulting stream for
+ * additional fields. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
+ *
+ * @param device
+ *     The device that completed the operation requested by a prior I/O
+ *     request.
+ *
+ * @param completion_id
+ *     The completion ID of the I/O request that requested the operation.
+ *
+ * @param status
+ *     An NTSTATUS code describing the success/failure of the operation that
+ *     was completed.
+ *
+ * @param size
+ *     The number of additional bytes to reserve at the end of the resulting
+ *     stream for additional fields to be appended.
+ *
+ * @return
+ *     A new wStream containing an I/O completion header, followed by the
+ *     requested additional free space.
+ */
+wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
+        int completion_id, int status, int size);
+
+/**
+ * Initializes device redirection support (file transfer, printing, etc.) for
+ * RDP and handling of the RDPDR channel.  If failures occur, messages noting
 
 Review comment:
   Should now be fixed - I did an overall search for double spaces occurring within comments and corrected all occurrences.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365610194
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,605 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities ... */
+    int status = guac_rdp_cliprdr_send_capabilities(cliprdr);
+    if (status != CHANNEL_RC_OK)
 
 Review comment:
   `if (!guac_rdp_cliprdr_send_capabilities(cliprdr))`
   
   ;-)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364071654
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
+ * name as the pipe stream. Received pipe streams are associated with the
+ * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino
 
 Review comment:
   Typo: "instructino"

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573941128
 
 
   OK, I'm having success with configure tests and am rewriting the previous typecast solutions for CLIPRDR, RAIL, etc. to instead use tests. This should be more future-proof in the sense that we'll get obvious build failures if API compatibility breaks, and it should allow us to support FreeRDP: Bionic Edition as well as 2.0.0-rc0 onward.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573460408
 
 
   Sigh ... sure enough: https://github.com/FreeRDP/FreeRDP/commit/65812bdbc00df2247f51147e78b25076d16ab1d8
   
   I'll add some checks...

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573454890
 
 
   Overall I'm fine with it.  Going to do one more quick(er) review pass and then do a test compile and run it and make sure everything looks okay.
   
   This is great work, Mike - so nice to have this one behind us and look at actually releasing 1.1.0 - and then another version pretty quickly after that, hopefully, and start our more frequent release process.  This is so cool!

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363062887
 
 

 ##########
 File path: src/protocols/rdp/bitmap.h
 ##########
 @@ -66,8 +61,11 @@ typedef struct guac_rdp_bitmap {
  *
  * @param bitmap
  *     The bitmap to cache.
+ *
+ * @return
+ *     TRUE if successful, FALSE otherwise.
 
 Review comment:
   This all seem to be switching from `void` to `BOOL`, but they also always seem to be returning `TRUE` - is there a rational for making them return something, when it's always expected to be successful?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364951731
 
 

 ##########
 File path: src/protocols/rdp/plugins/channels.c
 ##########
 @@ -0,0 +1,129 @@
+/*
+ * 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 "plugins/channels.h"
+
+#include <freerdp/channels/channels.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/addin.h>
+#include <winpr/wtypes.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+int guac_rdp_wrapped_entry_ex_count = 0;
+
+int guac_rdp_wrapped_entry_count = 0;
+
+PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS)
+        return entry_ex;
+
+    /* Generate wrapped version of provided entry point */
+    PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
+    guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
+    guac_rdp_wrapped_entry_ex_count++;
+
+    return wrapper;
+
+}
+
+PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS)
 
 Review comment:
   > No warning or anything if wrapping fails?
   
   To log a message using the normal logging subsystem exposed by libguac, we would need access to the `guac_client`, however the `guac_client` is unavailable at this level as the calling function (`guac_freerdp_channels_load_plugin()`) was meant to be a drop-in replacement for part of the FreeRDP API (`freerdp_channels_load_plugin()`) and none of the parameters received by these functions have a path for reaching the `guac_client`.
   
   We could work around this by:
   
   * *Not* having this function be a true drop-in replacement. There is arguably little utility to having the function be a drop-in replacement now that the code has been migrated. Passing different arguments (perhaps `rdpContext`) would allow access to the associated `guac_client`.
   * Using FreeRDP's logging subsystem (part of libwinpr). That subsystem is rerouted early on in the connection process such that all messages logged from FreeRDP actually get logged to the `guac_client` at the debug level.
   
   > What are the consequences if this happens?
   
   Generally, it shouldn't - there is an upper bound on the maximum number of static channels that can be loaded. This upper bound is set by RDP itself and by FreeRDP, and the `GUAC_RDP_MAX_CHANNELS` constant is set to a value that is intended to be well above this limit. While we can't verify this at runtime, there is a compile-time check that will fail the build if the constant is set incorrectly:
   
   https://github.com/apache/guacamole-server/blob/55959b54564cd7ce8800225ed8d3741345eb90a2/src/protocols/rdp/plugins/channels.h#L39-L42
   
   The plugin would fail to load due to there not being a slot available to hold the plugin.
   
   Setting that aside, though, let's assume something strange is going on and the plugin does successfully load after the limit is reached:
   
   The first attempt to load a plugin X would succeed, as prior instances of X had their entry points wrapped and FreeRDP sees this load attempt as unique. After this point, further attempts to load copies of X would fail due to its entry point already being present, and FreeRDP would refuse to load the plugin.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573457708
 
 
   FWIW - I just applied this change to the current `staging/1.1.0` branch and I get some compile failures.  Going to clean up and try, again, but not sure if it's mine or something missing from the commits here:
   ```
   channels/cliprdr.c: In function 'guac_rdp_cliprdr_channel_connected':
   channels/cliprdr.c:477:27: error: assignment from incompatible pointer type [-Werror]
        cliprdr->MonitorReady = guac_rdp_cliprdr_monitor_ready;
                              ^
   channels/cliprdr.c:478:31: error: assignment from incompatible pointer type [-Werror]
        cliprdr->ServerFormatList = guac_rdp_cliprdr_format_list;
                                  ^
   channels/cliprdr.c:479:38: error: assignment from incompatible pointer type [-Werror]
        cliprdr->ServerFormatDataRequest = guac_rdp_cliprdr_format_data_request;
                                         ^
   channels/cliprdr.c:480:39: error: assignment from incompatible pointer type [-Werror]
        cliprdr->ServerFormatDataResponse = guac_rdp_cliprdr_format_data_response;
                                          ^
   cc1: all warnings being treated as errors
   ```

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365488374
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
+ * Format List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format list.");
+
+    CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    /* Report successful processing of format list */
+    cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
+
+    /* Prefer Unicode (in this case, UTF-16) */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
+
+    /* Use Windows' CP-1252 if Unicode unavailable */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
+
+    /* Ignore any unsupported data */
+    guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
+            "clipboard data. Only Unicode and text clipboard formats are "
+            "currently supported.");
+
+    return CHANNEL_RC_OK;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Request PDUs. The Format Data Request PDU is sent by the RDP server when
+ * requesting that clipboard data be sent, in response to a received Format
+ * List PDU. The client is required to respond with a Format Data Response PDU
+ * containing the requested data.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_request
+ *     The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
+ *     Request PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data request.");
+
+    guac_iconv_write* writer;
+    const char* input = clipboard->clipboard->buffer;
+    char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    /* Map requested clipboard format to a guac_iconv writer */
+    switch (format_data_request->requestedFormatId) {
+
+        case CF_TEXT:
+            writer = GUAC_WRITE_CP1252;
+            break;
+
+        case CF_UNICODETEXT:
+            writer = GUAC_WRITE_UTF16;
+            break;
+
+        /* Warn if clipboard data cannot be sent as intended due to a violation
+         * of the CLIPRDR spec */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
+                    "clipboard data cannot be sent to the RDP server because "
+                    "the RDP server has requested a clipboard format which "
+                    "was not declared as available. This violates the "
+                    "specification for the CLIPRDR channel.");
+            free(output);
+            return CHANNEL_RC_OK;
+
+    }
+
+    /* Send received clipboard data to the RDP server in the format
+     * requested */
+    BYTE* start = (BYTE*) output;
+    guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
+               writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
+        .requestedFormatData = (BYTE*) start,
+        .dataLen = ((BYTE*) output) - start,
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data response.");
+
+    return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Response PDUs. The Format Data Response PDU is sent by the RDP server when
+ * fullfilling a request for clipboard data received via a Format Data Request
+ * PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_response
+ *     The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
+ *     Response PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data response.");
+
+    char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
+
+    guac_iconv_read* reader;
+    const char* input = (char*) format_data_response->requestedFormatData;
+    char* output = received_data;
+
+    /* Find correct source encoding */
+    switch (clipboard->requested_format) {
+
+        /* Non-Unicode (Windows CP-1252) */
+        case CF_TEXT:
+            reader = GUAC_READ_CP1252;
+            break;
+
+        /* Unicode (UTF-16) */
+        case CF_UNICODETEXT:
+            reader = GUAC_READ_UTF16;
+            break;
+
+        /* If the format ID stored within the guac_rdp_clipboard structure is actually
+         * not supported here, then something has been implemented incorrectly.
+         * Either incorrect values are (somehow) being stored, or support for
+         * the format indicated by that value is incomplete and must be added
+         * here. The values which may be stored within requested_format are
+         * completely within our control. */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested "
+                    "clipboard data in unsupported format (0x%X).",
+                    clipboard->requested_format);
+            return CHANNEL_RC_OK;
 
 Review comment:
   I assume it is intentional to return OK even though this isn't ok?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364534747
 
 

 ##########
 File path: src/protocols/rdp/channels/rail.c
 ##########
 @@ -0,0 +1,197 @@
+/*
+ * 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 "channels/rail.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+#include "settings.h"
+
+#include <freerdp/client/rail.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/rail.h>
+#include <guacamole/client.h>
+#include <winpr/wtypes.h>
+#include <winpr/wtsapi.h>
+
+#include <stddef.h>
+#include <string.h>
+
+/**
+ * Completes initialization of the RemoteApp session, sending client system
+ * parameters and executing the desired RemoteApp command using the Client
+ * System Parameters Update PDU and Client Execute PDU respectively. These PDUs
+ * MUST be sent for the desired RemoteApp to run, and MUST NOT be sent until
+ * after a Handshake or HandshakeEx PDU has been received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/60344497-883f-4711-8b9a-828d1c580195 (System Parameters Update PDU)
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/98a6e3c3-c2a9-42cc-ad91-0d9a6c211138 (Client Execute PDU)
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDUs were sent successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
+
+    guac_client* client = (guac_client*) rail->custom;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    RAIL_SYSPARAM_ORDER sysparam = {
+        .workArea = {
+            .left   = 0,
+            .top    = 0,
+            .right  = rdp_client->settings->width,
+            .bottom = rdp_client->settings->height
+        },
+        .dragFullWindows = FALSE
+    };
+
+    /* Send client system parameters */
+    UINT status = rail->ClientSystemParam(rail, &sysparam);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    RAIL_EXEC_ORDER exec = {
+        .RemoteApplicationProgram = rdp_client->settings->remote_app,
+        .RemoteApplicationWorkingDir = rdp_client->settings->remote_app_dir,
+        .RemoteApplicationArguments = rdp_client->settings->remote_app_args,
+    };
+
+    /* Execute desired RemoteApp command */
+    return rail->ClientExecute(rail, &exec);
+
+}
+
+/**
+ * Callback which is invoked when a Handshake PDU is received from the RDP
+ * server. No communication for RemoteApp may occur until the Handshake PDU
+ * (or, alternatively, the HandshakeEx PDU) is received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @param handshake
 
 Review comment:
   Huh, ok.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365481790
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h
 ##########
 @@ -17,58 +17,76 @@
  * under the License.
  */
 
-
-#ifndef __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
-#define __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
+#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
+#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
 
 /**
  * Handlers for directory queries received over the RDPDR channel via the
  * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor
  * function.
  *
- * @file rdpdr_fs_messages_dir_info.h
+ * @file rdpdr-fs-messages-dir-info.h
  */
 
-#include "config.h"
-
-#include "rdpdr_service.h"
+#include "channels/common-svc.h"
+#include "channels/rdpdr/rdpdr.h"
 
-#ifdef ENABLE_WINPR
 #include <winpr/stream.h>
-#else
-#include "compat/winpr-stream.h"
-#endif
+
+/**
+ * Handler for Device I/O Requests which query information about the files
+ * within a directory.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
+ *     the guac_rdpdr_iorequest structure, the deviceId field is stored within
+ *     device_id.
+ *
+ * @param iorequest
+ *     The contents of the common RDPDR Device I/O Request header shared by all
+ *     RDPDR devices.
+ *
+ * @param entry_name
+ *     The filename of the file being queried.
+ *
+ * @param entry_file_id
+ *     The ID of the file being queried.
+ */
+typedef void guac_rdpdr_directory_query_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
+        const char* entry_name, int entry_file_id);
 
 /**
  * Processes a query request for FileDirectoryInformation. From the
  * documentation this is "defined as the file's name, time stamp, and size, or its
  * attributes."
  */
-void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
-        const char* entry_name, int file_id, int completion_id);
+guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_directory_info;
 
 /**
  * Processes a query request for FileFullDirectoryInformation. From the
  * documentation, this is "defined as all the basic information, plus extended
  * attribute size."
  */
-void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
-        const char* entry_name, int file_id, int completion_id);
+guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_full_directory_info;
 
 /**
  * Processes a query request for FileBothDirectoryInformation. From the
  * documentation, this absurdly-named request is "basic information plus
 
 Review comment:
   Never noticed this comment before, but I'm glad it isn't being changed. :-D

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365510922
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must have at least GUAC_RDP_FS_MAX_PATH bytes available.
+ */
+static void __generate_upload_path(const char* filename, char* path) {
+
+    int i;
+
+    /* Add initial backslash */
+    *(path++) = '\\';
+
+    for (i=1; i<GUAC_RDP_FS_MAX_PATH; i++) {
+
+        /* Get current, stop at end */
+        char c = *(filename++);
+        if (c == '\0')
+            break;
+
+        /* Replace special characters with underscores */
+        if (c == '/' || c == '\\')
+            c = '_';
+
+        *(path++) = c;
+
+    }
+
+    /* Terminate path */
+    *path = '\0';
+
+}
+
+int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* filename) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    int file_id;
+    char file_path[GUAC_RDP_FS_MAX_PATH];
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
 
 Review comment:
   Are we really returning an error if we're returning 0, which also seems to be the success code?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365608878
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
+ * name as the pipe stream. Received pipe streams are associated with the
+ * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino
+ * handler (guac_rdp_pipe_svc_blob_handler).
 
 Review comment:
   Sorry about that - I even reloaded the review page a couple of times thinking that I'd see those items get updated.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364082023
 
 

 ##########
 File path: src/protocols/rdp/plugins/channels.c
 ##########
 @@ -0,0 +1,129 @@
+/*
+ * 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 "plugins/channels.h"
+
+#include <freerdp/channels/channels.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/addin.h>
+#include <winpr/wtypes.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+int guac_rdp_wrapped_entry_ex_count = 0;
+
+int guac_rdp_wrapped_entry_count = 0;
+
+PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS)
+        return entry_ex;
+
+    /* Generate wrapped version of provided entry point */
+    PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
+    guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
+    guac_rdp_wrapped_entry_ex_count++;
+
+    return wrapper;
+
+}
+
+PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS)
 
 Review comment:
   No warning or anything if wrapping fails? What are the consequences if this happens?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364077670
 
 

 ##########
 File path: src/protocols/rdp/download.c
 ##########
 @@ -0,0 +1,240 @@
+/*
+ * 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 "common/json.h"
+#include "download.h"
+#include "fs.h"
+#include "ls.h"
+#include "rdp.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/string.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+#include <winpr/shell.h>
+
+#include <stdlib.h>
+
+int guac_rdp_download_ack_handler(guac_user* user, guac_stream* stream,
+        char* message, guac_protocol_status status) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_download_status* download_status = (guac_rdp_download_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* If successful, read data */
+    if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
+
+        /* Attempt read into buffer */
+        char buffer[4096];
+        int bytes_read = guac_rdp_fs_read(fs,
+                download_status->file_id,
+                download_status->offset, buffer, sizeof(buffer));
+
+        /* If bytes read, send as blob */
+        if (bytes_read > 0) {
+            download_status->offset += bytes_read;
+            guac_protocol_send_blob(user->socket, stream,
+                    buffer, bytes_read);
+        }
+
+        /* If EOF, send end */
+        else if (bytes_read == 0) {
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        /* Otherwise, fail stream */
+        else {
+            guac_user_log(user, GUAC_LOG_ERROR,
+                    "Error reading file for download");
+            guac_protocol_send_end(user->socket, stream);
+            guac_user_free_stream(user, stream);
+            free(download_status);
+        }
+
+        guac_socket_flush(user->socket);
+
+    }
+
+    /* Otherwise, return stream to user */
+    else
+        guac_user_free_stream(user, stream);
+
+    return 0;
+
+}
+
+int guac_rdp_download_get_handler(guac_user* user, guac_object* object,
+        char* name) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    /* Get filesystem, ignore request if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL)
+        return 0;
+
+    /* Attempt to open file for reading */
+    int file_id = guac_rdp_fs_open(fs, name, GENERIC_READ, 0, FILE_OPEN, 0);
+    if (file_id < 0) {
+        guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
+                name);
+        return 0;
+    }
+
+    /* Get opened file */
+    guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
+    if (file == NULL) {
+        guac_client_log(fs->client, GUAC_LOG_DEBUG,
+                "%s: Successful open produced bad file_id: %i",
+                __func__, file_id);
+        return 0;
+    }
+
+    /* If directory, send contents of directory */
+    if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) {
+
+        /* Create stream data */
+        guac_rdp_ls_status* ls_status = malloc(sizeof(guac_rdp_ls_status));
+        ls_status->fs = fs;
+        ls_status->file_id = file_id;
+        guac_strlcpy(ls_status->directory_name, name,
+                sizeof(ls_status->directory_name));
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->ack_handler = guac_rdp_ls_ack_handler;
+        stream->data = ls_status;
+
+        /* Init JSON object state */
+        guac_common_json_begin_object(user, stream,
+                &ls_status->json_state);
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                GUAC_USER_STREAM_INDEX_MIMETYPE, name);
+
+    }
+
+    /* Otherwise, send file contents */
+    else {
+
+        /* Create stream data */
+        guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status));
+        download_status->file_id = file_id;
+        download_status->offset = 0;
+
+        /* Allocate stream for body */
+        guac_stream* stream = guac_user_alloc_stream(user);
+        stream->data = download_status;
+        stream->ack_handler = guac_rdp_download_ack_handler;
+
+        /* Associate new stream with get request */
+        guac_protocol_send_body(user->socket, object, stream,
+                "application/octet-stream", name);
+
+    }
+
+    guac_socket_flush(user->socket);
+    return 0;
+}
+
+void* guac_rdp_download_to_user(guac_user* user, void* data) {
+
+    /* Do not bother attempting the download if the user has left */
+    if (user == NULL)
+        return NULL;
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_rdp_fs* filesystem = rdp_client->filesystem;
+
+    /* Ignore download if filesystem has been unloaded */
+    if (filesystem == NULL)
+        return NULL;
+
+    /* Attempt to open requested file */
+    char* path = (char*) data;
+    int file_id = guac_rdp_fs_open(filesystem, path,
+            FILE_READ_DATA, 0, FILE_OPEN, 0);
+
+    /* If file opened successfully, start stream */
+    if (file_id >= 0) {
+
+        guac_rdp_download_status* download_status;
+        const char* basename;
+
+        int i;
 
 Review comment:
   Why not declare these variables down where they're actually used?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573920733
 
 
   I'll try nested autoconf. Perhaps adding a configure script which is dedicated to RDP and which is invoked by the top-level configure script will allow us to perform tests which inherit flags from pkg-config.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573516086
 
 
   I'm currently seeing the following after building on Debian:
   
       undefined symbol: guac_freerdp_dynamic_channel_collection_add	(/usr/local/lib/freerdp2/libguacai-client.so)
   
   Not sure why this isn't an issue under other distros, but I think I can resolve by moving the common parts of audio input to a different unit. The function referenced above is never invoked within the plugin and doesn't actually need to be present.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365554913
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   This should be fixed, I think. @jmuehlner found a few of these, as well, and I fixed them in commit 2139d40 after doing a search of all files beneath `src/protocols/rdp/` for any other occurrences of extra spaces in comments.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555050
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h
 ##########
 @@ -17,58 +17,76 @@
  * under the License.
  */
 
-
-#ifndef __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
-#define __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
+#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
+#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
 
 /**
  * Handlers for directory queries received over the RDPDR channel via the
  * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor
  * function.
  *
- * @file rdpdr_fs_messages_dir_info.h
+ * @file rdpdr-fs-messages-dir-info.h
  */
 
-#include "config.h"
-
-#include "rdpdr_service.h"
+#include "channels/common-svc.h"
+#include "channels/rdpdr/rdpdr.h"
 
-#ifdef ENABLE_WINPR
 #include <winpr/stream.h>
-#else
-#include "compat/winpr-stream.h"
-#endif
+
+/**
+ * Handler for Device I/O Requests which query information about the files
+ * within a directory.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
+ *     the guac_rdpdr_iorequest structure, the deviceId field is stored within
+ *     device_id.
+ *
+ * @param iorequest
+ *     The contents of the common RDPDR Device I/O Request header shared by all
+ *     RDPDR devices.
+ *
+ * @param entry_name
+ *     The filename of the file being queried.
+ *
+ * @param entry_file_id
+ *     The ID of the file being queried.
+ */
+typedef void guac_rdpdr_directory_query_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
+        const char* entry_name, int entry_file_id);
 
 /**
  * Processes a query request for FileDirectoryInformation. From the
  * documentation this is "defined as the file's name, time stamp, and size, or its
  * attributes."
  */
-void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
-        const char* entry_name, int file_id, int completion_id);
+guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_directory_info;
 
 /**
  * Processes a query request for FileFullDirectoryInformation. From the
  * documentation, this is "defined as all the basic information, plus extended
  * attribute size."
  */
-void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
-        const char* entry_name, int file_id, int completion_id);
+guac_rdpdr_directory_query_handler guac_rdpdr_fs_process_query_full_directory_info;
 
 /**
  * Processes a query request for FileBothDirectoryInformation. From the
  * documentation, this absurdly-named request is "basic information plus
 
 Review comment:
   Heh. :)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364084877
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available.
+ */
+static void __generate_upload_path(const char* filename, char* path) {
+
+    int i;
+
+    /* Add initial backslash */
+    *(path++) = '\\';
+
+    for (i=1; i<GUAC_RDP_FS_MAX_PATH; i++) {
+
+        /* Get current, stop at end */
+        char c = *(filename++);
+        if (c == '\0')
+            break;
+
+        /* Replace special characters with underscores */
+        if (c == '/' || c == '\\')
+            c = '_';
+
+        *(path++) = c;
+
+    }
+
+    /* Terminate path */
+    *path = '\0';
+
+}
+
+int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* filename) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    int file_id;
+    char file_path[GUAC_RDP_FS_MAX_PATH];
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Translate name */
+    __generate_upload_path(filename, file_path);
+
+    /* Open file */
+    file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0,
+            FILE_OVERWRITE_IF, 0);
+    if (file_id < 0) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)",
+                GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Init upload status */
+    guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status));
+    upload_status->offset = 0;
+    upload_status->file_id = file_id;
+    stream->data = upload_status;
+    stream->blob_handler = guac_rdp_upload_blob_handler;
+    stream->end_handler = guac_rdp_upload_end_handler;
+
+    guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)",
+            GUAC_PROTOCOL_STATUS_SUCCESS);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+
+int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream,
+        void* data, int length) {
+
+    int bytes_written;
+    guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem 0*/
 
 Review comment:
   Filesystem 0? What's that?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364074503
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr.h
 ##########
 @@ -0,0 +1,250 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_RDPDR_H
+#define GUAC_RDP_CHANNELS_RDPDR_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <winpr/stream.h>
+
+#include <stdint.h>
+
+/**
+ * The maximum number of bytes to allow for a device read.
+ */
+#define GUAC_RDP_MAX_READ_BUFFER 4194304
+
+/**
+ * Arbitrary device forwarded over the RDPDR channel.
+ */
+typedef struct guac_rdpdr_device guac_rdpdr_device;
+
+/**
+ * The contents of the header common to all RDPDR Device I/O Requests. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/a087ffa8-d0d5-4874-ac7b-0494f63e2d5d
+ */
+typedef struct guac_rdpdr_iorequest {
+
+    /**
+     * The unique ID assigned to the device receiving this I/O request.
+     */
+    int device_id;
+
+    /**
+     * The unique ID which identifies the relevant file, as returned when the
+     * file was opened. This field may not be relevant to all requests.
+     */
+    int file_id;
+
+    /**
+     * The unique ID that should be used to refer to this I/O request in future
+     * responses.
+     */
+    int completion_id;
+
+    /**
+     * Integer ID which identifies the function being requested, such as
+     * IRP_MJ_CREATE (open a file within a shared drive) or IRP_MJ_WRITE (write
+     * data to an open file).
+     */
+    int major_func;
+
+    /**
+     * Integer ID which identifies a variant of the function denoted by
+     * major_func. This value is only valid for IRP_MJ_DIRECTORY_CONTROL.
+     */
+    int minor_func;
+
+} guac_rdpdr_iorequest;
+
+/**
+ * Handler for Device I/O Requests. RDPDR devices must provide an
+ * implementation of this function to be able to handle inbound I/O requests.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
+ *     the guac_rdpdr_iorequest structure, the deviceId field is stored within
+ *     device_id.
+ *
+ * @param iorequest
+ *     The contents of the common RDPDR Device I/O Request header shared by all
+ *     RDPDR devices.
+ *
+ * @param input_stream
+ *     The remaining data within the received PDU, following the common RDPDR
+ *     Device I/O Request header.
+ */
+typedef void guac_rdpdr_device_iorequest_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device, guac_rdpdr_iorequest* iorequest,
+        wStream* input_stream);
+
+/**
+ * Handler for cleaning up the dynamically-allocated portions of a device.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the device being freed.
+ */
+typedef void guac_rdpdr_device_free_handler(guac_rdp_common_svc* svc,
+        guac_rdpdr_device* device);
+
+struct guac_rdpdr_device {
+
+    /**
+     * The ID assigned to this device by the RDPDR plugin.
+     */
+    int device_id;
+
+    /**
+     * Device name, used for logging and for passthrough to the
+     * server.
+     */
+    const char* device_name;
+
+    /**
+     * The type of RDPDR device that this represents.
+     */
+    uint32_t device_type;
+
+    /**
+     * The DOS name of the device.  Max 8 bytes, including terminator.
+     */
+    const char *dos_name;
+    
+    /**
+     * The stream that stores the RDPDR device announcement for this device.
+     */
+    wStream* device_announce;
+    
+    /**
+     * The length of the device_announce wStream.
+     */
+    int device_announce_len;
+
+    /**
+     * Handler which should be called for every I/O request received.
+     */
+    guac_rdpdr_device_iorequest_handler* iorequest_handler;
+
+    /**
+     * Handler which should be called when the device is being freed.
+     */
+    guac_rdpdr_device_free_handler* free_handler;
+
+    /**
+     * Arbitrary data, used internally by the handlers for this device.
+     */
+    void* data;
+
+};
+
+/**
+ * Structure representing the current state of the Guacamole RDPDR plugin for
+ * FreeRDP.
+ */
+typedef struct guac_rdpdr {
+
+    /**
+     * The number of devices registered within the devices array.
+     */
+    int devices_registered;
+
+    /**
+     * Array of registered devices.
+     */
+    guac_rdpdr_device devices[8];
+
+} guac_rdpdr;
+
+/**
+ * Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
+ * used for virtually all responses. Depending on the specific I/O completion
+ * being sent, additional space may be reserved within the resulting stream for
+ * additional fields. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
+ *
+ * @param device
+ *     The device that completed the operation requested by a prior I/O
+ *     request.
+ *
+ * @param completion_id
+ *     The completion ID of the I/O request that requested the operation.
+ *
+ * @param status
+ *     An NTSTATUS code describing the success/failure of the operation that
+ *     was completed.
+ *
+ * @param size
+ *     The number of additional bytes to reserve at the end of the resulting
+ *     stream for additional fields to be appended.
+ *
+ * @return
+ *     A new wStream containing an I/O completion header, followed by the
+ *     requested additional free space.
+ */
+wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
+        int completion_id, int status, int size);
+
+/**
+ * Initializes device redirection support (file transfer, printing, etc.) for
+ * RDP and handling of the RDPDR channel.  If failures occur, messages noting
 
 Review comment:
   Another double space here

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573911227
 
 
   > Rerunning builds for all FreeRDP tags, it looks like the current code will build only against 2.0.0-rc4. Earlier tags suffer from the issues noted above for Bionic.
   
   Lovely...so we're tied to a current RC of FreeRDP 2.  That feels safe.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364955658
 
 

 ##########
 File path: configure.ac
 ##########
 @@ -541,507 +540,17 @@ AC_ARG_WITH([rdp],
 
 if test "x$with_rdp" != "xno"
 then
-    have_winpr=yes
-    have_freerdp=yes
-    legacy_freerdp_extensions=no
-    rdpsettings_interface=unknown
-    rdpsettings_audiocapture=yes
-    rdpsettings_audioplayback=yes
-    rdpsettings_deviceredirection=yes
-    freerdp_interface=unknown
-    event_interface=unknown
-
-    # libfreerdp-core / libfreerdp
-    AC_CHECK_LIB([freerdp-core], [freerdp_new],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-core"],
-                 [AC_CHECK_LIB([freerdp], [freerdp_new],
-                               [RDP_LIBS="$RDP_LIBS -lfreerdp -lfreerdp-client"],
-                               [AC_MSG_WARN([
+    have_freerdp2=yes
+    PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],,
+                      [AC_MSG_WARN([
   --------------------------------------------
-   Unable to find libfreerdp-core / libfreerdp
+   Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2)
    RDP will be disabled.
   --------------------------------------------])
-                  have_freerdp=no])])
+                       have_freerdp2=no])
 fi
 
-
-# libfreerdp-cache
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-cache], [glyph_cache_register_callbacks],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-cache"])
-fi
-
-# libfreerdp-channels (1.0) / libfreerdp-client + libfreerdp-core (1.1)
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-client], [freerdp_channels_new],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-client"],
-                 [AC_CHECK_LIB([freerdp-channels], [freerdp_channels_new],
-                               [RDP_LIBS="$RDP_LIBS -lfreerdp-channels"
-                               legacy_freerdp_extensions=yes])],
-                 [-lfreerdp-core])
-fi
-
-# libfreerdp-utils
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-utils], [svc_plugin_init],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-utils"])
-fi
-
-# libfreerdp-codec
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_LIB([freerdp-codec], [freerdp_image_convert],
-                 [RDP_LIBS="$RDP_LIBS -lfreerdp-codec"])
-fi
-
-# Available color conversion functions
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([freerdp_convert_gdi_order_color],
-        [AC_DEFINE([HAVE_FREERDP_CONVERT_GDI_ORDER_COLOR],,
-                   [Whether freerdp_convert_gdi_order_color() is defined])],,
-        [#include <freerdp/codec/color.h>])
-
-    AC_CHECK_DECL([freerdp_color_convert_drawing_order_color_to_gdi_color],
-        [AC_DEFINE([HAVE_FREERDP_COLOR_CONVERT_DRAWING_ORDER_COLOR_TO_GDI_COLOR],,
-                   [Whether freerdp_color_convert_drawing_order_color_to_gdi_color() is defined])],,
-        [#include <freerdp/codec/color.h>])
-fi
-
-# Check for interval polling in plugins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSvcPlugin.interval_ms],,,
-                     [[#include <freerdp/utils/svc_plugin.h>]])
-fi
-
-# Keyboard layout header
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/locale/keyboard.h],,
-                      [AC_CHECK_HEADERS([freerdp/kbd/layouts.h],,
-                                       [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find keyboard layout headers
-   RDP will be disabled.
-  --------------------------------------------])
-                                        have_freerdp=no])])
-fi
-
-# New headers defining addins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/addin.h freerdp/client/channels.h])
-fi
-
-# Header defining cliprdr
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/client/cliprdr.h],,
-                     [AC_CHECK_HEADERS([freerdp/plugins/cliprdr.h],,
-                                       [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find cliprdr headers
-   RDP will be disabled.
-  --------------------------------------------])
-                                        have_freerdp=no],
-                                       [#include <freerdp/types.h>])],
-                     [#include <winpr/wtypes.h>
-                      #include <winpr/collections.h>])
-fi
-
-# Header defining display update channel
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/client/disp.h],
-                     [AC_DEFINE([HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT],,
-                                [Whether FreeRDP supports the display update channel])]
-                     [AC_CHECK_MEMBERS([rdpSettings.SupportDisplayControl],,,
-                                       [[#include <freerdp/freerdp.h>]])],,
-                     [#include <winpr/wtypes.h>
-                      #include <winpr/collections.h>])
-fi
-
-# Support for RDP gateways 
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSettings.GatewayEnabled],
-                     [AC_DEFINE([HAVE_FREERDP_GATEWAY_SUPPORT],,
-                                [Whether FreeRDP supports RDP gateways])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-# Support for load balancing via connection brokers 
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpSettings.LoadBalanceInfo],
-                     [AC_DEFINE([HAVE_FREERDP_LOAD_BALANCER_SUPPORT],,
-                                [Whether FreeRDP supports load balancers])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-# Support for "PubSub" event system
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([PubSub_SubscribeChannelConnected],
-        [AC_DEFINE([HAVE_FREERDP_EVENT_PUBSUB],,
-                   [Whether this version of FreeRDP provides the PubSub event system])],,
-        [#include <freerdp/event.h>])
-fi
-
-# Addin registration variations
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_DECL([freerdp_register_addin_provider],
-        [AC_DEFINE([HAVE_FREERDP_REGISTER_ADDIN_PROVIDER],,
-                   [Whether freerdp_register_addin_provider() is defined])],,
-        [#include <freerdp/addin.h>])
-
-    AC_CHECK_DECL([freerdp_channels_global_init],
-        [AC_DEFINE([HAVE_FREERDP_CHANNELS_GLOBAL_INIT],,
-                   [Whether freerdp_channels_global_init() is defined])],,
-        [#include <freerdp/channels/channels.h>])
-fi
-
-# Availability of ADDIN_ARGV structure for configuring plugins
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_TYPE([ADDIN_ARGV],
-        [AC_DEFINE([HAVE_ADDIN_ARGV],,
-                   [Whether the ADDIN_ARGV type is available])],,
-        [#include <freerdp/settings.h>])
-fi
-
-#
-# FreeRDP: WinPR
-#
-
-# Check for stream support via WinPR
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADER(winpr/stream.h,,
-                    [have_winpr=no,
-                     AC_CHECK_DECL([stream_write_uint8],,
-                                  [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find stream support
-   RDP will be disabled.
-  --------------------------------------------])
-                                   have_freerdp=no],
-                                  [#include <freerdp/utils/stream.h>])])
-fi
-
-# Check for types in WinPR
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADER(winpr/wtypes.h,,
-                    [have_winpr=no,
-                     AC_CHECK_HEADER(freerdp/types.h,,
-                                     [AC_MSG_WARN([
-  --------------------------------------------
-   Unable to find type definitions
-   RDP will be disabled.
-  --------------------------------------------])
-                                      have_freerdp=no])])
-fi
-
-if test "x${have_freerdp}" = "xyes" -a "x${have_winpr}" = "xyes"
-then
-    AC_DEFINE([ENABLE_WINPR],,
-              [Whether library support for WinPR types was found])
-fi
-
-#
-# FreeRDP: freerdp 
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    # Check for current (as of 1.1) freerdp interface
-    AC_CHECK_MEMBERS([freerdp.ContextSize],
-                     [freerdp_interface=stable],,
-                     [[#include <freerdp/freerdp.h>]])
-
-    # If not current, check for legacy interface
-    if test "x${freerdp_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([freerdp.context_size],
-                         [freerdp_interface=legacy],,
-                         [[#include <freerdp/freerdp.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${freerdp_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_FREERDP],,
-                  [Whether the older version of the FreeRDP API was found])
-    elif test "x${freerdp_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown FreeRDP interface
-   RDP will be disabled.
-  --------------------------------------------])
-        have_freerdp=no
-    fi
-fi
-
-#
-# FreeRDP: rdpSettings
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    # Check for current (as of 1.1) rdpSettings interface
-    AC_CHECK_MEMBERS([rdpSettings.Width,
-                      rdpSettings.Height,
-                      rdpSettings.FastPathInput,
-                      rdpSettings.FastPathOutput,
-                      rdpSettings.SendPreconnectionPdu,
-                      rdpSettings.OrderSupport],
-                     [rdpsettings_interface=stable],,
-                     [[#include <freerdp/freerdp.h>]])
-
-    # If not current, check for legacy interface
-    if test "x${rdpsettings_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([rdpSettings.width,
-                          rdpSettings.height,
-                          rdpSettings.order_support],
-                         [rdpsettings_interface=legacy],,
-                         [[#include <freerdp/freerdp.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${rdpsettings_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_RDPSETTINGS],,
-                  [Whether the legacy version of the rdpSettings API was found])
-
-        # Legacy interface may not have AudioPlayback settings
-        AC_CHECK_MEMBERS([rdpSettings.audio_playback],,
-                         [rdpsettings_audioplayback=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-        # Legacy interface may not have AudioCapture settings
-        AC_CHECK_MEMBERS([rdpSettings.audio_capture],,
-                         [rdpsettings_audiocapture=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-        # Legacy interface may not have DeviceRedirection settings
-        AC_CHECK_MEMBERS([rdpSettings.device_redirection],,
-                         [rdpsettings_deviceredirection=no],
-                         [[#include <freerdp/freerdp.h>]])
-
-    elif test "x${rdpsettings_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown rdpSettings interface
-   RDP will be disabled.
-  --------------------------------------------]) 
-        have_freerdp=no
-    fi
-fi
-
-# Activate audio playback settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audioplayback}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_AUDIOPLAYBACK],,
-              [Whether the rdpSettings structure has AudioPlayback settings])
-fi
-
-# Activate audio capture settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_audiocapture}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_AUDIOCAPTURE],,
-              [Whether the rdpSettings structure has AudioCapture settings])
-fi
-
-# Activate device redirection settings if present
-if test "x${have_freerdp}" = "xyes" -a "x${rdpsettings_deviceredirection}" = "xyes"; then
-    AC_DEFINE([HAVE_RDPSETTINGS_DEVICEREDIRECTION],,
-              [Whether the rdpSettings structure has DeviceRedirection settings])
-fi
-
-# Check if the type CHANNEL_ENTRY_POINTS_FREERDP exists, if not define it to CHANNEL_ENTRY_POINTS_EX
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_TYPE([CHANNEL_ENTRY_POINTS_FREERDP],,
-                  AC_DEFINE([CHANNEL_ENTRY_POINTS_FREERDP],[CHANNEL_ENTRY_POINTS_EX], [Type compatibility]),
-                  [[#include <freerdp/svc.h>]])
-fi
-
-# Check if the freerdp version header exists
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_HEADERS([freerdp/version.h])
-fi
-
-#
-# FreeRDP: rdpBitmap
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether rdpBitmap.Decompress() requires the codec_id])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <winpr/wtypes.h>
-                                        #include <freerdp/freerdp.h>
-                                        void __decompress(rdpContext* context,
-                                                          rdpBitmap* bitmap,
-                                                          UINT8* data,
-                                                          int width,
-                                                          int height,
-                                                          int bpp,
-                                                          int length,
-                                                          BOOL compressed,
-                                                          int codec_id);
-                                        rdpBitmap b = { .Decompress = __decompress };]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_RDPBITMAP],,
-                                 [Whether the legacy rdpBitmap API was found])])
-fi
-
-#
-# FreeRDP: IWTSVirtualChannelCallback
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether IWTSVirtualChannelCallback.OnDataReceived() uses a wStream])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <winpr/wtypes.h>
-                                        #include <freerdp/dvc.h>
-                                        #include <freerdp/freerdp.h>
-                                        int __data_received(
-                                            IWTSVirtualChannelCallback* channel_callback,
-                                            wStream* stream);
-                                        IWTSVirtualChannelCallback cb = {
-                                            .OnDataReceived = __data_received
-                                        };
-                                        int main() {
-                                            return
-                                                cb.OnDataReceived(NULL, NULL);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_IWTSVIRTUALCHANNELCALLBACK],,
-                                 [Whether the legacy IWTSVirtualChannelCallback API was found])])
-fi
-
-#
-# FreeRDP: Decompression function variants
-#
-
-# Check whether interleaved_decompress() can handle the palette
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether interleaved_decompress() accepts an additional palette parameter])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/codec/interleaved.h>
-
-                                        int main() {
-                                            BYTE* palette = NULL;
-                                            interleaved_decompress(NULL, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, palette);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])
-                       AC_DEFINE([INTERLEAVED_DECOMPRESS_TAKES_PALETTE],,
-                                 [Whether interleaved_decompress() accepts an additional palette parameter])],
-                      [AC_MSG_RESULT([no])])
-fi
-
-# Check whether planar_decompress() will handle flipping
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether planar_decompress() can flip])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/codec/planar.h>
-
-                                        int main() {
-                                            BOOL* flip = TRUE;
-                                            planar_decompress(NULL, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, flip);
-                                        }]])],
-                      [AC_MSG_RESULT([yes])
-                       AC_DEFINE([PLANAR_DECOMPRESS_CAN_FLIP],,
-                                 [Whether planar_decompress() can flip])],
-                      [AC_MSG_RESULT([no])])
-fi
-
-#
-# FreeRDP: rdpContext
-#
-
-# Check for rdpContext.codecs
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpContext.codecs],
-                     [AC_DEFINE([FREERDP_BITMAP_REQUIRES_ALIGNED_MALLOC],,
-                                [Whether this version of FreeRDP requires _aligned_malloc() for bitmap data])],,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-#
-# FreeRDP: rdpPalette
-#
-
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_MSG_CHECKING([whether rdpPalette.entries is static])
-    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <freerdp/update.h>
-                                        rdpPalette p;
-                                        PALETTE_ENTRY* foo = p.entries;]])],
-                      [AC_MSG_RESULT([yes])],
-                      [AC_MSG_RESULT([no])
-                       AC_DEFINE([LEGACY_RDPPALETTE],,
-                                 [Whether the legacy rdpPalette API was found])])
-fi
-
-#
-# FreeRDP: rdpPointer
-#
-
-# Check for SetDefault and SetNull members of rdpPointer
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([rdpPointer.SetDefault,
-                      rdpPointer.SetNull],
-                     ,,
-                     [[#include <freerdp/freerdp.h>]])
-fi
-
-#
-# FreeRDP: wMessage / RDP_EVENT
-#
-
-# Check for current (as of 1.1) wMessage interface
-if test "x${have_freerdp}" = "xyes"
-then
-    AC_CHECK_MEMBERS([wMessage.id],
-                     [event_interface=stable],,
-                     [[#include <winpr/collections.h>]])
-
-    # If not current, check for legacy (RDP_EVENT) interface
-    if test "x${event_interface}" = "xunknown"
-    then
-        AC_CHECK_MEMBERS([RDP_EVENT.event_class],
-                         [event_interface=legacy],,
-                         [[#include <freerdp/types.h>]])
-    fi
-
-    # Set defines based on interface type, warn if unknown
-    if test "x${event_interface}" = "xlegacy"; then
-        AC_DEFINE([LEGACY_EVENT],,
-                  [Whether the legacy RDP_EVENT API was found])
-    elif test "x${event_interface}" = "xunknown"; then
-        AC_MSG_WARN([
-  --------------------------------------------
-   Unknown event interface
-   RDP will be disabled.
-  --------------------------------------------])
-        have_freerdp=no
-    fi
-fi
-
-AM_CONDITIONAL([LEGACY_FREERDP_EXTENSIONS], [test "x${legacy_freerdp_extensions}" = "xyes"])
 
 Review comment:
   Yup!

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573461365
 
 
   Actually ... as the calling convention is the same between the two variants, and the only difference is that the version we currently code against explicitly declares that it will not modify the contents of that structure, we may have lucked out here. I think we can safely typecast to the type expected.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364067881
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   Double space in this comment should be changed to a single space.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365556619
 
 

 ##########
 File path: src/protocols/rdp/bitmap.h
 ##########
 @@ -66,8 +61,11 @@ typedef struct guac_rdp_bitmap {
  *
  * @param bitmap
  *     The bitmap to cache.
+ *
+ * @return
+ *     TRUE if successful, FALSE otherwise.
 
 Review comment:
   Regarding the other cases, yes - the other functions are written to comply with the API of the FreeRDP library, which does require a `BOOL` return to signal failures, even if our implementation doesn't have a failure condition in most (all?) cases.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555236
 
 

 ##########
 File path: src/protocols/rdp/bitmap.h
 ##########
 @@ -66,8 +61,11 @@ typedef struct guac_rdp_bitmap {
  *
  * @param bitmap
  *     The bitmap to cache.
+ *
+ * @return
+ *     TRUE if successful, FALSE otherwise.
 
 Review comment:
   In this case, no, I don't believe so. I was probably just on a roll with `BOOL`-ing everything.
   
   I'll recheck the body of the function and switch things back to `void` if `BOOL` is not needed. The fewer things need changing, the better.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365556441
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
+ * Format List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format list.");
+
+    CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    /* Report successful processing of format list */
+    cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
+
+    /* Prefer Unicode (in this case, UTF-16) */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
+
+    /* Use Windows' CP-1252 if Unicode unavailable */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
+
+    /* Ignore any unsupported data */
+    guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
+            "clipboard data. Only Unicode and text clipboard formats are "
+            "currently supported.");
+
+    return CHANNEL_RC_OK;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Request PDUs. The Format Data Request PDU is sent by the RDP server when
+ * requesting that clipboard data be sent, in response to a received Format
+ * List PDU. The client is required to respond with a Format Data Response PDU
+ * containing the requested data.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_request
+ *     The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
+ *     Request PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data request.");
+
+    guac_iconv_write* writer;
+    const char* input = clipboard->clipboard->buffer;
+    char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    /* Map requested clipboard format to a guac_iconv writer */
+    switch (format_data_request->requestedFormatId) {
+
+        case CF_TEXT:
+            writer = GUAC_WRITE_CP1252;
+            break;
+
+        case CF_UNICODETEXT:
+            writer = GUAC_WRITE_UTF16;
+            break;
+
+        /* Warn if clipboard data cannot be sent as intended due to a violation
+         * of the CLIPRDR spec */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
+                    "clipboard data cannot be sent to the RDP server because "
+                    "the RDP server has requested a clipboard format which "
+                    "was not declared as available. This violates the "
+                    "specification for the CLIPRDR channel.");
+            free(output);
+            return CHANNEL_RC_OK;
+
+    }
+
+    /* Send received clipboard data to the RDP server in the format
+     * requested */
+    BYTE* start = (BYTE*) output;
+    guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
+               writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
+        .requestedFormatData = (BYTE*) start,
+        .dataLen = ((BYTE*) output) - start,
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data response.");
+
+    return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Response PDUs. The Format Data Response PDU is sent by the RDP server when
+ * fullfilling a request for clipboard data received via a Format Data Request
+ * PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_response
+ *     The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
+ *     Response PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data response.");
+
+    char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
+
+    guac_iconv_read* reader;
+    const char* input = (char*) format_data_response->requestedFormatData;
+    char* output = received_data;
+
+    /* Find correct source encoding */
+    switch (clipboard->requested_format) {
+
+        /* Non-Unicode (Windows CP-1252) */
+        case CF_TEXT:
+            reader = GUAC_READ_CP1252;
+            break;
+
+        /* Unicode (UTF-16) */
+        case CF_UNICODETEXT:
+            reader = GUAC_READ_UTF16;
+            break;
+
+        /* If the format ID stored within the guac_rdp_clipboard structure is actually
+         * not supported here, then something has been implemented incorrectly.
+         * Either incorrect values are (somehow) being stored, or support for
+         * the format indicated by that value is incomplete and must be added
+         * here. The values which may be stored within requested_format are
+         * completely within our control. */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested "
+                    "clipboard data in unsupported format (0x%X).",
+                    clipboard->requested_format);
+            return CHANNEL_RC_OK;
 
 Review comment:
   Yes. FreeRDP handles error return codes similarly to the way we do, with such errors being treated as fatal (or at least near-fatal). In this case, I'm not sure whether the entire RDP connection would terminate, but returning a non-zero code here would result in the message processing thread for CLIPRDR being shut down.
   
   The root of the relevant code flow is the thread body of FreeRDP's CLIPRDR handling:
   
   https://github.com/FreeRDP/FreeRDP/blob/32bf768652a1a6d6872453ff5c84ab97bedaaa00/channels/cliprdr/client/cliprdr_main.c#L891-L935
   
   In a nutshell:
   
   1. Loading FreeRDP's "cliprdr" plugin results in the above thread starting. It handles messages received along the CLIPRDR channel, delegating processing of those messages to `cliprdr_order_recv()`, an internal function.
   2. In the case of a Format Data Response PDU, `cliprdr_order_recv()` further delegates to `cliprdr_process_format_data_response()` which finally delegates to the function assigned as the `ServerFormatDataResponse` handler, which is `guac_rdp_cliprdr_format_data_response()` in our case.
   3. If the `ServerFormatDataResponse` handler returns anything but `CHANNEL_RC_OK`, that error code propogates its way back up the chain and results in the thread being killed.
   
   So, we could return an error code here, but it would result in no further CLIPRDR messages being processed. Receiving data in an unexpected format from the RDP server isn't great, and would be a violation of CLIPRDR, but maybe is not so bad that CLIPRDR should be killed for the rest of the session. Returning success here (but logging that things are odd) allows things to continue, assuming copy/paste is otherwise working despite the server misbehaving.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573552512
 
 
   After fixing the RAIL issue, I encountered the following:
   
   ```
   ...
     CC       libguac_client_rdp_la-color.lo
   color.c: In function 'guac_rdp_convert_color':
   color.c:62:16: error: implicit declaration of function 'FreeRDPConvertColor'; did you mean 'ConvertColor'? [-Werror=implicit-function-declaration]
        intermed = FreeRDPConvertColor(intermed, src_format, dst_format,
                   ^~~~~~~~~~~~~~~~~~~
                   ConvertColor
   cc1: all warnings being treated as errors
   ```
   
   Apparently, the `FreeRDPConverColor()` function was formerly known as `ConvertColor()`. It was renamed along with similarly-named functions due to Mac applications using `GetColor()` failing to build because that function clashes with a system function of the same name (see FreeRDP/FreeRDP#3810).
   
   Adding tests to determine the proper function doesn't appear to be an option at the moment, as:
   
   * The necessary include path for FreeRDP is only known via pkg-config and I'm unaware of any way to get autoconf tests to find headers that can only be found when using the `CFLAGS` returned by pkg-config.
   * We can't simply test version numbers because all of these FreeRDP variants have the same version.
   
   I tried addressing this by switching to `ConvertColor()`, which should work due to compatibility macros present in the FreeRDP headers (commit a6b7e07). *But*, I then encountered issues with the glyph callbacks:
   
   ```
     CC       libguac_client_rdp_la-rdp.lo
   rdp.c: In function 'rdp_freerdp_pre_connect':
   rdp.c:155:16: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.Draw = guac_rdp_glyph_draw;
                   ^
   rdp.c:156:21: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.BeginDraw = guac_rdp_glyph_begindraw;
                        ^
   rdp.c:157:19: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.EndDraw = guac_rdp_glyph_enddraw;
                      ^
   cc1: all warnings being treated as errors
   ```
   
   In this case, the incompatibility is due to switching from `UINT32` to `INT32` for width and height. At this point, I'm thinking we simply shouldn't support the version of FreeRDP on Bionic. The version of the API in use appears to be unique to Bionic and from before any 2.0.0 release candidate was made.
   
   I've also created some Jenkins jobs to verify the build, so we should be able to better ensure build compatibility going forward:
   
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-centos/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-fedora/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-debian/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-ubuntu/
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-571311358
 
 
   After some self review, I've added a few more commits:
   
   * The color conversion function behaved incorrectly due to `FreeRDPConvertColor()` expecting the input color to be coming from `ReadColor()`. `ReadColor()` converts a color which is independent of native endianness to an intermediate format which is dependent on native endianness, and `FreeRDPConvertColor()` will only work correctly with that intermediate format. This was causing an issue where black text was occasionally rendering as bright blue, with the bright blue coming from the 0xFF value for the alpha channel being stuck in the wrong place. (See commit a54a123)
   * I had previously modified the common surface implementation to avoid automatically flushing the surface when a rectangle is drawn (typically used for initializing the surface) when that surface hasn't yet been sent to the client (common for RDP, where we sometimes receive instructions to create an off-screen surface and then destroy it without ever actually using it). The logic wasn't entirely correct, and accidentally removed some consideration of the dirty flag when determining whether to combine updates. (See commit 0677a9a)
   * I ran the Include What You Use tool before opening this PR to try to clean up the headers included over the ages, as many no longer need to be included in those locations due to changes made. That tool added empty `struct` forward declarations which were unnecessary. I have removed these. (See commit 1f24c47)
   
   I didn't redo the test merge on https://github.com/mike-jumper/guacamole-server/tree/freerdp-migrate-2.x-resolve-merge-master, but I did at least cherry pick the above commits onto that branch so the contents will match the expected merge resolution.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365492967
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.h
 ##########
 @@ -17,85 +17,103 @@
  * under the License.
  */
 
-
-#ifndef __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
-#define __GUAC_RDPDR_FS_MESSAGES_FILE_INFO_H
+#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H
+#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_FILE_INFO_H
 
 /**
  * Handlers for file queries received over the RDPDR channel via the
  * IRP_MJ_QUERY_INFORMATION major function.
  *
- * @file rdpdr_fs_messages_file_info.h
+ * @file rdpdr-fs-messages-file-info.h
  */
 
-#include "config.h"
-
-#include "rdpdr_service.h"
+#include "channels/common-svc.h"
+#include "channels/rdpdr/rdpdr.h"
 
-#ifdef ENABLE_WINPR
 #include <winpr/stream.h>
-#else
-#include "compat/winpr-stream.h"
-#endif
+
+/**
+ * Handler for Device I/O Requests which set/update file information.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
 
 Review comment:
   "of the common RDPDR header", perhaps?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574386165
 
 
   Merge to `master` completed.  I had to work around a couple of settings that got added into master, but I think I've managed to do it without clobbering any of the updates that have happened to `master` in the meantime.  There's certainly an off-chance we'll have to go back and fix something that I accidentally undid, but I tried to go back and verify a few times that nothing substantial was removed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364067881
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   Double space in this comment should be removed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364972724
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
+ * name as the pipe stream. Received pipe streams are associated with the
+ * relevant guac_rdp_pipe_svc instance and the SVC-specific "blob" instructino
 
 Review comment:
   Fixedo.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573971330
 
 
   Everything looks good with CentOS7 with 2.0.0-rc4

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555126
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
 
 Review comment:
   Fair point.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573381212
 
 
   OK - I think I have addressed everything noted thus far with the exception of:
   
   1. The naming of the `n` and `c` variables representing components of an NTSTATUS code.
   2. The concerns with CLIPRDR handler return codes.
   
   I believe the above are correct as they stand (see comments), but please let me know if you believe they still need to be addressed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364476956
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.c
 ##########
 @@ -0,0 +1,230 @@
+/*
+ * 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 "channels/common-svc.h"
+#include "channels/pipe-svc.h"
+#include "common/list.h"
+#include "rdp.h"
+
+#include <freerdp/settings.h>
+#include <guacamole/client.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/stream.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* pipe_svc) {
+
+    /* Send pipe instruction for the SVC's output stream */
+    guac_protocol_send_pipe(socket, pipe_svc->output_pipe,
+            "application/octet-stream", pipe_svc->svc->name);
+
+}
+
+void guac_rdp_pipe_svc_send_pipes(guac_user* user) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    guac_common_list_lock(rdp_client->available_svc);
+
+    /* Send pipe for each allocated SVC's output stream */
+    guac_common_list_element* current = rdp_client->available_svc->head;
+    while (current != NULL) {
+        guac_rdp_pipe_svc_send_pipe(user->socket, (guac_rdp_pipe_svc*) current->data);
+        current = current->next;
+    }
+
+    guac_common_list_unlock(rdp_client->available_svc);
+
+}
+
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* pipe_svc) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    /* Add to list of available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    guac_common_list_add(rdp_client->available_svc, pipe_svc);
+    guac_common_list_unlock(rdp_client->available_svc);
+
+}
+
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_common_list_element* current;
+    guac_rdp_pipe_svc* found = NULL;
+
+    /* For each available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    current = rdp_client->available_svc->head;
+    while (current != NULL) {
+
+        /* If name matches, found */
+        guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data;
+        if (strcmp(current_svc->svc->name, name) == 0) {
+            found = current_svc;
+            break;
+        }
+
+        current = current->next;
+
+    }
+    guac_common_list_unlock(rdp_client->available_svc);
+
+    return found;
+
+}
+
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_common_list_element* current;
+    guac_rdp_pipe_svc* found = NULL;
+
+    /* For each available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    current = rdp_client->available_svc->head;
+    while (current != NULL) {
+
+        /* If name matches, remove entry */
+        guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data;
+        if (strcmp(current_svc->svc->name, name) == 0) {
+            guac_common_list_remove(rdp_client->available_svc, current);
+            found = current_svc;
+            break;
+        }
+
+        current = current->next;
+
+    }
+    guac_common_list_unlock(rdp_client->available_svc);
+
+    /* Return removed entry, if any */
+    return found;
+
+}
+
+int guac_rdp_pipe_svc_pipe_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* name) {
+
+    guac_rdp_pipe_svc* pipe_svc = guac_rdp_pipe_svc_get(user->client, name);
+
+    /* Fail if no such SVC */
+    if (pipe_svc == NULL) {
+        guac_user_log(user, GUAC_LOG_WARNING, "User requested non-existent "
+                "pipe (no such SVC configured): \"%s\"", name);
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)",
+                GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST);
+        guac_socket_flush(user->socket);
+        return 0;
 
 Review comment:
   I assume returning 0 here, and in the other handlers, is the expected behavior??

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365556483
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,601 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities and supported format list */
+    guac_rdp_cliprdr_send_capabilities(cliprdr);
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicating that clipboard data is available via a
+ * Format List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format list.");
+
+    CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    /* Report successful processing of format list */
+    cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
+
+    /* Prefer Unicode (in this case, UTF-16) */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_UNICODETEXT);
+
+    /* Use Windows' CP-1252 if Unicode unavailable */
+    if (guac_rdp_cliprdr_format_supported(format_list, CF_TEXT))
+        return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
+
+    /* Ignore any unsupported data */
+    guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
+            "clipboard data. Only Unicode and text clipboard formats are "
+            "currently supported.");
+
+    return CHANNEL_RC_OK;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Request PDUs. The Format Data Request PDU is sent by the RDP server when
+ * requesting that clipboard data be sent, in response to a received Format
+ * List PDU. The client is required to respond with a Format Data Response PDU
+ * containing the requested data.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_request
+ *     The CLIPRDR_FORMAT_DATA_REQUEST structure representing the Format Data
+ *     Request PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_REQUEST* format_data_request) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data request.");
+
+    guac_iconv_write* writer;
+    const char* input = clipboard->clipboard->buffer;
+    char* output = malloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    /* Map requested clipboard format to a guac_iconv writer */
+    switch (format_data_request->requestedFormatId) {
+
+        case CF_TEXT:
+            writer = GUAC_WRITE_CP1252;
+            break;
+
+        case CF_UNICODETEXT:
+            writer = GUAC_WRITE_UTF16;
+            break;
+
+        /* Warn if clipboard data cannot be sent as intended due to a violation
+         * of the CLIPRDR spec */
+        default:
+            guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
+                    "clipboard data cannot be sent to the RDP server because "
+                    "the RDP server has requested a clipboard format which "
+                    "was not declared as available. This violates the "
+                    "specification for the CLIPRDR channel.");
+            free(output);
+            return CHANNEL_RC_OK;
+
+    }
+
+    /* Send received clipboard data to the RDP server in the format
+     * requested */
+    BYTE* start = (BYTE*) output;
+    guac_iconv(GUAC_READ_UTF8, &input, clipboard->clipboard->length,
+               writer, &output, GUAC_RDP_CLIPBOARD_MAX_LENGTH);
+
+    CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
+        .requestedFormatData = (BYTE*) start,
+        .dataLen = ((BYTE*) output) - start,
+        .msgFlags = CB_RESPONSE_OK
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data response.");
+
+    return cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format Data
+ * Response PDUs. The Format Data Response PDU is sent by the RDP server when
+ * fullfilling a request for clipboard data received via a Format Data Request
+ * PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_data_response
+ *     The CLIPRDR_FORMAT_DATA_RESPONSE structure representing the Format Data
+ *     Response PDU that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_DATA_RESPONSE* format_data_response) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "format data response.");
+
+    char received_data[GUAC_RDP_CLIPBOARD_MAX_LENGTH];
+
+    guac_iconv_read* reader;
+    const char* input = (char*) format_data_response->requestedFormatData;
+    char* output = received_data;
+
+    /* Find correct source encoding */
+    switch (clipboard->requested_format) {
+
+        /* Non-Unicode (Windows CP-1252) */
+        case CF_TEXT:
+            reader = GUAC_READ_CP1252;
+            break;
+
+        /* Unicode (UTF-16) */
+        case CF_UNICODETEXT:
+            reader = GUAC_READ_UTF16;
+            break;
+
+        /* If the format ID stored within the guac_rdp_clipboard structure is actually
+         * not supported here, then something has been implemented incorrectly.
+         * Either incorrect values are (somehow) being stored, or support for
+         * the format indicated by that value is incomplete and must be added
+         * here. The values which may be stored within requested_format are
+         * completely within our control. */
 
 Review comment:
   I believe so (see my other response regarding FreeRDP's CLIPRDR thread and its error handling).

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573971638
 
 
   OK, I've added configure tests and things seem to build across the board now: git master, 2.0.0-rc0 through 2.0.0-rc4, as well as Bionic Edition.
   
   The ASF Jenkins instance is too backed up at the moment to be used to verify the builds, but I'm doing so manually on my own dev machine via Docker.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r363062983
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   Extra space after "AUDIO_INPUT" here.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364954598
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-messages.c
 ##########
 @@ -0,0 +1,349 @@
+/*
+ * 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 "channels/rdpdr/rdpdr-messages.h"
+#include "channels/rdpdr/rdpdr.h"
+#include "rdp.h"
+#include "settings.h"
+
+#include <freerdp/channels/rdpdr.h>
+#include <guacamole/client.h>
+#include <winpr/stream.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Client Announce Reply message. The Client Announce Reply message is
+ * required to be sent in response to the Server Announce Request message. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/d6fe6d1b-c145-4a6f-99aa-4fe3cdcea398
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param major
+ *     The major version of the RDPDR protocol in use. This value must always
+ *     be 1.
+ *
+ * @param minor
+ *     The minor version of the RDPDR protocol in use. This value must be
+ *     either 2, 5, 10, 12, or 13.
+ *
+ * @param client_id
+ *     The client ID received in the Server Announce Request, or a randomly
+ *     generated ID.
+ */
+static void guac_rdpdr_send_client_announce_reply(guac_rdp_common_svc* svc,
+        unsigned int major, unsigned int minor, unsigned int client_id) {
+
+    wStream* output_stream = Stream_New(NULL, 12);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENTID_CONFIRM);
+
+    /* Write content */
+    Stream_Write_UINT16(output_stream, major);
+    Stream_Write_UINT16(output_stream, minor);
+    Stream_Write_UINT32(output_stream, client_id);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+
+}
+
+/**
+ * Sends a Client Name Request message. The Client Name Request message is used
+ * by the client to announce its own name. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/902497f1-3b1c-4aee-95f8-1668f9b7b7d2
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param name
+ *     The name that should be used for the client.
+ */
+static void guac_rdpdr_send_client_name_request(guac_rdp_common_svc* svc,
+        const char* name) {
+
+    int name_bytes = strlen(name) + 1;
+    wStream* output_stream = Stream_New(NULL, 16 + name_bytes);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_NAME);
+
+    /* Write content */
+    Stream_Write_UINT32(output_stream, 0); /* ASCII */
+    Stream_Write_UINT32(output_stream, 0); /* 0 required by RDPDR spec */
+    Stream_Write_UINT32(output_stream, name_bytes);
+    Stream_Write(output_stream, name, name_bytes);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+
+}
+
+/**
+ * Sends a Client Core Capability Response message. The Client Core Capability
+ * Response message is used to announce the client's capabilities, in response
+ * to receiving the server's capabilities via a Server Core Capability Request.
+ * See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/f513bf87-cca0-488a-ac5c-18cf18f4a7e1
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ */
+static void guac_rdpdr_send_client_capability(guac_rdp_common_svc* svc) {
+
+    wStream* output_stream = Stream_New(NULL, 256);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Sending capabilities...");
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_CLIENT_CAPABILITY);
+
+    /* Capability count + padding */
+    Stream_Write_UINT16(output_stream, 3);
+    Stream_Write_UINT16(output_stream, 0); /* Padding */
+
+    /* General capability header */
+    Stream_Write_UINT16(output_stream, CAP_GENERAL_TYPE);
+    Stream_Write_UINT16(output_stream, 44);
+    Stream_Write_UINT32(output_stream, GENERAL_CAPABILITY_VERSION_02);
+
+    /* General capability data */
+    Stream_Write_UINT32(output_stream, GUAC_OS_TYPE);                /* osType - required to be ignored */
+    Stream_Write_UINT32(output_stream, 0);                           /* osVersion */
+    Stream_Write_UINT16(output_stream, 1);                           /* protocolMajor - must be set to 1 */
+    Stream_Write_UINT16(output_stream, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinor */
+    Stream_Write_UINT32(output_stream, 0xFFFF);                      /* ioCode1 */
+    Stream_Write_UINT32(output_stream, 0);                           /* ioCode2 */
+    Stream_Write_UINT32(output_stream,
+                                      RDPDR_DEVICE_REMOVE_PDUS
+                                    | RDPDR_CLIENT_DISPLAY_NAME_PDU
+                                    | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
+    Stream_Write_UINT32(output_stream, 0);                      /* extraFlags1 */
+    Stream_Write_UINT32(output_stream, 0);                      /* extraFlags2 */
+    Stream_Write_UINT32(output_stream, 0);                      /* SpecialTypeDeviceCap */
+
+    /* Printer support header */
+    Stream_Write_UINT16(output_stream, CAP_PRINTER_TYPE);
+    Stream_Write_UINT16(output_stream, 8);
+    Stream_Write_UINT32(output_stream, PRINT_CAPABILITY_VERSION_01);
+
+    /* Drive support header */
+    Stream_Write_UINT16(output_stream, CAP_DRIVE_TYPE);
+    Stream_Write_UINT16(output_stream, 8);
+    Stream_Write_UINT32(output_stream, DRIVE_CAPABILITY_VERSION_02);
+
+    guac_rdp_common_svc_write(svc, output_stream);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Capabilities sent.");
+
+}
+
+/**
+ * Sends a Client Device List Announce Request message. The Client Device List
+ * Announce Request message is used by the client to enumerate all devices
+ * which should be made available within the RDP session via RDPDR. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/10ef9ada-cba2-4384-ab60-7b6290ed4a9a
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ */
+static void guac_rdpdr_send_client_device_list_announce_request(guac_rdp_common_svc* svc) {
+
+    guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
+
+    /* Calculate number of bytes needed for the stream */
+    int streamBytes = 16;
+    for (int i=0; i < rdpdr->devices_registered; i++)
+        streamBytes += rdpdr->devices[i].device_announce_len;
+
+    /* Allocate the stream */
+    wStream* output_stream = Stream_New(NULL, streamBytes);
+
+    /* Write header */
+    Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
+    Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICELIST_ANNOUNCE);
+
+    /* Get the stream for each of the devices. */
+    Stream_Write_UINT32(output_stream, rdpdr->devices_registered);
+    for (int i=0; i<rdpdr->devices_registered; i++) {
+        
+        Stream_Write(output_stream,
+                Stream_Buffer(rdpdr->devices[i].device_announce),
+                rdpdr->devices[i].device_announce_len);
+
+        guac_client_log(svc->client, GUAC_LOG_DEBUG, "Registered device %i (%s)",
+                rdpdr->devices[i].device_id, rdpdr->devices[i].device_name);
+        
+    }
+
+    guac_rdp_common_svc_write(svc, output_stream);
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "All supported devices sent.");
+
+}
+
+void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+
+    unsigned int major, minor, client_id;
+
+    Stream_Read_UINT16(input_stream, major);
+    Stream_Read_UINT16(input_stream, minor);
+    Stream_Read_UINT32(input_stream, client_id);
+
+    /* Must choose own client ID if minor not >= 12 */
+    if (minor < 12)
+        client_id = random() & 0xFFFF;
+
+    guac_client_log(svc->client, GUAC_LOG_INFO, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id);
+
+    /* Respond to announce */
+    guac_rdpdr_send_client_announce_reply(svc, major, minor, client_id);
+
+    /* Name request */
+    guac_rdpdr_send_client_name_request(svc, ((guac_rdp_client*) svc->client->data)->settings->client_name);
+
+}
+
+void guac_rdpdr_process_clientid_confirm(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+    guac_client_log(svc->client, GUAC_LOG_DEBUG, "Client ID confirmed");
+}
+
+void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc,
+        wStream* input_stream) {
+
+    guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
+
+    unsigned int device_id, ntstatus;
+    int severity, c, n, facility, code;
 
 Review comment:
   Weirdly enough, they are standard names. The standard is not set by FreeRDP but by Microsoft. Each of these variables refers to a portion of a 32-bit "NTSTATUS" code:
   
   https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/87fba13e-bf06-450e-83b1-9241dc81e781
   
   As I'm calling the "sev" field "severity" here, it might make sense to change `c` to `customer`, however I'm not sure anyone knows what `n` is:
   
   > **N (1 bit)**: Reserved. MUST be set to 0 so that it is possible to map an NTSTATUS value to an equivalent HRESULT value, as specified in section 2.1, by setting this bit.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573483137
 
 
   Okay, testing looks good for me - I'll try to kick the tires on it some more over the next few days to be sure, but initial stuff looks fine.
   
   @jmuehlner Any last objections before the merge?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364361909
 
 

 ##########
 File path: src/protocols/rdp/channels/rail.c
 ##########
 @@ -0,0 +1,197 @@
+/*
+ * 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 "channels/rail.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+#include "settings.h"
+
+#include <freerdp/client/rail.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/rail.h>
+#include <guacamole/client.h>
+#include <winpr/wtypes.h>
+#include <winpr/wtsapi.h>
+
+#include <stddef.h>
+#include <string.h>
+
+/**
+ * Completes initialization of the RemoteApp session, sending client system
+ * parameters and executing the desired RemoteApp command using the Client
+ * System Parameters Update PDU and Client Execute PDU respectively. These PDUs
+ * MUST be sent for the desired RemoteApp to run, and MUST NOT be sent until
+ * after a Handshake or HandshakeEx PDU has been received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/60344497-883f-4711-8b9a-828d1c580195 (System Parameters Update PDU)
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/98a6e3c3-c2a9-42cc-ad91-0d9a6c211138 (Client Execute PDU)
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDUs were sent successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
+
+    guac_client* client = (guac_client*) rail->custom;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    RAIL_SYSPARAM_ORDER sysparam = {
+        .workArea = {
+            .left   = 0,
+            .top    = 0,
+            .right  = rdp_client->settings->width,
+            .bottom = rdp_client->settings->height
+        },
+        .dragFullWindows = FALSE
+    };
+
+    /* Send client system parameters */
+    UINT status = rail->ClientSystemParam(rail, &sysparam);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    RAIL_EXEC_ORDER exec = {
+        .RemoteApplicationProgram = rdp_client->settings->remote_app,
+        .RemoteApplicationWorkingDir = rdp_client->settings->remote_app_dir,
+        .RemoteApplicationArguments = rdp_client->settings->remote_app_args,
+    };
+
+    /* Execute desired RemoteApp command */
+    return rail->ClientExecute(rail, &exec);
+
+}
+
+/**
+ * Callback which is invoked when a Handshake PDU is received from the RDP
+ * server. No communication for RemoteApp may occur until the Handshake PDU
+ * (or, alternatively, the HandshakeEx PDU) is received. See:
+ *
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdperp/cec4eb83-b304-43c9-8378-b5b8f5e7082a
+ *
+ * @param rail
+ *     The RailClientContext structure used by FreeRDP to handle the RAIL
+ *     channel for the current RDP session.
+ *
+ * @param handshake
 
 Review comment:
   Not currently, no. We ignore the contents of the handshake, simply using it to signal when client system parameters should be sent and execution of the RemoteApp should be requested.
   
   This is actually in line with the behavior of xfreerdp, which also ignores the contents of the handshake PDU received from the server:
   
   https://github.com/FreeRDP/FreeRDP/blob/02614cce49ce6ff120a1306962c5d3ff6b05ea75/client/X11/xf_rail.c#L892-L901

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573460561
 
 
   Ugh.  It would be nice if the API would stay constant enough to be able to use it...

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365610870
 
 

 ##########
 File path: src/protocols/rdp/channels/cliprdr.c
 ##########
 @@ -0,0 +1,605 @@
+/*
+ * 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 "channels/cliprdr.h"
+#include "client.h"
+#include "common/clipboard.h"
+#include "common/iconv.h"
+#include "plugins/channels.h"
+#include "rdp.h"
+
+#include <freerdp/client/cliprdr.h>
+#include <freerdp/event.h>
+#include <freerdp/freerdp.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+#include <winpr/wtypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Sends a Format List PDU to the RDP server containing the formats of
+ * clipboard data supported. This PDU is used both to indicate the general
+ * clipboard formats supported at the begining of an RDP session and to inform
+ * the RDP server that new clipboard data is available within the listed
+ * formats.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Format List PDU was sent successfully, an
+ *     error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
+
+    /* This function is only invoked within FreeRDP-specific handlers for
+     * CLIPRDR, which are not assigned, and thus not callable, until after the
+     * relevant guac_rdp_clipboard structure is allocated and associated with
+     * the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* We support CP-1252 and UTF-16 text */
+    CLIPRDR_FORMAT_LIST format_list = {
+        .formats = (CLIPRDR_FORMAT[]) {
+            { .formatId = CF_TEXT },
+            { .formatId = CF_UNICODETEXT }
+        },
+        .numFormats = 2
+    };
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format list");
+
+    return cliprdr->ClientFormatList(cliprdr, &format_list);
+
+}
+
+/**
+ * Sends a Clipboard Capabilities PDU to the RDP server describing the features
+ * of the CLIPRDR channel that are supported by the client.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the
+ *     CLIPRDR channel for the current RDP session.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the Clipboard Capabilities PDU was sent
+ *     successfully, an error code (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
+
+    CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
+        .capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
+        .capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
+        .version = CB_CAPS_VERSION_2, /* The version of the CLIPRDR specification supported */
+        .generalFlags = CB_USE_LONG_FORMAT_NAMES /* Bitwise OR of all supported feature flags */
+    };
+
+    CLIPRDR_CAPABILITIES caps = {
+        .cCapabilitiesSets = 1,
+        .capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
+    };
+
+    return cliprdr->ClientCapabilities(cliprdr, &caps);
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Monitor Ready
+ * PDUs. The Monitor Ready PDU is sent by the RDP server only during
+ * initialization of the CLIPRDR channel. It is part of the CLIPRDR channel
+ * handshake and indicates that the RDP server's handling of clipboard
+ * redirection is ready to proceed.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param monitor_ready
+ *     The CLIPRDR_MONITOR_READY structure representing the Monitor Ready PDU
+ *     that was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
+        const CLIPRDR_MONITOR_READY* monitor_ready) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
+            "monitor ready.");
+
+    /* Respond with capabilities ... */
+    int status = guac_rdp_cliprdr_send_capabilities(cliprdr);
+    if (status != CHANNEL_RC_OK)
+        return status;
+
+    /* ... and supported format list */
+    return guac_rdp_cliprdr_send_format_list(cliprdr);
+
+}
+
+/**
+ * Sends a Format Data Request PDU to the RDP server, requesting that available
+ * clipboard data be sent to the client in the specified format. This PDU is
+ * sent when the server indicates that clipboard data is available via a Format
+ * List PDU.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param format
+ *     The clipboard format to request. This format must be one of the
+ *     documented values used by the CLIPRDR channel for clipboard format IDs.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_send_format_data_request(
+        CliprdrClientContext* cliprdr, UINT32 format) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
+
+    /* Create new data request */
+    CLIPRDR_FORMAT_DATA_REQUEST data_request = {
+        .requestedFormatId = format
+    };
+
+    /* Note the format we've requested for reference later when the requested
+     * data is received via a Format Data Response PDU */
+    clipboard->requested_format = format;
+
+    guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
+            "format data request.");
+
+    /* Send request */
+    return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
+
+}
+
+/**
+ * Returns whether the given Format List PDU indicates support for the given
+ * clipboard format.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU
+ *     being tested.
+ *
+ * @param format_id
+ *     The ID of the clipboard format to test, such as CF_TEXT or
+ *     CF_UNICODETEXT.
+ *
+ * @return
+ *     Non-zero if the given Format List PDU indicates support for the given
+ *     clipboard format, zero otherwise.
+ */
+static int guac_rdp_cliprdr_format_supported(const CLIPRDR_FORMAT_LIST* format_list,
+        UINT format_id) {
+
+    /* Search format list for matching ID */
+    for (int i = 0; i < format_list->numFormats; i++) {
+        if (format_list->formats[i].formatId == format_id)
+            return 1;
+    }
+
+    /* If no matching ID, format is not supported */
+    return 0;
+
+}
+
+/**
+ * Callback invoked by the FreeRDP CLIPRDR plugin for received Format List
+ * PDUs. The Format List PDU is sent by the RDP server to indicate that new
+ * clipboard data has been copied and is available for retrieval in the formats
+ * listed. A client wishing to retrieve that data responds with a Format Data
+ * Request PDU.
+ *
+ * @param cliprdr
+ *     The CliprdrClientContext structure used by FreeRDP to handle the CLIPRDR
+ *     channel for the current RDP session.
+ *
+ * @param format_list
+ *     The CLIPRDR_FORMAT_LIST structure representing the Format List PDU that
+ *     was received.
+ *
+ * @return
+ *     CHANNEL_RC_OK (zero) if the PDU was handled successfully, an error code
+ *     (non-zero) otherwise.
+ */
+static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
+        const CLIPRDR_FORMAT_LIST* format_list) {
+
+    /* FreeRDP-specific handlers for CLIPRDR are not assigned, and thus not
+     * callable, until after the relevant guac_rdp_clipboard structure is
+     * allocated and associated with the CliprdrClientContext */
+    guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
+    assert(clipboard != NULL);
 
 Review comment:
   This is more a curiosity than anything, but is there any special reason to using `assert` here instead of `if (clipboard == NULL); return`?  I'm familiar with `assert` in the Java side of the code, but it seems pretty rare in Guacamole's C code-based, so I'm just curious why it goes here and how it changes behavior?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573458354
 
 
   Hm. I will recheck. I really hope this doesn't mean we need to add new configure tests for API differences already...

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573525880
 
 
   OK, the above should be addressed by commit 4282da6. Checking against various Ubuntus, I'm now seeing the following on Bionic:
   
   ```
     CC       channels/libguac_client_rdp_la-rail.lo
   channels/rail.c: In function 'guac_rdp_rail_channel_connected':
   channels/rail.c:167:27: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        rail->ServerHandshake = guac_rdp_rail_handshake;
                              ^
   channels/rail.c:168:29: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        rail->ServerHandshakeEx = guac_rdp_rail_handshake_ex;
                                ^
   cc1: all warnings being treated as errors
   ```
   
   Will see whether the solution here is as simple as before.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573457860
 
 
   I'm not seeing those errors on my end. Which Linux distribution and version of FreeRDP are you building against?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573997083
 
 
   I've manually confirmed on:
   
   * CentOS 7
   * Fedora 29, 30, and 31
   * Debian stable and testing
   * Ubuntu Bionic, Disco, and Eoan
   * Builds of FreeRDP from source using 2.0.0-rc0, 2.0.0-rc1, 2.0.0-rc2, 2.0.0-rc3, 2.0.0-rc4, and master
   
   I *think* we're good to go.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555874
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.c
 ##########
 @@ -0,0 +1,230 @@
+/*
+ * 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 "channels/common-svc.h"
+#include "channels/pipe-svc.h"
+#include "common/list.h"
+#include "rdp.h"
+
+#include <freerdp/settings.h>
+#include <guacamole/client.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/stream.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* pipe_svc) {
+
+    /* Send pipe instruction for the SVC's output stream */
+    guac_protocol_send_pipe(socket, pipe_svc->output_pipe,
+            "application/octet-stream", pipe_svc->svc->name);
+
+}
+
+void guac_rdp_pipe_svc_send_pipes(guac_user* user) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    guac_common_list_lock(rdp_client->available_svc);
+
+    /* Send pipe for each allocated SVC's output stream */
+    guac_common_list_element* current = rdp_client->available_svc->head;
+    while (current != NULL) {
+        guac_rdp_pipe_svc_send_pipe(user->socket, (guac_rdp_pipe_svc*) current->data);
+        current = current->next;
+    }
+
+    guac_common_list_unlock(rdp_client->available_svc);
+
+}
+
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* pipe_svc) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    /* Add to list of available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    guac_common_list_add(rdp_client->available_svc, pipe_svc);
+    guac_common_list_unlock(rdp_client->available_svc);
+
+}
+
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_common_list_element* current;
+    guac_rdp_pipe_svc* found = NULL;
+
+    /* For each available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    current = rdp_client->available_svc->head;
+    while (current != NULL) {
+
+        /* If name matches, found */
+        guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data;
+        if (strcmp(current_svc->svc->name, name) == 0) {
+            found = current_svc;
+            break;
+        }
+
+        current = current->next;
+
+    }
+    guac_common_list_unlock(rdp_client->available_svc);
+
+    return found;
+
+}
+
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name) {
+
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+    guac_common_list_element* current;
+    guac_rdp_pipe_svc* found = NULL;
+
+    /* For each available SVC */
+    guac_common_list_lock(rdp_client->available_svc);
+    current = rdp_client->available_svc->head;
+    while (current != NULL) {
+
+        /* If name matches, remove entry */
+        guac_rdp_pipe_svc* current_svc = (guac_rdp_pipe_svc*) current->data;
+        if (strcmp(current_svc->svc->name, name) == 0) {
+            guac_common_list_remove(rdp_client->available_svc, current);
+            found = current_svc;
+            break;
+        }
+
+        current = current->next;
+
+    }
+    guac_common_list_unlock(rdp_client->available_svc);
+
+    /* Return removed entry, if any */
+    return found;
+
+}
+
+int guac_rdp_pipe_svc_pipe_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* name) {
+
+    guac_rdp_pipe_svc* pipe_svc = guac_rdp_pipe_svc_get(user->client, name);
+
+    /* Fail if no such SVC */
+    if (pipe_svc == NULL) {
+        guac_user_log(user, GUAC_LOG_WARNING, "User requested non-existent "
+                "pipe (no such SVC configured): \"%s\"", name);
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO SUCH PIPE)",
+                GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST);
+        guac_socket_flush(user->socket);
+        return 0;
 
 Review comment:
   Yes. Returning an error code from within an instruction handler aborts the user's connection:
   
   https://github.com/apache/guacamole-server/blob/381ff1a4214e06803f0f587f1ed97cf7e54853e7/src/libguac/user-handshake.c#L164-L177
   
   In this case, the instruction is successfully handled in that the fault has been communicated to the user with an `ack`.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364365088
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available.
+ */
+static void __generate_upload_path(const char* filename, char* path) {
+
+    int i;
+
+    /* Add initial backslash */
+    *(path++) = '\\';
+
+    for (i=1; i<GUAC_RDP_FS_MAX_PATH; i++) {
+
+        /* Get current, stop at end */
+        char c = *(filename++);
+        if (c == '\0')
+            break;
+
+        /* Replace special characters with underscores */
+        if (c == '/' || c == '\\')
+            c = '_';
+
+        *(path++) = c;
+
+    }
+
+    /* Terminate path */
+    *path = '\0';
+
+}
+
+int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* filename) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    int file_id;
+    char file_path[GUAC_RDP_FS_MAX_PATH];
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Translate name */
+    __generate_upload_path(filename, file_path);
+
+    /* Open file */
+    file_id = guac_rdp_fs_open(fs, file_path, GENERIC_WRITE, 0,
+            FILE_OVERWRITE_IF, 0);
+    if (file_id < 0) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (CANNOT OPEN)",
+                GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
+
+    /* Init upload status */
+    guac_rdp_upload_status* upload_status = malloc(sizeof(guac_rdp_upload_status));
+    upload_status->offset = 0;
+    upload_status->file_id = file_id;
+    stream->data = upload_status;
+    stream->blob_handler = guac_rdp_upload_blob_handler;
+    stream->end_handler = guac_rdp_upload_end_handler;
+
+    guac_protocol_send_ack(user->socket, stream, "OK (STREAM BEGIN)",
+            GUAC_PROTOCOL_STATUS_SUCCESS);
+    guac_socket_flush(user->socket);
+    return 0;
+
+}
+
+int guac_rdp_upload_blob_handler(guac_user* user, guac_stream* stream,
+        void* data, int length) {
+
+    int bytes_written;
+    guac_rdp_upload_status* upload_status = (guac_rdp_upload_status*) stream->data;
+
+    /* Get filesystem, return error if no filesystem 0*/
 
 Review comment:
   Arg, it's a vim typo. I must have been moving the cursor to the beginning of the line.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365555946
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must have at least GUAC_RDP_FS_MAX_PATH bytes available.
+ */
+static void __generate_upload_path(const char* filename, char* path) {
+
+    int i;
+
+    /* Add initial backslash */
+    *(path++) = '\\';
+
+    for (i=1; i<GUAC_RDP_FS_MAX_PATH; i++) {
+
+        /* Get current, stop at end */
+        char c = *(filename++);
+        if (c == '\0')
+            break;
+
+        /* Replace special characters with underscores */
+        if (c == '/' || c == '\\')
+            c = '_';
+
+        *(path++) = c;
+
+    }
+
+    /* Terminate path */
+    *path = '\0';
+
+}
+
+int guac_rdp_upload_file_handler(guac_user* user, guac_stream* stream,
+        char* mimetype, char* filename) {
+
+    guac_client* client = user->client;
+    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
+
+    int file_id;
+    char file_path[GUAC_RDP_FS_MAX_PATH];
+
+    /* Get filesystem, return error if no filesystem */
+    guac_rdp_fs* fs = rdp_client->filesystem;
+    if (fs == NULL) {
+        guac_protocol_send_ack(user->socket, stream, "FAIL (NO FS)",
+                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
+        guac_socket_flush(user->socket);
+        return 0;
+    }
 
 Review comment:
   Yep - the error is being returned to the user via the `ack`. The received instruction has otherwise been successfully handled and the rest of the user's connection can continue.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573526953
 
 
   As an aside, I'd like to say it's definitely irksome that "FreeRDP 2.0.0" does not mean the same thing across the various distros, with variances in the API despite otherwise being apparently the same version.
   
   Looks like we should be able to make things flexible enough to build across the board, though.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
jmuehlner commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364067881
 
 

 ##########
 File path: src/protocols/rdp/channels/audio-input.h
 ##########
 @@ -296,18 +292,13 @@ guac_user_end_handler guac_rdp_audio_end_handler;
 /**
  * Adds Guacamole's "guacai" plugin to the list of dynamic virtual channel
  * plugins to be loaded by FreeRDP's "drdynvc" plugin. The plugin will only
- * be loaded once guac_rdp_load_drdynvc() is invoked with the guac_rdp_dvc_list
- * passed to this function. The "guacai" plugin ultimately adds support for the
- * "AUDIO_INPUT"  dynamic virtual channel.
+ * be loaded once the "drdynvc" plugin is loaded. The "guacai" plugin
+ * ultimately adds support for the "AUDIO_INPUT"  dynamic virtual channel.
 
 Review comment:
   Double space in this comment should be changed to a single space
   .

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-574312304
 
 
   > You mentioned needing to deal with conflicts in the master - anything special that we need to worry about for that?
   
   Only that these conflicts are likely to be more difficult to resolve than the usual conflicts. I've tried to summarize the specific issues that conflicted and how to resolve in the issue description. AFAIK, there's no real way to provide a patch which addresses merge conflicts, but I went ahead and performed the merge myself as a test, manually resolving the conflicts, and have been cherry-picking any new commits to that branch since then:
   
   https://github.com/mike-jumper/guacamole-server/tree/freerdp-migrate-2.x-resolve-merge-master
   
   My hope is that the above branch might help in verifying the result of the merge and/or in guiding the resolution of the conflicts.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper edited a comment on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper edited a comment on issue #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#issuecomment-573552512
 
 
   After fixing the RAIL issue, I encountered the following:
   
   ```
   ...
     CC       libguac_client_rdp_la-color.lo
   color.c: In function 'guac_rdp_convert_color':
   color.c:62:16: error: implicit declaration of function 'FreeRDPConvertColor'; did you mean 'ConvertColor'? [-Werror=implicit-function-declaration]
        intermed = FreeRDPConvertColor(intermed, src_format, dst_format,
                   ^~~~~~~~~~~~~~~~~~~
                   ConvertColor
   cc1: all warnings being treated as errors
   ```
   
   Apparently, the `FreeRDPConverColor()` function was formerly known as `ConvertColor()`. It was renamed along with similarly-named functions due to Mac applications using `GetColor()` failing to build because that function clashes with a system function of the same name (see FreeRDP/FreeRDP#3810).
   
   Adding tests to determine the proper function doesn't appear to be an option at the moment, as:
   
   * The necessary include path for FreeRDP is only known via pkg-config and I'm unaware of any way to get autoconf tests to find headers that can only be found when using the `CFLAGS` returned by pkg-config.
   * We can't simply test version numbers because all of these FreeRDP variants have the same version.
   
   I tried addressing this by switching to `ConvertColor()`, which should work due to compatibility macros present in the FreeRDP headers. *But*, I then encountered issues with the glyph callbacks:
   
   ```
     CC       libguac_client_rdp_la-rdp.lo
   rdp.c: In function 'rdp_freerdp_pre_connect':
   rdp.c:155:16: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.Draw = guac_rdp_glyph_draw;
                   ^
   rdp.c:156:21: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.BeginDraw = guac_rdp_glyph_begindraw;
                        ^
   rdp.c:157:19: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
        glyph.EndDraw = guac_rdp_glyph_enddraw;
                      ^
   cc1: all warnings being treated as errors
   ```
   
   In this case, the incompatibility is due to switching from `UINT32` to `INT32` for width and height. At this point, I'm thinking we simply shouldn't support the version of FreeRDP on Bionic. The version of the API in use appears to be unique to Bionic and from before any 2.0.0 release candidate was made.
   
   I've also created some Jenkins jobs to verify the build, so we should be able to better ensure build compatibility going forward:
   
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-centos/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-fedora/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-debian/
   * https://builds.apache.org/view/E-G/view/Guacamole/job/guacamole-server-ubuntu/
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364697576
 
 

 ##########
 File path: src/protocols/rdp/channels/pipe-svc.h
 ##########
 @@ -0,0 +1,188 @@
+/*
+ * 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 GUAC_RDP_CHANNELS_PIPE_SVC_H
+#define GUAC_RDP_CHANNELS_PIPE_SVC_H
+
+#include "channels/common-svc.h"
+
+#include <freerdp/freerdp.h>
+#include <freerdp/svc.h>
+#include <guacamole/client.h>
+#include <guacamole/stream.h>
+#include <guacamole/socket.h>
+#include <guacamole/user.h>
+#include <winpr/wtsapi.h>
+
+/**
+ * The maximum number of bytes to allow within each channel name, including
+ * null terminator.
+ */
+#define GUAC_RDP_SVC_MAX_LENGTH 8
+
+/**
+ * Structure describing a static virtual channel and a corresponding Guacamole
+ * pipe stream;
+ */
+typedef struct guac_rdp_pipe_svc {
+
+    /**
+     * The output pipe, opened when the RDP server receives a connection to
+     * the static channel.
+     */
+    guac_stream* output_pipe;
+
+    /**
+     * The underlying static channel. Data written to this SVC by the RDP
+     * server will be forwarded along the pipe stream to the Guacamole client,
+     * and data written to the pipe stream by the Guacamole client will be
+     * forwarded along the SVC to the RDP server.
+     */
+    guac_rdp_common_svc* svc;
+
+} guac_rdp_pipe_svc;
+
+/**
+ * Initializes arbitrary static virtual channel (SVC) support for RDP, handling
+ * communication for the SVC having the given name. Data sent from within the
+ * RDP session using this channel will be sent along an identically-named pipe
+ * stream to the Guacamole client, and data sent along a pipe stream having the
+ * same name will be written to the SVC and received within the RDP session. If
+ * failures occur while loading the plugin, messages noting the specifics of
+ * those failures will be logged, and support for the given channel will not be
+ * functional.
+ *
+ * This MUST be called within the PreConnect callback of the freerdp instance
+ * for static virtual channel support to be loaded.
+ *
+ * @param context
+ *     The rdpContext associated with the FreeRDP side of the RDP connection.
+ *
+ * @param name
+ *     The name of the SVC which should be handled.
+ */
+void guac_rdp_pipe_svc_load_plugin(rdpContext* context, char* name);
+
+/**
+ * Sends the "pipe" instruction describing the given static virtual channel
+ * along the given socket. This pipe instruction will relate the SVC's
+ * underlying output stream with the SVC's name and the mimetype
+ * "application/octet-stream".
+ *
+ * @param socket
+ *     The socket along which the "pipe" instruction should be sent.
+ *
+ * @param svc
+ *     The static virtual channel that the "pipe" instruction should describe.
+ */
+void guac_rdp_pipe_svc_send_pipe(guac_socket* socket, guac_rdp_pipe_svc* svc);
+
+/**
+ * Sends the "pipe" instructions describing all static virtual channels
+ * available to the given user along that user's socket. Each pipe instruction
+ * will relate the associated SVC's underlying output stream with the SVC's
+ * name and the mimetype "application/octet-stream".
+ *
+ * @param user
+ *     The user to send the "pipe" instructions to.
+ */
+void guac_rdp_pipe_svc_send_pipes(guac_user* user);
+
+/**
+ * Add the given SVC to the list of all available SVCs. This function must be
+ * invoked after the SVC is connected for inbound pipe streams having that
+ * SVC's name to result in received data being sent into the RDP session.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param svc
+ *     The static virtual channel to add to the list of all such channels
+ *     available.
+ */
+void guac_rdp_pipe_svc_add(guac_client* client, guac_rdp_pipe_svc* svc);
+
+/**
+ * Retrieve the SVC with the given name from the list stored in the client. The
+ * requested SVC must previously have been added using guac_rdp_pipe_svc_add().
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to retrieve.
+ *
+ * @return
+ *     The static virtual channel with the given name, or NULL if no such
+ *     virtual channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_get(guac_client* client, const char* name);
+
+/**
+ * Removes the SVC with the given name from the list stored in the client.
+ * Inbound pipe streams having the given name will no longer be routed to the
+ * associated SVC.
+ *
+ * @param client
+ *     The guac_client associated with the current RDP session.
+ *
+ * @param name
+ *     The name of the static virtual channel to remove.
+ *
+ * @return
+ *     The static virtual channel that was removed, or NULL if no such virtual
+ *     channel exists.
+ */
+guac_rdp_pipe_svc* guac_rdp_pipe_svc_remove(guac_client* client, const char* name);
+
+/**
+ * Handler for "blob" instructions which automatically writes received data to
+ * the associated SVC using guac_rdp_pipe_svc_write().
+ */
+guac_user_blob_handler guac_rdp_pipe_svc_blob_handler;
+
+/**
+ * Handler for "pipe" instructions which automatically prepares received pipe
+ * streams to automatically write received blobs to the SVC having the same
 
 Review comment:
   Nitpick, but this feels like a bit to much automatically for two lines :-).

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
necouchman commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r365481469
 
 

 ##########
 File path: src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-dir-info.h
 ##########
 @@ -17,58 +17,76 @@
  * under the License.
  */
 
-
-#ifndef __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
-#define __GUAC_RDPDR_FS_MESSAGES_DIR_INFO_H
+#ifndef GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
+#define GUAC_RDP_CHANNELS_RDPDR_FS_MESSAGES_DIR_INFO_H
 
 /**
  * Handlers for directory queries received over the RDPDR channel via the
  * IRP_MJ_DIRECTORY_CONTROL major function and the IRP_MN_QUERY_DIRECTORY minor
  * function.
  *
- * @file rdpdr_fs_messages_dir_info.h
+ * @file rdpdr-fs-messages-dir-info.h
  */
 
-#include "config.h"
-
-#include "rdpdr_service.h"
+#include "channels/common-svc.h"
+#include "channels/rdpdr/rdpdr.h"
 
-#ifdef ENABLE_WINPR
 #include <winpr/stream.h>
-#else
-#include "compat/winpr-stream.h"
-#endif
+
+/**
+ * Handler for Device I/O Requests which query information about the files
+ * within a directory.
+ *
+ * @param svc
+ *     The guac_rdp_common_svc representing the static virtual channel being
+ *     used for RDPDR.
+ *
+ * @param device
+ *     The guac_rdpdr_device of the relevant device, as dictated by the
+ *     deviceId field of common RDPDR header within the received PDU. Within
 
 Review comment:
   "the common RDPDR header" or "RDPDR headers", perhaps?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364986388
 
 

 ##########
 File path: src/protocols/rdp/plugins/channels.c
 ##########
 @@ -0,0 +1,129 @@
+/*
+ * 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 "plugins/channels.h"
+
+#include <freerdp/channels/channels.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/addin.h>
+#include <winpr/wtypes.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+int guac_rdp_wrapped_entry_ex_count = 0;
+
+int guac_rdp_wrapped_entry_count = 0;
+
+PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
+
+PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(PVIRTUALCHANNELENTRYEX entry_ex) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS)
+        return entry_ex;
+
+    /* Generate wrapped version of provided entry point */
+    PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
+    guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
+    guac_rdp_wrapped_entry_ex_count++;
+
+    return wrapper;
+
+}
+
+PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(PVIRTUALCHANNELENTRY entry) {
+
+    /* Do not wrap if there is insufficient space to store the wrapped
+     * function */
+    if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS)
 
 Review comment:
   OK - I went ahead and refactored `guac_freerdp_channels_load_plugin()` such that it accepts a `rdpContext` instead, allowing warnings to be logged if plugins may fail to load due to limits being reached. It's no longer a true drop-in replacement, but it really doesn't need to be.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [guacamole-server] mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x

Posted by GitBox <gi...@apache.org>.
mike-jumper commented on a change in pull request #243: GUACAMOLE-249: Migrate to FreeRDP 2.x
URL: https://github.com/apache/guacamole-server/pull/243#discussion_r364973163
 
 

 ##########
 File path: src/protocols/rdp/upload.c
 ##########
 @@ -0,0 +1,236 @@
+/*
+ * 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 "fs.h"
+#include "rdp.h"
+#include "upload.h"
+
+#include <guacamole/client.h>
+#include <guacamole/object.h>
+#include <guacamole/protocol.h>
+#include <guacamole/socket.h>
+#include <guacamole/stream.h>
+#include <guacamole/user.h>
+#include <winpr/nt.h>
+
+#include <stdlib.h>
+
+/**
+ * Writes the given filename to the given upload path, sanitizing the filename
+ * and translating the filename to the root directory.
+ *
+ * @param filename
+ *     The filename to sanitize and move to the root directory.
+ *
+ * @param path
+ *     A pointer to a buffer which should receive the sanitized path. The
+ *     buffer must hav at least GUAC_RDP_FS_MAX_PATH bytes available.
 
 Review comment:
   Fixed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services