From 650a275ceb3eb2d02732e5adbf9487d58eaaaf62 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 22 Jun 2022 12:17:44 +0200 Subject: [PATCH] Added new client callback LoadChannels and freerdp_client_load_channels Split channel loading from PreConnect as it might be necessary to reinitialize channels on redirect --- .../src/main/cpp/android_freerdp.c | 12 +++----- client/Mac/MRDPView.m | 3 -- client/Mac/mf_client.m | 1 + client/Sample/tf_freerdp.c | 6 +--- client/Wayland/wlfreerdp.c | 4 +-- client/Windows/wf_client.c | 4 +-- client/X11/xf_client.c | 6 ++-- client/common/client.c | 12 ++++++++ include/freerdp/client.h | 2 ++ include/freerdp/freerdp.h | 27 +++++++++-------- .../freerdp/server/proxy/proxy_modules_api.h | 3 +- server/proxy/pf_client.c | 30 ++++++++++++++++--- server/proxy/pf_modules.c | 6 ++++ server/proxy/proxy_modules.h | 1 + server/shadow/Win/win_rdp.c | 4 +-- 15 files changed, 75 insertions(+), 46 deletions(-) diff --git a/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.c b/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.c index 6139d961c..29bd7a35c 100644 --- a/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.c +++ b/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.c @@ -177,7 +177,7 @@ static BOOL android_desktop_resize(rdpContext* context) freerdp_callback("OnGraphicsResize", "(JIII)V", (jlong)context->instance, context->settings->DesktopWidth, context->settings->DesktopHeight, - context->settings->ColorDepth); + context->freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth)); return TRUE; } @@ -212,12 +212,6 @@ static BOOL android_pre_connect(freerdp* instance) return FALSE; } - if (!freerdp_client_load_addins(instance->context->channels, instance->context->settings)) - { - WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError()); - return FALSE; - } - freerdp_callback("OnPreConnect", "(J)V", (jlong)instance); return TRUE; } @@ -307,7 +301,8 @@ static BOOL android_post_connect(freerdp* instance) update->EndPaint = android_end_paint; update->DesktopResize = android_desktop_resize; freerdp_callback("OnSettingsChanged", "(JIII)V", (jlong)instance, settings->DesktopWidth, - settings->DesktopHeight, settings->ColorDepth); + settings->DesktopHeight, + freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth)); freerdp_callback("OnConnectionSuccess", "(J)V", (jlong)instance); return TRUE; } @@ -537,6 +532,7 @@ static BOOL android_client_new(freerdp* instance, rdpContext* context) if (!android_event_queue_init(instance)) return FALSE; + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = android_pre_connect; instance->PostConnect = android_post_connect; instance->PostDisconnect = android_post_disconnect; diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 0c6534a19..3b00644cf 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -860,9 +860,6 @@ BOOL mac_pre_connect(freerdp *instance) PubSub_SubscribeChannelDisconnected(instance->context->pubSub, mac_OnChannelDisconnectedEventHandler); - if (!freerdp_client_load_addins(instance->context->channels, settings)) - return FALSE; - return TRUE; } diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 281aee92c..30e7a2507 100644 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -88,6 +88,7 @@ static BOOL mfreerdp_client_new(freerdp *instance, rdpContext *context) WINPR_ASSERT(mfc); mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + context->instance->LoadChannels = freerdp_client_load_channels; context->instance->PreConnect = mac_pre_connect; context->instance->PostConnect = mac_post_connect; context->instance->PostDisconnect = mac_post_disconnect; diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c index 425685ef1..cfc289c44 100644 --- a/client/Sample/tf_freerdp.c +++ b/client/Sample/tf_freerdp.c @@ -158,11 +158,6 @@ static BOOL tf_pre_connect(freerdp* instance) PubSub_SubscribeChannelDisconnected(instance->context->pubSub, tf_OnChannelDisconnectedEventHandler); - /* Load all required plugins / channels / libraries specified by current - * settings. */ - if (!freerdp_client_load_addins(instance->context->channels, settings)) - return FALSE; - /* TODO: Any code your client requires */ return TRUE; } @@ -326,6 +321,7 @@ static BOOL tf_client_new(freerdp* instance, rdpContext* context) if (!instance || !context) return FALSE; + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = tf_pre_connect; instance->PostConnect = tf_post_connect; instance->PostDisconnect = tf_post_disconnect; diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index e286fc4be..2a79cc996 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -204,9 +204,6 @@ static BOOL wl_pre_connect(freerdp* instance) } } - if (!freerdp_client_load_addins(instance->context->channels, settings)) - return FALSE; - return TRUE; } @@ -621,6 +618,7 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context) if (!instance || !context) return FALSE; + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; instance->PostDisconnect = wl_post_disconnect; diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index 47d8152c9..cc012eee7 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -273,9 +273,6 @@ static BOOL wf_pre_connect(freerdp* instance) freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, desktopHeight); } - if (!freerdp_client_load_addins(context->channels, context->settings)) - return -1; - rc = freerdp_keyboard_init(freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout)); freerdp_settings_set_uint32(settings, FreeRDP_KeyboardLayout, rc); PubSub_SubscribeChannelConnected(instance->context->pubSub, wf_OnChannelConnectedEventHandler); @@ -1308,6 +1305,7 @@ static BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context) return FALSE; WINPR_ASSERT(instance); + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = wf_pre_connect; instance->PostConnect = wf_post_connect; instance->PostDisconnect = wf_post_disconnect; diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 69d5587f5..f6fbad961 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1,4 +1,4 @@ -/** +/** * FreeRDP: A Remote Desktop Protocol Implementation * X11 Client Interface * @@ -1223,9 +1223,6 @@ static BOOL xf_pre_connect(freerdp* instance) PubSub_SubscribeChannelConnected(context->pubSub, xf_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(context->pubSub, xf_OnChannelDisconnectedEventHandler); - if (!freerdp_client_load_addins(channels, settings)) - return FALSE; - if (!settings->Username && !settings->CredentialsFromStdin && !settings->SmartcardLogon) { char login_name[MAX_PATH] = { 0 }; @@ -1851,6 +1848,7 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) WINPR_ASSERT(!xfc->display); WINPR_ASSERT(!xfc->mutex); WINPR_ASSERT(!xfc->x11event); + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; instance->PostDisconnect = xf_post_disconnect; diff --git a/client/common/client.c b/client/common/client.c index bc614bccf..776023aab 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -1207,3 +1207,15 @@ BOOL freerdp_client_send_extended_button_event(rdpClientContext* cctx, BOOL rela return TRUE; } +BOOL freerdp_client_load_channels(freerdp* instance) +{ + WINPR_ASSERT(instance); + WINPR_ASSERT(instance->context); + + if (!freerdp_client_load_addins(instance->context->channels, instance->context->settings)) + { + WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError()); + return FALSE; + } + return TRUE; +} diff --git a/include/freerdp/client.h b/include/freerdp/client.h index bd83961a8..0d098ce72 100644 --- a/include/freerdp/client.h +++ b/include/freerdp/client.h @@ -193,6 +193,8 @@ extern "C" FREERDP_API int freerdp_client_common_stop(rdpContext* context); + FREERDP_API BOOL freerdp_client_load_channels(freerdp* instance); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index 5b6175564..5dec619dd 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -111,9 +111,7 @@ extern "C" typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context); typedef void (*pContextFree)(freerdp* instance, rdpContext* context); - typedef BOOL (*pPreConnect)(freerdp* instance); - typedef BOOL (*pPostConnect)(freerdp* instance); - typedef BOOL (*pRedirect)(freerdp* instance); + typedef BOOL (*pConnectCallback)(freerdp* instance); typedef void (*pPostDisconnect)(freerdp* instance); typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); @@ -405,13 +403,13 @@ owned by rdpRdp */ ALIGN64 UINT ConnectionCallbackState; /* 47 */ - ALIGN64 pPreConnect + ALIGN64 pConnectCallback PreConnect; /**< (offset 48) Callback for pre-connect operations. Can be set before calling freerdp_connect() to have it executed before the actual connection happens. Must be set to NULL if not needed. */ - ALIGN64 pPostConnect + ALIGN64 pConnectCallback PostConnect; /**< (offset 49) Callback for post-connect operations. Can be set before calling freerdp_connect() to have it executed after the @@ -452,13 +450,18 @@ owned by rdpRdp */ Callback for gateway consent messages. It is used to present consent messages to the user. */ - ALIGN64 pRedirect - Redirect; /**< (offset 59) - Callback for redirect operations. - Can be set after rdp_client_disconnect_and_clear and applying redirection -settings but before rdp_client_connect() to have it executed after the - actual connection has succeeded. Must be set to NULL if not needed. */ - UINT64 paddingD[64 - 59]; /* 59 */ + ALIGN64 pConnectCallback Redirect; /**< (offset 58) + Callback for redirect operations. + Can be set after + rdp_client_disconnect_and_clear and applying redirection settings but before + rdp_client_connect() to have it executed after the actual connection has + succeeded. Must be set to NULL if not needed. */ + ALIGN64 pConnectCallback + LoadChannels; /**< (offset 59) + * callback for loading channel configuration. Might be called multiple + * times when redirection occurs. */ + + UINT64 paddingD[64 - 60]; /* 60 */ ALIGN64 pSendChannelData SendChannelData; /* (offset 64) diff --git a/include/freerdp/server/proxy/proxy_modules_api.h b/include/freerdp/server/proxy/proxy_modules_api.h index 50233d01b..ffa2e4820 100644 --- a/include/freerdp/server/proxy/proxy_modules_api.h +++ b/include/freerdp/server/proxy/proxy_modules_api.h @@ -69,7 +69,8 @@ struct proxy_plugin proxyHookFn ClientLoginFailure; /* 72 custom=rdpContext* */ proxyHookFn ClientEndPaint; /* 73 custom=rdpContext* */ proxyHookFn ClientRedirect; /* 74 custom=rdpContext* */ - UINT64 reserved3[96 - 75]; /* 75-95 */ + proxyHookFn ClientLoadChannels; /* 75 custom=rdpContext* */ + UINT64 reserved3[96 - 76]; /* 76-95 */ proxyHookFn ServerPostConnect; /* 96 custom=freerdp_peer* */ proxyHookFn ServerPeerActivate; /* 97 custom=freerdp_peer* */ diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index 9440f8b69..7fe47e04a 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -303,15 +303,36 @@ static BOOL pf_client_pre_connect(freerdp* instance) PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); PubSub_SubscribeActivated(instance->context->pubSub, pf_client_on_activated); + if (!pf_client_use_peer_load_balance_info(pc)) + return FALSE; + + return pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_PRE_CONNECT, pc->pdata, pc); +} + +static BOOL pf_client_load_channels(freerdp* instance) +{ + pClientContext* pc; + pServerContext* ps; + const proxyConfig* config; + rdpSettings* settings; + + WINPR_ASSERT(instance); + pc = (pClientContext*)instance->context; + WINPR_ASSERT(pc); + WINPR_ASSERT(pc->pdata); + ps = pc->pdata->ps; + WINPR_ASSERT(ps); + WINPR_ASSERT(ps->pdata); + config = ps->pdata->config; + WINPR_ASSERT(config); + settings = instance->context->settings; + WINPR_ASSERT(settings); /** * Load all required plugins / channels / libraries specified by current * settings. */ PROXY_LOG_INFO(TAG, pc, "Loading addins"); - if (!pf_client_use_peer_load_balance_info(pc)) - return FALSE; - if (!pf_client_load_rdpsnd(pc)) { PROXY_LOG_ERR(TAG, pc, "Failed to load rdpsnd client"); @@ -371,7 +392,7 @@ static BOOL pf_client_pre_connect(freerdp* instance) return FALSE; } } - return pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_PRE_CONNECT, pc->pdata, pc); + return pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_LOAD_CHANNELS, pc->pdata, pc); } static BOOL pf_client_receive_channel_data_hook(freerdp* instance, UINT16 channelId, @@ -942,6 +963,7 @@ static BOOL pf_client_client_new(freerdp* instance, rdpContext* context) if (!instance || !context) return FALSE; + instance->LoadChannels = pf_client_load_channels; instance->PreConnect = pf_client_pre_connect; instance->PostConnect = pf_client_post_connect; instance->PostDisconnect = pf_client_post_disconnect; diff --git a/server/proxy/pf_modules.c b/server/proxy/pf_modules.c index 54b27bb30..d37cdc849 100644 --- a/server/proxy/pf_modules.c +++ b/server/proxy/pf_modules.c @@ -105,6 +105,8 @@ static const char* pf_modules_get_hook_type_string(PF_HOOK_TYPE result) return "HOOK_TYPE_SERVER_CHANNELS_FREE"; case HOOK_TYPE_SERVER_SESSION_END: return "HOOK_TYPE_SERVER_SESSION_END"; + case HOOK_TYPE_CLIENT_LOAD_CHANNELS: + return "HOOK_TYPE_CLIENT_LOAD_CHANNELS"; case HOOK_TYPE_SERVER_SESSION_INITIALIZE: return "HOOK_TYPE_SERVER_SESSION_INITIALIZE"; case HOOK_TYPE_SERVER_SESSION_STARTED: @@ -168,6 +170,10 @@ static BOOL pf_modules_proxy_ArrayList_ForEachFkt(void* data, size_t index, va_l ok = IFCALLRESULT(TRUE, plugin->ClientEndPaint, plugin, pdata, custom); break; + case HOOK_TYPE_CLIENT_LOAD_CHANNELS: + ok = IFCALLRESULT(TRUE, plugin->ClientLoadChannels, plugin, pdata, custom); + break; + case HOOK_TYPE_SERVER_POST_CONNECT: ok = IFCALLRESULT(TRUE, plugin->ServerPostConnect, plugin, pdata, custom); break; diff --git a/server/proxy/proxy_modules.h b/server/proxy/proxy_modules.h index 99e373a2f..5e9aa3fa6 100644 --- a/server/proxy/proxy_modules.h +++ b/server/proxy/proxy_modules.h @@ -51,6 +51,7 @@ typedef enum HOOK_TYPE_CLIENT_VERIFY_X509, HOOK_TYPE_CLIENT_LOGIN_FAILURE, HOOK_TYPE_CLIENT_END_PAINT, + HOOK_TYPE_CLIENT_LOAD_CHANNELS, HOOK_TYPE_SERVER_POST_CONNECT, HOOK_TYPE_SERVER_ACTIVATE, diff --git a/server/shadow/Win/win_rdp.c b/server/shadow/Win/win_rdp.c index 6ffe9b0ba..b63fc1be0 100644 --- a/server/shadow/Win/win_rdp.c +++ b/server/shadow/Win/win_rdp.c @@ -128,9 +128,6 @@ static BOOL shw_pre_connect(freerdp* instance) PubSub_SubscribeChannelConnected(context->pubSub, shw_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(context->pubSub, shw_OnChannelDisconnectedEventHandler); - if (!freerdp_client_load_addins(context->channels, context->settings)) - return FALSE; - return TRUE; } @@ -283,6 +280,7 @@ static BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context) if (!(shw->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) return FALSE; + instance->LoadChannels = freerdp_client_load_channels; instance->PreConnect = shw_pre_connect; instance->PostConnect = shw_post_connect; instance->Authenticate = shw_authenticate;