Skip to content

Commit

Permalink
GUACAMOLE-1026: Add support for FreeRDP3.
Browse files Browse the repository at this point in the history
  • Loading branch information
aleitner committed May 22, 2024
1 parent 3ad3b04 commit 37a5368
Show file tree
Hide file tree
Showing 21 changed files with 636 additions and 119 deletions.
201 changes: 176 additions & 25 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,12 @@ then
fi

#
# FreeRDP 2 (libfreerdp2, libfreerdp-client2, and libwinpr2)
# FreeRDP (libfreerdpX, libfreerdp-clientX, and libwinprX)
#

have_freerdp2=disabled
FREERDP2_PLUGIN_DIR=
freerdp_version=
have_freerdp=
FREERDP_PLUGIN_DIR=

AC_ARG_WITH([rdp],
[AS_HELP_STRING([--with-rdp],
Expand All @@ -664,29 +665,46 @@ AC_ARG_WITH([rdp],
AC_ARG_WITH(freerdp_plugin_dir,
[AS_HELP_STRING([--with-freerdp-plugin-dir=<path>],
[install FreeRDP plugins to the given directory @<:@default=check@:>@])
],FREERDP2_PLUGIN_DIR=$withval)
],FREERDP_PLUGIN_DIR=$withval)

# Preserve CPPFLAGS so it can be restored later, following the addition of
# options specific to FreeRDP tests
OLDCPPFLAGS="$CPPFLAGS"

if test "x$with_rdp" != "xno"
then
have_freerdp2=yes
freerdp_version=3
have_freerdp=yes
PKG_CHECK_MODULES([RDP], [freerdp3 freerdp-client3 winpr3],
[CPPFLAGS="${RDP_CFLAGS} -Werror $CPPFLAGS"]
[AS_IF([test "x${FREERDP_PLUGIN_DIR}" = "x"],
[FREERDP_PLUGIN_DIR="`$PKG_CONFIG --variable=libdir freerdp3`/freerdp3"])],
[AC_MSG_WARN([
--------------------------------------------
Unable to find FreeRDP3 (libfreerdp3 / libfreerdp-client3 / libwinpr3).
Checking for FreeRDP2.
--------------------------------------------])
have_freerdp=no])
fi

if test "x$with_rdp" != "xno" -a "x${have_freerdp}" = "xno"
then
freerdp_version=2
have_freerdp=yes
PKG_CHECK_MODULES([RDP], [freerdp2 freerdp-client2 winpr2],
[CPPFLAGS="${RDP_CFLAGS} -Werror $CPPFLAGS"]
[AS_IF([test "x${FREERDP2_PLUGIN_DIR}" = "x"],
[FREERDP2_PLUGIN_DIR="`$PKG_CONFIG --variable=libdir freerdp2`/freerdp2"])],
[AS_IF([test "x${FREERDP_PLUGIN_DIR}" = "x"],
[FREERDP_PLUGIN_DIR="`$PKG_CONFIG --variable=libdir freerdp2`/freerdp2"])],
[AC_MSG_WARN([
--------------------------------------------
Unable to find FreeRDP (libfreerdp2 / libfreerdp-client2 / libwinpr2)
Unable to find FreeRDP2 (libfreerdp2 / libfreerdp-client2 / libwinpr2)
RDP will be disabled.
--------------------------------------------])
have_freerdp2=no])
have_freerdp=no])
fi

# Available color conversion functions
if test "x$have_freerdp2" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc3 and older referred to FreeRDPConvertColor() as
Expand All @@ -708,7 +726,7 @@ AC_ARG_ENABLE(allow_freerdp_snapshots,
[allow building against unknown development snapshots of FreeRDP])
],allow_freerdp_snapshots=yes)

if test "x${have_freerdp2}" = "xyes" -a "x${allow_freerdp_snapshots}" != "xyes"
if test "x${have_freerdp}" = "xyes" -a "x${allow_freerdp_snapshots}" != "xyes"
then

AC_MSG_CHECKING([whether FreeRDP appears to be a development version])
Expand Down Expand Up @@ -736,7 +754,7 @@ then
fi

# Variation in memory internal allocation/free behavior for bitmaps
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc0 and older automatically free rdpBitmap and its
Expand All @@ -760,7 +778,7 @@ then
fi

