diff --git a/server/proxy/config.ini b/server/proxy/config.ini index 47273aa17..a8ac44b5d 100644 --- a/server/proxy/config.ini +++ b/server/proxy/config.ini @@ -9,8 +9,8 @@ Port = 3389 ; and the /load-balance-info: CLI option for xfreerdp. Otherwise, the server ; will always connect to the same target, using the configured values of `Host` ; and `Port`. -UseLoadBalanceInfo = TRUE -Host = FakeHost +FixedTarget = TRUE +Host = CustomHost Port = 3389 [Input] diff --git a/server/proxy/modules/demo/demo.cpp b/server/proxy/modules/demo/demo.cpp index 617cda037..f77e265f6 100644 --- a/server/proxy/modules/demo/demo.cpp +++ b/server/proxy/modules/demo/demo.cpp @@ -66,6 +66,7 @@ static proxyPlugin demo_plugin = { NULL, /* MouseEvent */ NULL, /* ClientChannelData */ NULL, /* ServerChannelData */ + NULL /* ServerFetchTargetAddr */ }; BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager) diff --git a/server/proxy/modules/modules_api.h b/server/proxy/modules/modules_api.h index 4b9de1d58..e0c086a68 100644 --- a/server/proxy/modules/modules_api.h +++ b/server/proxy/modules/modules_api.h @@ -61,6 +61,7 @@ typedef struct proxy_plugin proxyFilterFn MouseEvent; proxyFilterFn ClientChannelData; /* passthrough channels data */ proxyFilterFn ServerChannelData; /* passthrough channels data */ + proxyFilterFn ServerFetchTargetAddr; } proxyPlugin; /* @@ -111,6 +112,27 @@ typedef struct channel_data_event_info const BYTE* data; size_t data_len; } proxyChannelDataEventInfo; + +typedef enum proxy_fetch_target_method +{ + PROXY_FETCH_TARGET_METHOD_DEFAULT, + PROXY_FETCH_TARGET_METHOD_CONFIG, + PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO, + PROXY_FETCH_TARGET_USE_CUSTOM_ADDR +} ProxyFetchTargetMethod; + +typedef struct fetch_target_event_info +{ + /* out values */ + char* target_address; + UINT16 target_port; + + /* + * If this value is set to true by a plugin, target info will be fetched from config and proxy + * will connect any client to the same remote server. + */ + ProxyFetchTargetMethod fetch_method; +} proxyFetchTargetEventInfo; #define WINPR_PACK_POP #include diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index 0edf56e59..4db6e9a08 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -217,15 +217,8 @@ static BOOL pf_client_pre_connect(freerdp* instance) */ LOG_INFO(TAG, pc, "Loading addins"); - if (!config->UseLoadBalanceInfo) - { - /* if target is static (i.e fetched from config). make sure to use peer's load-balance info, - * in order to support broker redirection. - */ - - if (!pf_client_use_peer_load_balance_info(pc)) - return FALSE; - } + if (!pf_client_use_peer_load_balance_info(pc)) + return FALSE; if (!pf_client_passthrough_channels_init(pc)) return FALSE; diff --git a/server/proxy/pf_config.c b/server/proxy/pf_config.c index 4dcb7277d..4d29ac9a6 100644 --- a/server/proxy/pf_config.c +++ b/server/proxy/pf_config.c @@ -157,7 +157,7 @@ static BOOL pf_config_load_target(wIniFile* ini, proxyConfig* config) if (!config->TargetHost) return FALSE; - config->UseLoadBalanceInfo = pf_config_get_bool(ini, "Target", "UseLoadBalanceInfo"); + config->FixedTarget = pf_config_get_bool(ini, "Target", "FixedTarget"); return TRUE; } @@ -307,7 +307,7 @@ void pf_server_config_print(proxyConfig* config) CONFIG_PRINT_STR(config, Host); CONFIG_PRINT_UINT16(config, Port); - if (!config->UseLoadBalanceInfo) + if (config->FixedTarget) { CONFIG_PRINT_SECTION("Target"); CONFIG_PRINT_STR(config, TargetHost); diff --git a/server/proxy/pf_config.h b/server/proxy/pf_config.h index 5b5c10c77..83b55f16e 100644 --- a/server/proxy/pf_config.h +++ b/server/proxy/pf_config.h @@ -34,7 +34,7 @@ struct proxy_config UINT16 Port; /* target */ - BOOL UseLoadBalanceInfo; + BOOL FixedTarget; char* TargetHost; UINT16 TargetPort; diff --git a/server/proxy/pf_modules.c b/server/proxy/pf_modules.c index daa81451e..0d0d8ff48 100644 --- a/server/proxy/pf_modules.c +++ b/server/proxy/pf_modules.c @@ -39,12 +39,8 @@ static wArrayList* handles_list = NULL; /* list of module handles to free at shu typedef BOOL (*moduleEntryPoint)(proxyPluginsManager* plugins_manager); -static const char* FILTER_TYPE_STRINGS[] = { - "KEYBOARD_EVENT", - "MOUSE_EVENT", - "CLIENT_CHANNEL_DATA", - "SERVER_CHANNEL_DATA", -}; +static const char* FILTER_TYPE_STRINGS[] = { "KEYBOARD_EVENT", "MOUSE_EVENT", "CLIENT_CHANNEL_DATA", + "SERVER_CHANNEL_DATA", "SERVER_FETCH_TARGET_ADDR" }; static const char* HOOK_TYPE_STRINGS[] = { "CLIENT_PRE_CONNECT", "CLIENT_POST_CONNECT", "CLIENT_LOGIN_FAILURE", "CLIENT_END_PAINT", @@ -165,6 +161,11 @@ BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param) case FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA: IFCALLRET(plugin->ServerChannelData, result, pdata, param); break; + + case FILTER_TYPE_SERVER_FETCH_TARGET_ADDR: + IFCALLRET(plugin->ServerFetchTargetAddr, result, pdata, param); + break; + default: WLog_ERR(TAG, "invalid filter called"); } diff --git a/server/proxy/pf_modules.h b/server/proxy/pf_modules.h index bb188c46d..656f71b62 100644 --- a/server/proxy/pf_modules.h +++ b/server/proxy/pf_modules.h @@ -32,7 +32,9 @@ enum _PF_FILTER_TYPE FILTER_TYPE_KEYBOARD, FILTER_TYPE_MOUSE, FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA, + FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA, + FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, FILTER_LAST }; diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c index 2811faad5..b2097be20 100644 --- a/server/proxy/pf_server.c +++ b/server/proxy/pf_server.c @@ -100,22 +100,58 @@ static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings proxyConfig* config) { pServerContext* ps = (pServerContext*)context; + proxyFetchTargetEventInfo ev = { 0 }; - LOG_INFO(TAG, ps, "fetching target from %s", - config->UseLoadBalanceInfo ? "load-balance-info" : "config"); + ev.fetch_method = config->FixedTarget ? PROXY_FETCH_TARGET_METHOD_CONFIG + : PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO; - if (config->UseLoadBalanceInfo) - return pf_server_parse_target_from_routing_token(context, &settings->ServerHostname, - &settings->ServerPort); - - /* use hardcoded target info from configuration */ - if (!(settings->ServerHostname = _strdup(config->TargetHost))) - { - LOG_ERR(TAG, ps, "strdup failed!"); + if (!pf_modules_run_filter(FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, ps->pdata, &ev)) return FALSE; + + switch (ev.fetch_method) + { + case PROXY_FETCH_TARGET_METHOD_DEFAULT: + case PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO: + return pf_server_parse_target_from_routing_token(context, &settings->ServerHostname, + &settings->ServerPort); + + case PROXY_FETCH_TARGET_METHOD_CONFIG: + { + settings->ServerPort = config->TargetPort > 0 ? 3389 : settings->ServerPort; + settings->ServerHostname = _strdup(config->TargetHost); + + if (!settings->ServerHostname) + { + LOG_ERR(TAG, ps, "strdup failed!"); + return FALSE; + } + + return TRUE; + } + case PROXY_FETCH_TARGET_USE_CUSTOM_ADDR: + { + if (!ev.target_address) + { + WLog_ERR(TAG, "router: using CUSTOM_ADDR fetch method, but target_address == NULL"); + return FALSE; + } + + settings->ServerHostname = _strdup(ev.target_address); + if (!settings->ServerHostname) + { + LOG_ERR(TAG, ps, "strdup failed!"); + return FALSE; + } + + free(ev.target_address); + settings->ServerPort = ev.target_port; + return TRUE; + } + default: + WLog_WARN(TAG, "unknown target fetch method: %d", ev.fetch_method); + return FALSE; } - settings->ServerPort = config->TargetPort > 0 ? 3389 : settings->ServerPort; return TRUE; }