diff --git a/CMakeLists.txt b/CMakeLists.txt index 967304e..930eee1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.6.0") +set(RAW_VERSION_STRING "2.6.1") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -111,6 +111,24 @@ else() endif() message("FREERDP_VERSION=${FREERDP_VERSION_FULL}") +if(EXISTS "${PROJECT_SOURCE_DIR}/.source_version" ) + file(READ ${PROJECT_SOURCE_DIR}/.source_version GIT_REVISION) + + string(STRIP ${GIT_REVISION} GIT_REVISION) +elseif(USE_VERSION_FROM_GIT_TAG) + git_get_exact_tag(GIT_REVISION --tags --always) + + if (${GIT_REVISION} STREQUAL "n/a") + git_rev_parse (GIT_REVISION --short) + endif() +endif() + +if (NOT GIT_REVISION) + set(GIT_REVISION ${FREERDP_VERSION}) +endif() + +message(STATUS "Git Revision ${GIT_REVISION}") + set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/") # Compatibility options @@ -147,25 +165,11 @@ if(CCACHE AND WITH_CCACHE) endif() endif(CCACHE AND WITH_CCACHE) -if(EXISTS "${CMAKE_SOURCE_DIR}/.source_version" ) - file(READ ${CMAKE_SOURCE_DIR}/.source_version GIT_REVISION) - - string(STRIP ${GIT_REVISION} GIT_REVISION) -else() - git_get_exact_tag(GIT_REVISION --tags --always) - - if (${GIT_REVISION} STREQUAL "n/a") - git_rev_parse (GIT_REVISION --short) - endif() -endif() - if(CMAKE_CROSSCOMPILING) SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) endif(CMAKE_CROSSCOMPILING) # /Allow to search the host machine for git/ccache -message(STATUS "Git Revision ${GIT_REVISION}") - # Turn on solution folders (2.8.4+) set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/ChangeLog b/ChangeLog index b7c7c4f..5d32697 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +# 2022-03-07 Version 2.6.1 + +Noteworthy changes: +* Decreased logging verbosity, now freerdp is much less verbose by default + +Fixed issues: +* Backported freerdp_abort_connect during freerdp_connect fix (#7700) +* Backported improved version dection see docs/version_detection.md for details +* Backported various rdpsnd fixes (#7695) + +Important notes: + +For a complete and detailed change log since the last release run: +git log 2.0.0..2.6.1 + # 2022-02-22 Version 2.6.0 Noteworthy changes: diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index c6d193e..ebdf931 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -182,7 +182,7 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd) rdpsnd->ClientFormats = audio_formats_new(rdpsnd->NumberOfServerFormats); - if (!rdpsnd->ClientFormats) + if (!rdpsnd->ClientFormats || !rdpsnd->device) return; for (index = 0; index < rdpsnd->NumberOfServerFormats; index++) @@ -213,6 +213,10 @@ static UINT rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd) UINT16 length; UINT32 dwVolume; UINT16 wNumberOfFormats; + + if (!rdpsnd->device || (!rdpsnd->dynamic && (rdpsnd->OpenHandle == 0))) + return CHANNEL_RC_INITIALIZATION_ERROR; + dwVolume = IFCALLRESULT(0, rdpsnd->device->GetVolume, rdpsnd->device); wNumberOfFormats = rdpsnd->NumberOfClientFormats; length = 4 + 20; @@ -695,7 +699,7 @@ static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd) */ static UINT rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s) { - BOOL rc; + BOOL rc = FALSE; UINT32 dwVolume; if (Stream_GetRemainingLength(s) < 4) @@ -704,7 +708,8 @@ static UINT rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s) Stream_Read_UINT32(s, dwVolume); WLog_Print(rdpsnd->log, WLOG_DEBUG, "%s Volume: 0x%08" PRIX32 "", rdpsnd_is_dyn_str(rdpsnd->dynamic), dwVolume); - rc = IFCALLRESULT(FALSE, rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); + if (rdpsnd->device) + rc = IFCALLRESULT(FALSE, rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); if (!rc) { @@ -1182,38 +1187,51 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd, LPVOID UINT32 dataLength) { UINT32 status; + DWORD opened = 0; WINPR_UNUSED(pData); WINPR_UNUSED(dataLength); status = rdpsnd->channelEntryPoints.pVirtualChannelOpenEx( - rdpsnd->InitHandle, &rdpsnd->OpenHandle, rdpsnd->channelDef.name, - rdpsnd_virtual_channel_open_event_ex); + rdpsnd->InitHandle, &opened, rdpsnd->channelDef.name, rdpsnd_virtual_channel_open_event_ex); if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "%s pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", rdpsnd_is_dyn_str(rdpsnd->dynamic), WTSErrorToString(status), status); - return status; + goto fail; } - rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); - - if (!rdpsnd->dsp_context) + if (rdpsnd_process_connect(rdpsnd) != CHANNEL_RC_OK) goto fail; - rdpsnd->pool = StreamPool_New(TRUE, 4096); - - if (!rdpsnd->pool) - goto fail; - - return rdpsnd_process_connect(rdpsnd); + rdpsnd->OpenHandle = opened; + return CHANNEL_RC_OK; fail: - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Free(rdpsnd->pool); + if (opened != 0) + rdpsnd->channelEntryPoints.pVirtualChannelCloseEx(rdpsnd->InitHandle, opened); return CHANNEL_RC_NO_MEMORY; } +static void cleanup_internals(rdpsndPlugin* rdpsnd) +{ + if (!rdpsnd) + return; + + if (rdpsnd->pool) + StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); + + audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); + audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); + + rdpsnd->NumberOfClientFormats = 0; + rdpsnd->ClientFormats = NULL; + rdpsnd->NumberOfServerFormats = 0; + rdpsnd->ServerFormats = NULL; + + rdpsnd->data_in = NULL; +} + /** * Function description * @@ -1223,33 +1241,25 @@ static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) { UINT error; - if (rdpsnd->OpenHandle == 0) - return CHANNEL_RC_OK; - - if (rdpsnd->device) - IFCALL(rdpsnd->device->Close, rdpsnd->device); - - error = - rdpsnd->channelEntryPoints.pVirtualChannelCloseEx(rdpsnd->InitHandle, rdpsnd->OpenHandle); - - if (CHANNEL_RC_OK != error) + if (rdpsnd->OpenHandle != 0) { - WLog_ERR(TAG, "%s pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", - rdpsnd_is_dyn_str(rdpsnd->dynamic), WTSErrorToString(error), error); - return error; + DWORD opened = rdpsnd->OpenHandle; + rdpsnd->OpenHandle = 0; + + if (rdpsnd->device) + IFCALL(rdpsnd->device->Close, rdpsnd->device); + + error = rdpsnd->channelEntryPoints.pVirtualChannelCloseEx(rdpsnd->InitHandle, opened); + + if (CHANNEL_RC_OK != error) + { + WLog_ERR(TAG, "%s pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", + rdpsnd_is_dyn_str(rdpsnd->dynamic), WTSErrorToString(error), error); + return error; + } } - rdpsnd->OpenHandle = 0; - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); - StreamPool_Free(rdpsnd->pool); - - audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); - rdpsnd->NumberOfClientFormats = 0; - rdpsnd->ClientFormats = NULL; - audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); - rdpsnd->NumberOfServerFormats = 0; - rdpsnd->ServerFormats = NULL; + cleanup_internals(rdpsnd); if (rdpsnd->device) { @@ -1266,6 +1276,36 @@ static void _queue_free(void* obj) Stream_Release(s); } +static void free_internals(rdpsndPlugin* rdpsnd) +{ + if (!rdpsnd) + return; + + freerdp_dsp_context_free(rdpsnd->dsp_context); + StreamPool_Free(rdpsnd->pool); + rdpsnd->pool = NULL; + rdpsnd->dsp_context = NULL; +} + +static BOOL allocate_internals(rdpsndPlugin* rdpsnd) +{ + if (!rdpsnd->pool) + { + rdpsnd->pool = StreamPool_New(TRUE, 4096); + if (!rdpsnd->pool) + return FALSE; + } + + if (!rdpsnd->dsp_context) + { + rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); + if (!rdpsnd->dsp_context) + return FALSE; + } + + return TRUE; +} + static DWORD WINAPI play_thread(LPVOID arg) { UINT error = CHANNEL_RC_OK; @@ -1311,17 +1351,22 @@ static UINT rdpsnd_virtual_channel_event_initialized(rdpsndPlugin* rdpsnd) if (!rdpsnd->queue) return CHANNEL_RC_NO_MEMORY; + if (!allocate_internals(rdpsnd)) + return CHANNEL_RC_NO_MEMORY; + rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL); if (!rdpsnd->thread) return CHANNEL_RC_INITIALIZATION_ERROR; + return CHANNEL_RC_OK; } -static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) +void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) { if (rdpsnd) { - MessageQueue_PostQuit(rdpsnd->queue, 0); + if (rdpsnd->queue) + MessageQueue_PostQuit(rdpsnd->queue, 0); if (rdpsnd->thread) { WaitForSingleObject(rdpsnd->thread, INFINITE); @@ -1329,6 +1374,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) } MessageQueue_Free(rdpsnd->queue); + free_internals(rdpsnd); audio_formats_free(rdpsnd->fixed_format, 1); free(rdpsnd->subsystem); free(rdpsnd->device_name); @@ -1370,6 +1416,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event_ex(LPVOID lpUserParam, L case CHANNEL_EVENT_TERMINATED: rdpsnd_virtual_channel_event_terminated(plugin); + plugin = NULL; break; case CHANNEL_EVENT_ATTACHED: @@ -1401,6 +1448,27 @@ rdpContext* freerdp_rdpsnd_get_context(rdpsndPlugin* plugin) return plugin->rdpcontext; } +static rdpsndPlugin* allocatePlugin(void) +{ + rdpsndPlugin* rdpsnd = (rdpsndPlugin*)calloc(1, sizeof(rdpsndPlugin)); + if (!rdpsnd) + goto fail; + + rdpsnd->fixed_format = audio_format_new(); + if (!rdpsnd->fixed_format) + goto fail; + rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); + if (!rdpsnd->log) + goto fail; + + rdpsnd->attached = TRUE; + return rdpsnd; + +fail: + if (rdpsnd) + audio_format_free(rdpsnd->fixed_format); + return NULL; +} /* rdpsnd is always built-in */ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) { @@ -1411,12 +1479,11 @@ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, if (!pEntryPoints) return FALSE; - rdpsnd = (rdpsndPlugin*)calloc(1, sizeof(rdpsndPlugin)); + rdpsnd = allocatePlugin(); if (!rdpsnd) return FALSE; - rdpsnd->attached = TRUE; rdpsnd->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP; sprintf_s(rdpsnd->channelDef.name, ARRAYSIZE(rdpsnd->channelDef.name), "rdpsnd"); pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; @@ -1427,15 +1494,6 @@ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, rdpsnd->rdpcontext = pEntryPointsEx->context; } - rdpsnd->fixed_format = audio_format_new(); - - if (!rdpsnd->fixed_format) - { - free(rdpsnd); - return FALSE; - } - - rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); rdpsnd->InitHandle = pInitHandle; @@ -1447,7 +1505,7 @@ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, { WLog_ERR(TAG, "%s pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", rdpsnd_is_dyn_str(FALSE), WTSErrorToString(rc), rc); - free(rdpsnd); + rdpsnd_virtual_channel_event_terminated(rdpsnd); return FALSE; } @@ -1459,19 +1517,10 @@ static UINT rdpsnd_on_open(IWTSVirtualChannelCallback* pChannelCallback) RDPSND_CHANNEL_CALLBACK* callback = (RDPSND_CHANNEL_CALLBACK*)pChannelCallback; rdpsndPlugin* rdpsnd = (rdpsndPlugin*)callback->plugin; - rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); - if (!rdpsnd->dsp_context) - goto fail; - - rdpsnd->pool = StreamPool_New(TRUE, 4096); - if (!rdpsnd->pool) - goto fail; + if (!allocate_internals(rdpsnd)) + return ERROR_OUTOFMEMORY; return rdpsnd_process_connect(rdpsnd); -fail: - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Free(rdpsnd->pool); - return CHANNEL_RC_NO_MEMORY; } static UINT rdpsnd_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) @@ -1479,7 +1528,9 @@ static UINT rdpsnd_on_data_received(IWTSVirtualChannelCallback* pChannelCallback RDPSND_CHANNEL_CALLBACK* callback = (RDPSND_CHANNEL_CALLBACK*)pChannelCallback; rdpsndPlugin* plugin; wStream* copy; - size_t len = Stream_GetRemainingLength(data); + size_t len; + + len = Stream_GetRemainingLength(data); if (!callback || !callback->plugin) return ERROR_INVALID_PARAMETER; @@ -1508,22 +1559,16 @@ static UINT rdpsnd_on_close(IWTSVirtualChannelCallback* pChannelCallback) if (rdpsnd->device) IFCALL(rdpsnd->device->Close, rdpsnd->device); - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); - StreamPool_Free(rdpsnd->pool); - audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); - rdpsnd->NumberOfClientFormats = 0; - rdpsnd->ClientFormats = NULL; - audio_formats_free(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats); - rdpsnd->NumberOfServerFormats = 0; - rdpsnd->ServerFormats = NULL; + cleanup_internals(rdpsnd); + if (rdpsnd->device) { IFCALL(rdpsnd->device->Free, rdpsnd->device); rdpsnd->device = NULL; } + free_internals(rdpsnd); free(pChannelCallback); return CHANNEL_RC_OK; } @@ -1622,7 +1667,7 @@ UINT rdpsnd_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) if (!rdpsnd) { - rdpsnd = (rdpsndPlugin*)calloc(1, sizeof(rdpsndPlugin)); + rdpsnd = allocatePlugin(); if (!rdpsnd) { WLog_ERR(TAG, "%s calloc failed!", rdpsnd_is_dyn_str(TRUE)); @@ -1633,14 +1678,10 @@ UINT rdpsnd_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) rdpsnd->iface.Connected = NULL; rdpsnd->iface.Disconnected = NULL; rdpsnd->iface.Terminated = rdpsnd_plugin_terminated; - rdpsnd->attached = TRUE; rdpsnd->dynamic = TRUE; - rdpsnd->fixed_format = audio_format_new(); - if (!rdpsnd->fixed_format) - goto fail; - rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client"); - rdpsnd->channelEntryPoints.pExtendedData = pEntryPoints->GetPluginData(pEntryPoints); + /* user data pointer is not const, cast to avoid warning. */ + rdpsnd->channelEntryPoints.pExtendedData = (void*)pEntryPoints->GetPluginData(pEntryPoints); error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpsnd", &rdpsnd->iface); } @@ -1650,8 +1691,5 @@ UINT rdpsnd_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) return CHANNEL_RC_BAD_CHANNEL; } - return error; -fail: - rdpsnd_plugin_terminated(&rdpsnd->iface); return error; } diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4bdad53..24a03d4 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1461,7 +1461,7 @@ static BOOL handle_window_events(freerdp* instance) { if (!xf_process_x_events(instance)) { - WLog_INFO(TAG, "Closed from X11"); + WLog_DBG(TAG, "Closed from X11"); return FALSE; } } diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index e08048f..85a1736 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -1570,7 +1570,7 @@ xf_cliprdr_server_format_data_response(CliprdrClientContext* context, { if (SrcSize == 0) { - WLog_INFO(TAG, "skipping, empty data detected!!!"); + WLog_DBG(TAG, "skipping, empty data detected!"); free(clipboard->respond); clipboard->respond = NULL; return CHANNEL_RC_OK; diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 9bb417e..50a52e0 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -152,8 +152,8 @@ int xf_input_init(xfContext* xfc, Window window) if (xfc->context.settings->MultiTouchInput) { - WLog_INFO(TAG, "%s (%d) \"%s\" id: %d", xf_input_get_class_string(class->type), - class->type, dev->name, dev->deviceid); + WLog_DBG(TAG, "%s (%d) \"%s\" id: %d", xf_input_get_class_string(class->type), + class->type, dev->name, dev->deviceid); } evmasks[nmasks].mask = masks[nmasks]; @@ -166,9 +166,9 @@ int xf_input_init(xfContext* xfc, Window window) { if (xfc->context.settings->MultiTouchInput) { - WLog_INFO(TAG, "%s %s touch device (id: %d, mode: %d), supporting %d touches.", - dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", - dev->deviceid, t->mode, t->num_touches); + WLog_DBG(TAG, "%s %s touch device (id: %d, mode: %d), supporting %d touches.", + dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent", + dev->deviceid, t->mode, t->num_touches); } XISetMask(masks[nmasks], XI_TouchBegin); @@ -182,8 +182,8 @@ int xf_input_init(xfContext* xfc, Window window) if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer")) { - WLog_INFO(TAG, "%s button device (id: %d, mode: %d)", dev->name, dev->deviceid, - t->mode); + WLog_DBG(TAG, "%s button device (id: %d, mode: %d)", dev->name, dev->deviceid, + t->mode); XISetMask(masks[nmasks], XI_ButtonPress); XISetMask(masks[nmasks], XI_ButtonRelease); XISetMask(masks[nmasks], XI_Motion); diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 55ea712..5c50a07 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -355,7 +355,7 @@ BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int leng if (actual_type == None) { - WLog_INFO(TAG, "Property %lu does not exist", (unsigned long)property); + WLog_DBG(TAG, "Property %lu does not exist", (unsigned long)property); return FALSE; } diff --git a/client/common/client.c b/client/common/client.c index 0cdb636..12317dc 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -730,6 +730,7 @@ BOOL client_auto_reconnect(freerdp* instance) BOOL client_auto_reconnect_ex(freerdp* instance, BOOL (*window_events)(freerdp* instance)) { + BOOL retry = TRUE; UINT32 error; UINT32 maxRetries; UINT32 numRetries = 0; @@ -765,7 +766,7 @@ BOOL client_auto_reconnect_ex(freerdp* instance, BOOL (*window_events)(freerdp* } /* Perform an auto-reconnect. */ - while (TRUE) + while (retry) { UINT32 x; @@ -781,12 +782,21 @@ BOOL client_auto_reconnect_ex(freerdp* instance, BOOL (*window_events)(freerdp* if (freerdp_reconnect(instance)) return TRUE; + switch (freerdp_get_last_error(instance)) + { + case FREERDP_ERROR_CONNECT_CANCELLED: + WLog_WARN(TAG, "Autoreconnect aborted by user"); + retry = FALSE; + break; + default: + break; + } for (x = 0; x < 50; x++) { if (!IFCALLRESULT(TRUE, window_events, instance)) return FALSE; - Sleep(100); + Sleep(10); } } diff --git a/client/common/cmdline.c b/client/common/cmdline.c index e6b3e55..15d4813 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -3499,7 +3499,7 @@ static BOOL freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpS { if (freerdp_channels_client_load_ex(channels, settings, entryEx, data) == 0) { - WLog_INFO(TAG, "loading channelEx %s", name); + WLog_DBG(TAG, "loading channelEx %s", name); return TRUE; } } @@ -3507,7 +3507,7 @@ static BOOL freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpS { if (freerdp_channels_client_load(channels, settings, entry, data) == 0) { - WLog_INFO(TAG, "loading channel %s", name); + WLog_DBG(TAG, "loading channel %s", name); return TRUE; } } diff --git a/docs/version_detection.md b/docs/version_detection.md new file mode 100644 index 0000000..0cd3b89 --- /dev/null +++ b/docs/version_detection.md @@ -0,0 +1,35 @@ +As FreeRDPs is build on different OS with different build tools and methods the +"version detection" has grown historically. +This document quickly describes how it's currently used. + +When doing a `xfreerdp /version` for example the following is shown + +`This is FreeRDP version 3.0.0-dev (c99c4cecddee4e5b914b122bc1531d47a668bb8e)` + +The first part ist the Version as defined in `RAW_VERSION_STRING` and the second part, in braces, +the `GIT_REVISON` of this version. + +`RAW_VERSION_STRING` is very vital as it determines the version used for libraries as well also for +all sub-projects as WinPR. + +As default both variables are equal. + +For nightly or development builds it is often of advantage to have the actual version from git +instead of having the hard coded value set in CMakeLists.txt. For this the cmake variable `USE_VERSION_FROM_GIT_TAG` +can be set. In order for this to work you need a) source checkout and b) git command line utility. +If enabled the information from the last git tag (in the format major.minor.patch-extra like +2.6.0-android12) will be used. + +If you are building FreeRDP and can't use git because it's not available or the source is not in an +git repository - for example when building packages - the files `.source_tag` and `.source_version` +in the top-level source directory can be used. `.source_tag` is equal to `RAW_VERSION_STRING` and +need to contain the version in the same format as the git tag. `.source_version` is used to pre-fill +`GIT_REVISON`. Although mostly used for that it must not contain a git commit or tag - it can be +used to set additional arbitrary information. Our recommendation for packagers is to create +`.source_version` when importing and set it to the upstream commit or tag to simplify issue +tracking. + +As summary the different mechanisms are applied in that order: +* `.source_tag` and `.source_version` if found +* version set from the last git tag if `RAW_VERSION_STRING` is set +* hard coded version in CMakeLists.txt diff --git a/libfreerdp/codec/h264_openh264.c b/libfreerdp/codec/h264_openh264.c index 5321f30..9efce29 100644 --- a/libfreerdp/codec/h264_openh264.c +++ b/libfreerdp/codec/h264_openh264.c @@ -115,6 +115,21 @@ static int openh264_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 } } + if (state != dsErrorFree) + { + WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%02X", state); + return -2003; + } + +#if OPENH264_MAJOR >= 2 + state = (*sys->pDecoder)->FlushFrame(sys->pDecoder, pYUVData, &sBufferInfo); + if (state != dsErrorFree) + { + WLog_Print(h264->log, WLOG_WARN, "FlushFrame state: 0x%02X", state); + return -2003; + } +#endif + pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; iStride[0] = pSystemBuffer->iStride[0]; iStride[1] = pSystemBuffer->iStride[1]; diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index f9f8300..a979d7a 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -131,7 +131,10 @@ set(${MODULE_PREFIX}_SRCS peer.c peer.h display.c - display.h) + display.h + utils.c + utils.h + ) set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_GATEWAY_SRCS}) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 143a1cb..a1a01e9 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -39,6 +39,8 @@ #include #include +#include "utils.h" + #define TAG FREERDP_TAG("core.connection") /** @@ -411,10 +413,13 @@ BOOL rdp_client_disconnect_and_clear(rdpRdp* rdp) return FALSE; context = rdp->context; + + if (freerdp_get_last_error(context) == FREERDP_ERROR_CONNECT_CANCELLED) + return FALSE; + context->LastError = FREERDP_ERROR_SUCCESS; clearChannelError(context); - ResetEvent(context->abortEvent); - return TRUE; + return utils_reset_abort(context); } static BOOL rdp_client_reconnect_channels(rdpRdp* rdp, BOOL redirect) diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index a070d0c..7d9eba4 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -52,6 +52,7 @@ #include #include "settings.h" +#include "utils.h" #define TAG FREERDP_TAG("core") @@ -168,7 +169,9 @@ BOOL freerdp_connect(freerdp* instance) #endif freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS); clearChannelError(instance->context); - ResetEvent(instance->context->abortEvent); + if (!utils_reset_abort(instance->context)) + return FALSE; + rdp = instance->context->rdp; settings = instance->settings; @@ -308,7 +311,8 @@ BOOL freerdp_abort_connect(freerdp* instance) if (!instance || !instance->context) return FALSE; - return SetEvent(instance->context->abortEvent); + freerdp_set_last_error_if_not(instance->context, FREERDP_ERROR_CONNECT_CANCELLED); + return utils_abort_connect(instance->context); } BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount) @@ -540,11 +544,16 @@ BOOL freerdp_disconnect_before_reconnect(freerdp* instance) BOOL freerdp_reconnect(freerdp* instance) { - BOOL status; - rdpRdp* rdp = instance->context->rdp; - ResetEvent(instance->context->abortEvent); - status = rdp_client_reconnect(rdp); - return status; + rdpRdp* rdp; + + if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED) + return FALSE; + + rdp = instance->context->rdp; + + if (!utils_reset_abort(instance->context)) + return FALSE; + return rdp_client_reconnect(rdp); } BOOL freerdp_shall_disconnect(freerdp* instance) @@ -886,7 +895,7 @@ void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char if (lastError == FREERDP_ERROR_SUCCESS) { - WLog_INFO(TAG, "%s:%s resetting error state", fkt, __FUNCTION__); + WLog_DBG(TAG, "%s:%s resetting error state", fkt, __FUNCTION__); } else if (context->LastError != FREERDP_ERROR_SUCCESS) { diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index fb32d3c..1ef0c04 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -38,6 +38,7 @@ #include "rpc_client.h" #include "rts_signature.h" +#include "../utils.h" #include "../rdp.h" #include "../proxy.h" @@ -362,7 +363,7 @@ static int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) Stream_SetPosition(fragment, StubOffset); Stream_Read_UINT32(fragment, rpc->result); - freerdp_abort_connect(context->instance); + utils_abort_connect(context); tsg_set_state(tsg, TSG_STATE_TUNNEL_CLOSE_PENDING); EventArgsInit(&e, "freerdp"); e.code = 0; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 7da499e..610d81e 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -27,6 +27,7 @@ #include "rdp.h" #include "info.h" +#include "utils.h" #include "redirection.h" #include @@ -414,7 +415,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) { if (code == X224_TPDU_DISCONNECT_REQUEST) { - freerdp_abort_connect(rdp->instance); + utils_abort_connect(rdp->instance->context); return TRUE; } @@ -471,7 +472,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) } WLog_DBG(TAG, "DisconnectProviderUltimatum: reason: %d", reason); - freerdp_abort_connect(rdp->instance); + utils_abort_connect(context); EventArgsInit(&e, "freerdp"); e.code = 0; PubSub_OnTerminate(context->pubSub, context, &e); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index 60b4211..0d0641b 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -844,12 +844,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct status = WaitForMultipleObjects(count, handles, FALSE, tout); if (WAIT_OBJECT_0 != status) - { - if (status == WAIT_OBJECT_0 + 1) - freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED); - goto fail; - } status = recv(sockfd, NULL, 0, 0); @@ -1235,9 +1230,6 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, const char* if (WaitForSingleObject(context->abortEvent, 0) == WAIT_OBJECT_0) { close(sockfd); - - freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED); - return -1; } diff --git a/libfreerdp/core/utils.c b/libfreerdp/core/utils.c new file mode 100644 index 0000000..6b6770b --- /dev/null +++ b/libfreerdp/core/utils.c @@ -0,0 +1,47 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Terminal Server Gateway (utils) + * + * Copyright 2021 Armin Novak + * Copyright 2021 Thincast Technologies GmbH + * + * Licensed 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include +#define TAG FREERDP_TAG("core.gateway.utils") + +#include "utils.h" + +#define WINPR_ASSERT(x) assert(x) + +BOOL utils_abort_connect(rdpContext* context) +{ + WINPR_ASSERT(context); + + return SetEvent(context->abortEvent); +} + +BOOL utils_reset_abort(rdpContext* context) +{ + WINPR_ASSERT(context); + return ResetEvent(context->abortEvent); +} diff --git a/libfreerdp/core/utils.h b/libfreerdp/core/utils.h new file mode 100644 index 0000000..c7985be --- /dev/null +++ b/libfreerdp/core/utils.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Terminal Server Gateway (utils) + * + * Copyright 2021 Armin Novak + * Copyright 2021 Thincast Technologies GmbH + * + * Licensed 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 FREERDP_LIB_CORE_UTILS_H +#define FREERDP_LIB_CORE_UTILS_H + +#include +#include + +BOOL utils_reset_abort(rdpContext* context); +BOOL utils_abort_connect(rdpContext* context); + +#endif /* FREERDP_LIB_CORE_UTILS_H */ diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index fee8db5..1990302 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -866,7 +866,7 @@ int tls_connect(rdpTls* tls, BIO* underlying) #else if (!tls_prepare(tls, underlying, TLS_client_method(), options, TRUE)) #endif - return FALSE; + return 0; #if !defined(OPENSSL_NO_TLSEXT) && !defined(LIBRESSL_VERSION_NUMBER) SSL_set_tlsext_host_name(tls->ssl, tls->hostname); diff --git a/libfreerdp/primitives/primitives.c b/libfreerdp/primitives/primitives.c index 26c6338..0a4303d 100644 --- a/libfreerdp/primitives/primitives.c +++ b/libfreerdp/primitives/primitives.c @@ -260,7 +260,7 @@ static BOOL primitives_autodetect_best(primitives_t* prims) /* finally compute the results */ *prims = *best->prims; - WLog_INFO(TAG, "primitives autodetect, using %s", best->name); + WLog_DBG(TAG, "primitives autodetect, using %s", best->name); ret = TRUE; out: if (!ret) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 3bad25b..7e5860d 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -51,7 +51,7 @@ if (NOT WIN32) endif() # Soname versioning -set(RAW_VERSION_STRING "2.6.0") +set(RAW_VERSION_STRING "2.6.1") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff --git a/winpr/libwinpr/clipboard/clipboard.c b/winpr/libwinpr/clipboard/clipboard.c index 2e88d75..3c5acd4 100644 --- a/winpr/libwinpr/clipboard/clipboard.c +++ b/winpr/libwinpr/clipboard/clipboard.c @@ -528,7 +528,7 @@ static void ClipboardInitLocalFileSubsystem(wClipboard* clipboard) #ifdef WITH_WCLIPBOARD_POSIX if (ClipboardInitPosixFileSubsystem(clipboard)) { - WLog_INFO(TAG, "initialized POSIX local file subsystem"); + WLog_DBG(TAG, "initialized POSIX local file subsystem"); return; } else