# Variation in memory internal allocation/free behavior for channel streams
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc3 through 2.0.0-rc4 automatically free the wStream
Expand All @@ -782,7 +800,7 @@ then
fi

# Glyph callback variants
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc3 and older used UINT32 for integer parameters to all
Expand Down Expand Up @@ -815,7 +833,7 @@ then
fi

# CLIPRDR callback variants
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc3 and older did not use const for CLIPRDR callbacks
Expand Down Expand Up @@ -845,7 +863,7 @@ then
fi

# RAIL callback variants
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then

# FreeRDP 2.0.0-rc3 and older did not use const for RAIL callbacks
Expand Down Expand Up @@ -875,7 +893,7 @@ then
fi

# Support for receiving unannounced orders from the RDP server
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_MEMBERS([rdpSettings.AllowUnanouncedOrdersFromServer],,
[AC_MSG_WARN([
Expand All @@ -891,17 +909,151 @@ fi

# Updated certificate verification callback (introduced with 2.0.0, not present
# in 2.0.0-rc4 or earlier)
if test "x${have_freerdp2}" = "xyes"
if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_MEMBERS([freerdp.VerifyCertificateEx],,,
[[#include <freerdp/freerdp.h>]])
[[#include <freerdp/freerdp.h>]])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_DECLS([winpr_aligned_free],
[AC_DEFINE([HAVE_WINPR_ALIGNED],,
[Defined if winpr_aligned_free() and winpr_aligned_malloc() are available])],,
[#include <winpr/crt.h>])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_MSG_CHECKING([whether CLIPRDR structs have a common CLIPRDR_HEADER])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/client/cliprdr.h>
int main() {
CLIPRDR_FORMAT_LIST list;
list.common.msgType = 0;
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([HAVE_CLIPRDR_HEADER],,
[Defined if CLIPRDR structs have a common CLIPRDR_HEADER])],
[AC_MSG_RESULT([no])])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_DECLS([FreeRDPReadColor],
[AC_DEFINE([USE_UPDATED_RW_COLOR_FUNCS],,
[Defined if FreeRDPReadColor() and FreeRDPWriteColor() are available])],,
[#include <freerdp/codec/color.h>])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_DECLS([freerdp_settings_set_pointer],
[AC_DEFINE([HAVE_SETTERS_GETTERS],,
[Defined if freerdp_settings_set_pointer is available])],,
[#include <freerdp/settings.h>])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_MSG_CHECKING([whether freerdp structs have a context])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/freerdp.h>
int main() {
freerdp* instance = freerdp_new();
/* We cast to void to prevent unused variable warnings */
(void)instance->context->input;
(void)instance->context->settings;
freerdp_free(instance);
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([FREERDP_HAS_CONTEXT],,
[FreeRDP structs have a context])],
[AC_MSG_RESULT([no])])
fi

if test "x${have_freerdp}" = "xyes"
then
AC_CHECK_DECL([freerdp_shall_disconnect_context],
[AC_DEFINE([HAVE_DISCONNECT_CONTEXT],,
[Defined if 'freerdp_shall_disconnect_context' is available in FreeRDP])],,
[#include <freerdp/freerdp.h>])
fi
if test "x${have_freerdp}" = "xyes"
then
# Check whether FreeRDP 3.x requires const for GetPluginData
AC_MSG_CHECKING([whether GetPluginData requires const for the returned args])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/dvc.h>
int main() {
IDRDYNVC_ENTRY_POINTS test_entry_points;
const ADDIN_ARGV* args = test_entry_points.GetPluginData(&test_entry_points);
(void)args;
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([PLUGIN_DATA_CONST],,
[Defined if GetPluginData returns a pointer to a const ADDIN_ARGV])],
[AC_MSG_RESULT([no])])
fi

if test "x${have_freerdp}" = "xyes"
then
# Check whether glyph.New expects a const rdpGlyph* parameter
AC_MSG_CHECKING([whether glyph.New expects a const rdpGlyph* parameter])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/graphics.h>
BOOL mock_glyph_new(rdpContext* context, const rdpGlyph* glyph) {
return TRUE;
}
int main() {
rdpGlyph* glyph = (rdpGlyph*) malloc(sizeof(rdpGlyph));
glyph->New = mock_glyph_new;
free(glyph);
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([RDP_GLYPH_NEW_REQUIRES_CONST],,
[Defined if glyph.New expects a const rdpGlyph* parameter])],
[AC_MSG_RESULT([no])])
fi

if test "x${have_freerdp}" = "xyes"
then
# Check whether pointer.Set expects a const rdpPointer* parameter
AC_MSG_CHECKING([whether pointer.Set expects a const rdpPointer* parameter])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/graphics.h>
BOOL mock_pointer_set(rdpContext* context, const rdpPointer* pointer) {
return TRUE;
}
int main() {
rdpPointer* pointer = (rdpPointer*) malloc(sizeof(rdpPointer));
pointer->Set = mock_pointer_set;
free(pointer);
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([RDP_POINTER_SET_REQUIRES_CONST],,
[Defined if pointer.Set expects a const rdpPointer* parameter])],
[AC_MSG_RESULT([no])])
fi

# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing
CPPFLAGS="$OLDCPPFLAGS"

AC_SUBST(FREERDP2_PLUGIN_DIR)
AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp2}" = "xyes"])
AC_SUBST(FREERDP_PLUGIN_DIR)
AM_CONDITIONAL([ENABLE_RDP], [test "x${have_freerdp}" = "xyes"])

#
# libssh2
Expand Down Expand Up @@ -1237,7 +1389,7 @@ AM_COND_IF([ENABLE_SYSTEMD], [build_systemd="${systemd_dir}"], [build_systemd=no
# FreeRDP plugins
#

AM_COND_IF([ENABLE_RDP], [build_rdp_plugins="${FREERDP2_PLUGIN_DIR}"], [build_rdp_plugins=no])
AM_COND_IF([ENABLE_RDP], [build_rdp_plugins="${FREERDP_PLUGIN_DIR}"], [build_rdp_plugins=no])

#
# Display summary
Expand All @@ -1250,7 +1402,7 @@ $PACKAGE_NAME version $PACKAGE_VERSION

Library status:

freerdp2 ............ ${have_freerdp2}
freerdp${freerdp_version} ............ ${have_freerdp}
pango ............... ${have_pango}
libavcodec .......... ${have_libavcodec}
libavformat ......... ${have_libavformat}
Expand Down Expand Up @@ -1280,10 +1432,9 @@ $PACKAGE_NAME version $PACKAGE_VERSION
guacenc .... ${build_guacenc}
guaclog .... ${build_guaclog}

FreeRDP plugins: ${build_rdp_plugins}
FreeRDP${freerdp_version} plugins: ${build_rdp_plugins}
Init scripts: ${build_init}
Systemd units: ${build_systemd}

Type \"make\" to compile $PACKAGE_NAME.
"

33 changes: 32 additions & 1 deletion src/libguac/guacamole/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,38 @@ size_t guac_strlcat(char* restrict dest, const char* restrict src, size_t n);
*/
char* guac_strnstr(const char *haystack, const char *needle, size_t len);

/**
* Duplicates up to the given number of characters from the provided string,
* returning a newly-allocated string containing the copied contents. The
* provided string must be null-terminated, and only the first 'n' characters
* will be considered for duplication, or the full string length if it is
* shorter than 'n'. The memory block for the newly-allocated string will
* include enough space for these characters, as well as for the null
* terminator.
*
* The pointer returned by guac_strndup() SHOULD be freed with a subsequent call
* to guac_mem_free(), but MAY instead be freed with a subsequent call to free().
*
* This function behaves similarly to the POSIX strndup() function, except that
* NULL will be returned if the provided string is NULL or if memory allocation
* fails. Also, the length of the string to be duplicated will be checked to
* prevent overflow if adding space for the null terminator.
*
* @param str
* The string of which up to the first 'n' characters should be duplicated
* as a newly-allocated string. If 'n' exceeds the length of the string,
* the entire string is duplicated.
*
* @param n
* The maximum number of characters to duplicate from the given string.
*
* @return
* A newly-allocated string containing up to the first 'n' characters from
* the given string, including a terminating null byte, or NULL if the
* provided string was NULL or if memory allocation fails.
*/
char* guac_strndup(const char* str, size_t n);

/**
* Duplicates the given string, returning a newly-allocated string containing
* the same contents. The provided string must be null-terminated. The size of
Expand Down Expand Up @@ -202,4 +234,3 @@ size_t guac_strljoin(char* restrict dest, const char* restrict const* elements,
int nmemb, const char* restrict delim, size_t n);

#endif

Loading

0 comments on commit 37a5368

Please sign in to comment.