24#include <freerdp/config.h>
28#include <winpr/path.h>
29#include <winpr/synch.h>
30#include <winpr/string.h>
31#include <winpr/winsock.h>
32#include <winpr/thread.h>
35#include <freerdp/freerdp.h>
36#include <freerdp/streamdump.h>
37#include <freerdp/channels/wtsvc.h>
38#include <freerdp/channels/channels.h>
39#include <freerdp/channels/drdynvc.h>
40#include <freerdp/build-config.h>
42#include <freerdp/channels/rdpdr.h>
44#include <freerdp/server/proxy/proxy_server.h>
45#include <freerdp/server/proxy/proxy_log.h>
49#include "pf_channel.h"
50#include <freerdp/server/proxy/proxy_config.h>
52#include <freerdp/server/proxy/proxy_context.h>
54#include "proxy_modules.h"
56#include "channels/pf_channel_drdynvc.h"
57#include "channels/pf_channel_rdpdr.h"
59#define TAG PROXY_TAG("server")
68static BOOL pf_server_parse_target_from_routing_token(rdpContext* context, rdpSettings* settings,
69 FreeRDP_Settings_Keys_String targetID,
70 FreeRDP_Settings_Keys_UInt32 portID)
72#define TARGET_MAX (100)
73#define ROUTING_TOKEN_PREFIX "Cookie: msts="
74 char* colon =
nullptr;
76 DWORD routing_token_length = 0;
77 const size_t prefix_len = strnlen(ROUTING_TOKEN_PREFIX,
sizeof(ROUTING_TOKEN_PREFIX));
78 const char* routing_token = freerdp_nego_get_routing_token(context, &routing_token_length);
79 pServerContext* ps = (pServerContext*)context;
84 if ((routing_token_length <= prefix_len) || (routing_token_length >= TARGET_MAX))
86 PROXY_LOG_ERR(TAG, ps,
"invalid routing token length: %" PRIu32
"", routing_token_length);
90 len = routing_token_length - prefix_len;
96 colon = strchr(target,
':');
101 unsigned long p = strtoul(colon + 1,
nullptr, 10);
114static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings,
115 const proxyConfig* config)
117 pServerContext* ps = (pServerContext*)context;
120 WINPR_ASSERT(settings);
122 WINPR_ASSERT(ps->pdata);
124 ev.fetch_method = config->FixedTarget ? PROXY_FETCH_TARGET_METHOD_CONFIG
125 : PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO;
127 if (!pf_modules_run_filter(ps->pdata->module, FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, ps->pdata,
131 switch (ev.fetch_method)
133 case PROXY_FETCH_TARGET_METHOD_DEFAULT:
134 case PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO:
135 return pf_server_parse_target_from_routing_token(
136 context, settings, FreeRDP_ServerHostname, FreeRDP_ServerPort);
138 case PROXY_FETCH_TARGET_METHOD_CONFIG:
140 WINPR_ASSERT(config);
142 if (config->TargetPort > 0)
154 config->TargetTlsSecLevel))
159 PROXY_LOG_ERR(TAG, ps,
"strdup failed!");
163 if (config->TargetUser)
169 if (config->TargetDomain)
175 if (config->TargetPassword)
178 config->TargetPassword))
183 config->TargetSmartcardAuth))
186 if (config->TargetSmartcardCert)
191 config->TargetSmartcardCert))
195 if (config->TargetSmartcardKey)
200 config->TargetSmartcardKey))
206 case PROXY_FETCH_TARGET_USE_CUSTOM_ADDR:
208 if (!ev.target_address)
212 "router: using CUSTOM_ADDR fetch method, but target_address == nullptr");
218 PROXY_LOG_ERR(TAG, ps,
"strdup failed!");
222 free(ev.target_address);
226 PROXY_LOG_ERR(TAG, ps,
"unknown target fetch method: %u", ev.fetch_method);
234static BOOL pf_server_setup_channels(freerdp_peer* peer)
237 char** accepted_channels =
nullptr;
238 size_t accepted_channels_count = 0;
239 pServerContext* ps = (pServerContext*)peer->context;
241 accepted_channels = WTSGetAcceptedChannelNames(peer, &accepted_channels_count);
242 if (!accepted_channels)
245 for (
size_t i = 0; i < accepted_channels_count; i++)
247 pServerStaticChannelContext* channelContext =
nullptr;
248 const char* cname = accepted_channels[i];
249 UINT16 channelId = WTSChannelGetId(peer, cname);
251 PROXY_LOG_INFO(TAG, ps,
"Accepted channel: %s (%" PRIu16
")", cname, channelId);
252 channelContext = StaticChannelContext_new(ps, cname, channelId);
255 PROXY_LOG_ERR(TAG, ps,
"error setting up channelContext for '%s'", cname);
259 if ((strcmp(cname, DRDYNVC_SVC_CHANNEL_NAME) == 0) &&
260 (channelContext->channelMode == PF_UTILS_CHANNEL_INTERCEPT))
262 if (!pf_channel_setup_drdynvc(ps->pdata, channelContext))
264 PROXY_LOG_ERR(TAG, ps,
"error while setting up dynamic channel");
265 StaticChannelContext_free(channelContext);
269 else if (strcmp(cname, RDPDR_SVC_CHANNEL_NAME) == 0 &&
270 (channelContext->channelMode == PF_UTILS_CHANNEL_INTERCEPT))
272 if (!pf_channel_setup_rdpdr(ps, channelContext))
274 PROXY_LOG_ERR(TAG, ps,
"error while setting up redirection channel");
275 StaticChannelContext_free(channelContext);
281 if (!pf_channel_setup_generic(channelContext))
283 PROXY_LOG_ERR(TAG, ps,
"error while setting up generic channel");
284 StaticChannelContext_free(channelContext);
289 if (!HashTable_Insert(ps->channelsByFrontId, &channelContext->front_channel_id,
292 StaticChannelContext_free(channelContext);
293 PROXY_LOG_ERR(TAG, ps,
"error inserting channelContext in byId table for '%s'", cname);
300 free((
void*)accepted_channels);
314static BOOL pf_server_post_connect(freerdp_peer* peer)
316 pServerContext* ps =
nullptr;
317 pClientContext* pc =
nullptr;
318 rdpSettings* client_settings =
nullptr;
319 proxyData* pdata =
nullptr;
320 rdpSettings* frontSettings =
nullptr;
324 ps = (pServerContext*)peer->context;
327 frontSettings = peer->context->settings;
328 WINPR_ASSERT(frontSettings);
334 PROXY_LOG_INFO(TAG, ps,
"Accepted client: %s", ClientHostname);
335 if (!pf_server_setup_channels(peer))
337 PROXY_LOG_ERR(TAG, ps,
"error setting up channels");
341 pc = pf_context_create_client_context(frontSettings);
344 PROXY_LOG_ERR(TAG, ps,
"failed to create client context!");
348 client_settings = pc->context.settings;
351 proxy_data_set_client_context(pdata, pc);
353 if (!pf_server_get_target_info(peer->context, client_settings, pdata->config))
355 PROXY_LOG_INFO(TAG, ps,
"pf_server_get_target_info failed!");
359 PROXY_LOG_INFO(TAG, ps,
"remote target is %s:%" PRIu32
"",
363 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_POST_CONNECT, pdata, peer))
367 if (!(pdata->client_thread = CreateThread(
nullptr, 0, pf_client_start, pc, 0,
nullptr)))
369 PROXY_LOG_ERR(TAG, ps,
"failed to create client thread");
377static BOOL pf_server_activate(freerdp_peer* peer)
379 pServerContext* ps =
nullptr;
380 proxyData* pdata =
nullptr;
381 rdpSettings* settings =
nullptr;
385 ps = (pServerContext*)peer->context;
391 settings = peer->context->settings;
395 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_ACTIVATE, pdata, peer))
402static BOOL pf_server_logon(freerdp_peer* peer,
const SEC_WINNT_AUTH_IDENTITY* identity,
405 pServerContext* ps =
nullptr;
406 proxyData* pdata =
nullptr;
411 ps = (pServerContext*)peer->context;
416 WINPR_ASSERT(identity);
418 info.identity = identity;
419 info.automatic = automatic;
420 return (pf_modules_run_filter(pdata->module, FILTER_TYPE_SERVER_PEER_LOGON, pdata, &info));
424static BOOL pf_server_adjust_monitor_layout(WINPR_ATTR_UNUSED freerdp_peer* peer)
432static BOOL pf_server_receive_channel_data_hook(freerdp_peer* peer, UINT16 channelId,
433 const BYTE* data,
size_t size, UINT32 flags,
436 UINT64 channelId64 = channelId;
440 pServerContext* ps = (pServerContext*)peer->context;
443 proxyData* pdata = ps->pdata;
446 pClientContext* pc = pdata->pc;
457 const pServerStaticChannelContext* channel =
458 HashTable_GetItemValue(ps->channelsByFrontId, &channelId64);
461 PROXY_LOG_ERR(TAG, ps,
"channel id=%" PRIu64
" not registered here, dropping",
466 WINPR_ASSERT(channel->onFrontData);
467 switch (channel->onFrontData(pdata, channel, data, size, flags, totalSize))
469 case PF_CHANNEL_RESULT_PASS:
473 ev.channel_id = channelId;
474 ev.channel_name = channel->channel_name;
478 ev.total_size = totalSize;
479 return IFCALLRESULT(TRUE, pc->sendChannelData, pc, &ev);
481 case PF_CHANNEL_RESULT_DROP:
483 case PF_CHANNEL_RESULT_ERROR:
489 WINPR_ASSERT(pdata->server_receive_channel_data_original);
490 return pdata->server_receive_channel_data_original(peer, channelId, data, size, flags,
495static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
499 pServerContext* ps = (pServerContext*)peer->context;
503 rdpSettings* settings = peer->context->settings;
504 WINPR_ASSERT(settings);
506 proxyData* pdata = proxy_data_new();
509 proxyServer* server = (proxyServer*)peer->ContextExtra;
510 WINPR_ASSERT(server);
511 proxy_data_set_server_context(pdata, ps);
513 pdata->module = server->module;
514 const proxyConfig* config = pdata->config = server->config;
516 rdpPrivateKey* key = freerdp_key_new_from_pem_enc(config->PrivateKeyPEM,
nullptr);
523 rdpCertificate* cert = freerdp_certificate_new_from_pem(config->CertificatePEM);
539 ZeroMemory(OrderSupport, 32);
542 WINPR_ASSERT(peer->context->update);
543 peer->context->update->autoCalculateBitmapData = FALSE;
550 if (pf_utils_is_passthrough(config))
556 if (config->RemoteApp)
559 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
560 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
561 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
562 RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
563 RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
578 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
599 peer->PostConnect = pf_server_post_connect;
600 peer->Activate = pf_server_activate;
601 peer->Logon = pf_server_logon;
602 peer->AdjustMonitorsLayout = pf_server_adjust_monitor_layout;
605 pdata->server_receive_channel_data_original = peer->ReceiveChannelData;
606 peer->ReceiveChannelData = pf_server_receive_channel_data_hook;
609 pf_server_register_input_callbacks(peer->context->input);
610 pf_server_register_update_callbacks(peer->context->update);
612 return (stream_dump_register_handlers(peer->context, CONNECTION_STATE_NEGO, TRUE));
621static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
623 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = WINPR_C_ARRAY_INIT;
624 pServerContext* ps =
nullptr;
625 proxyData* pdata =
nullptr;
626 peer_thread_args* args = arg;
630 freerdp_peer* client = args->client;
631 WINPR_ASSERT(client);
633 proxyServer* server = (proxyServer*)client->ContextExtra;
634 WINPR_ASSERT(server);
636 ArrayList_Lock(server->peer_list);
637 size_t count = ArrayList_Count(server->peer_list);
638 ArrayList_Unlock(server->peer_list);
640 if (!pf_context_init_server_context(client))
643 if (!pf_server_initialize_peer_connection(client))
646 ps = (pServerContext*)client->context;
648 PROXY_LOG_DBG(TAG, ps,
"Added peer, %" PRIuz
" connected", count);
653 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_INITIALIZE, pdata, client))
656 WINPR_ASSERT(client->Initialize);
657 if (!client->Initialize(client))
660 PROXY_LOG_INFO(TAG, ps,
"new connection: proxy address: %s, client address: %s",
661 pdata->config->Host, client->hostname);
663 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_STARTED, pdata, client))
668 HANDLE ChannelEvent = INVALID_HANDLE_VALUE;
669 DWORD eventCount = 0;
671 WINPR_ASSERT(client->GetEventHandles);
672 const DWORD tmp = client->GetEventHandles(client, &eventHandles[eventCount],
673 ARRAYSIZE(eventHandles) - eventCount);
677 PROXY_LOG_ERR(TAG, ps,
"Failed to get FreeRDP transport event handles");
684 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm);
686 WINPR_ASSERT(ChannelEvent && (ChannelEvent != INVALID_HANDLE_VALUE));
687 WINPR_ASSERT(pdata->abort_event && (pdata->abort_event != INVALID_HANDLE_VALUE));
688 eventHandles[eventCount++] = ChannelEvent;
689 eventHandles[eventCount++] = pdata->abort_event;
690 eventHandles[eventCount++] = server->stopEvent;
692 const DWORD status = WaitForMultipleObjects(
693 eventCount, eventHandles, FALSE, 1000);
695 if (status == WAIT_FAILED)
697 PROXY_LOG_ERR(TAG, ps,
"WaitForMultipleObjects failed (status: %" PRIu32
")", status);
701 WINPR_ASSERT(client->CheckFileDescriptor);
702 if (client->CheckFileDescriptor(client) != TRUE)
705 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
707 if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
709 PROXY_LOG_ERR(TAG, ps,
"WTSVirtualChannelManagerCheckFileDescriptor failure");
715 if (proxy_data_shall_disconnect(pdata))
717 PROXY_LOG_INFO(TAG, ps,
"abort event is set, closing connection with peer %s",
722 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
724 PROXY_LOG_INFO(TAG, ps,
"Server shutting down, terminating peer");
728 switch (WTSVirtualChannelManagerGetDrdynvcState(ps->vcm))
731 case DRDYNVC_STATE_NONE:
734 if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
736 PROXY_LOG_ERR(TAG, ps,
"Failed to initialize drdynvc channel");
742 case DRDYNVC_STATE_READY:
743 if (WaitForSingleObject(ps->dynvcReady, 0) == WAIT_TIMEOUT)
745 (void)SetEvent(ps->dynvcReady);
757 PROXY_LOG_INFO(TAG, ps,
"starting shutdown of connection");
758 PROXY_LOG_INFO(TAG, ps,
"stopping proxy's client");
761 proxy_data_abort_connect(pdata);
763 (void)pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_END, pdata, client);
765 PROXY_LOG_INFO(TAG, ps,
"freeing server's channels");
767 WINPR_ASSERT(client->Close);
768 client->Close(client);
770 WINPR_ASSERT(client->Disconnect);
771 client->Disconnect(client);
774 PROXY_LOG_INFO(TAG, ps,
"freeing proxy data");
776 if (pdata && pdata->client_thread)
778 proxy_data_abort_connect(pdata);
779 (void)WaitForSingleObject(pdata->client_thread, INFINITE);
783 ArrayList_Lock(server->peer_list);
784 ArrayList_Remove(server->peer_list, args->thread);
785 count = ArrayList_Count(server->peer_list);
786 ArrayList_Unlock(server->peer_list);
788 PROXY_LOG_DBG(TAG, ps,
"Removed peer, %" PRIuz
" connected", count);
789 freerdp_peer_context_free(client);
790 freerdp_peer_free(client);
791 proxy_data_free(pdata);
793#if defined(WITH_DEBUG_EVENTS)
802static BOOL pf_server_start_peer(freerdp_peer* client)
804 HANDLE hThread =
nullptr;
805 proxyServer* server =
nullptr;
806 peer_thread_args* args = calloc(1,
sizeof(peer_thread_args));
810 WINPR_ASSERT(client);
811 args->client = client;
813 server = (proxyServer*)client->ContextExtra;
814 WINPR_ASSERT(server);
816 hThread = CreateThread(
nullptr, 0, pf_server_handle_peer, args, CREATE_SUSPENDED,
nullptr);
823 args->thread = hThread;
824 ArrayList_Lock(server->peer_list);
825 const BOOL appended = ArrayList_Append(server->peer_list, hThread);
826 ArrayList_Unlock(server->peer_list);
829 (void)CloseHandle(hThread);
834 return ResumeThread(hThread) != (DWORD)-1;
838static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* client)
840 WINPR_ASSERT(listener);
841 WINPR_ASSERT(client);
843 client->ContextExtra = listener->info;
845 return pf_server_start_peer(client);
848BOOL pf_server_start(proxyServer* server)
852 WINPR_ASSERT(server);
854 if (!WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()))
857 if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT))
860 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
863 WINPR_ASSERT(server->config);
864 WINPR_ASSERT(server->listener);
865 WINPR_ASSERT(server->listener->Open);
866 if (!server->listener->Open(server->listener, server->config->Host, server->config->Port))
871 WLog_ERR(TAG,
"failed to start listener: address already in use!");
874 WLog_ERR(TAG,
"failed to start listener: insufficient permissions!");
877 WLog_ERR(TAG,
"failed to start listener: errno=%d", errno);
891BOOL pf_server_start_from_socket(proxyServer* server,
int socket)
895 WINPR_ASSERT(server);
897 if (!WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi()))
900 if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT))
903 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
906 WINPR_ASSERT(server->listener);
907 WINPR_ASSERT(server->listener->OpenFromSocket);
908 if (!server->listener->OpenFromSocket(server->listener, socket))
913 WLog_ERR(TAG,
"failed to start listener: address already in use!");
916 WLog_ERR(TAG,
"failed to start listener: insufficient permissions!");
919 WLog_ERR(TAG,
"failed to start listener: errno=%d", errno);
933BOOL pf_server_start_with_peer_socket(proxyServer* server,
int socket)
935 struct sockaddr_storage peer_addr;
936 socklen_t len =
sizeof(peer_addr);
937 freerdp_peer* client =
nullptr;
939 WINPR_ASSERT(server);
941 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
944 client = freerdp_peer_new(socket);
948 if (getpeername(socket, (
struct sockaddr*)&peer_addr, &len) != 0)
951 if (!freerdp_peer_set_local_and_hostname(client, &peer_addr))
954 client->ContextExtra = server;
956 if (!pf_server_start_peer(client))
962 WLog_ERR(TAG,
"PeerAccepted callback failed");
963 freerdp_peer_free(client);
968static BOOL are_all_required_modules_loaded(proxyModule* module,
const proxyConfig* config)
974 if (!pf_modules_is_plugin_loaded(module, plugin_name))
976 WLog_ERR(TAG,
"Required plugin '%s' is not loaded. stopping.", plugin_name);
984static void peer_free(
void* obj)
986 HANDLE hdl = (HANDLE)obj;
987 (void)CloseHandle(hdl);
990proxyServer* pf_server_new(
const proxyConfig* config)
993 proxyServer* server =
nullptr;
995 WINPR_ASSERT(config);
997 server = calloc(1,
sizeof(proxyServer));
1004 server->module = pf_modules_new(FREERDP_PROXY_PLUGINDIR,
pf_config_modules(server->config),
1006 if (!server->module)
1008 WLog_ERR(TAG,
"failed to initialize proxy modules!");
1012 if (!pf_modules_list_loaded_plugins(server->module))
1015 if (!are_all_required_modules_loaded(server->module, server->config))
1018 server->stopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1019 if (!server->stopEvent)
1022 server->listener = freerdp_listener_new();
1023 if (!server->listener)
1026 server->peer_list = ArrayList_New(FALSE);
1027 if (!server->peer_list)
1030 obj = ArrayList_Object(server->peer_list);
1035 server->listener->info = server;
1036 server->listener->PeerAccepted = pf_server_peer_accepted;
1038 if (!pf_modules_add(server->module,
pf_config_plugin, (
void*)server->config))
1044 WINPR_PRAGMA_DIAG_PUSH
1045 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1046 pf_server_free(server);
1047 WINPR_PRAGMA_DIAG_POP
1051BOOL pf_server_run(proxyServer* server)
1054 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = WINPR_C_ARRAY_INIT;
1055 DWORD eventCount = 0;
1057 freerdp_listener* listener =
nullptr;
1059 WINPR_ASSERT(server);
1061 listener = server->listener;
1062 WINPR_ASSERT(listener);
1066 WINPR_ASSERT(listener->GetEventHandles);
1067 eventCount = listener->GetEventHandles(listener, eventHandles, ARRAYSIZE(eventHandles));
1069 if ((0 == eventCount) || (eventCount >= ARRAYSIZE(eventHandles)))
1071 WLog_ERR(TAG,
"Failed to get FreeRDP event handles");
1075 WINPR_ASSERT(server->stopEvent);
1076 eventHandles[eventCount++] = server->stopEvent;
1077 status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, 1000);
1079 if (WAIT_FAILED == status)
1082 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
1085 if (WAIT_FAILED == status)
1087 WLog_ERR(TAG,
"select failed");
1092 WINPR_ASSERT(listener->CheckFileDescriptor);
1093 if (listener->CheckFileDescriptor(listener) != TRUE)
1095 WLog_ERR(TAG,
"Failed to accept new peer");
1101 WINPR_ASSERT(listener->Close);
1102 listener->Close(listener);
1106void pf_server_stop(proxyServer* server)
1113 (void)SetEvent(server->stopEvent);
1116void pf_server_free(proxyServer* server)
1121 pf_server_stop(server);
1123 if (server->peer_list)
1125 while (ArrayList_Count(server->peer_list) > 0)
1137 ArrayList_Free(server->peer_list);
1138 freerdp_listener_free(server->listener);
1140 if (server->stopEvent)
1141 (void)CloseHandle(server->stopEvent);
1144 pf_modules_free(server->module);
1147#if defined(WITH_DEBUG_EVENTS)
1152BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep,
void* userdata)
1154 WINPR_ASSERT(server);
1157 return pf_modules_add(server->module, ep, userdata);
FREERDP_API void pf_server_config_free(proxyConfig *config)
pf_server_config_free Releases all resources associated with proxyConfig
WINPR_ATTR_NODISCARD FREERDP_API const char ** pf_config_modules(const proxyConfig *config)
pf_config_modules
WINPR_ATTR_NODISCARD FREERDP_API const char * pf_config_required_plugin(const proxyConfig *config, size_t index)
pf_config_required_plugin
WINPR_ATTR_NODISCARD FREERDP_API size_t pf_config_modules_count(const proxyConfig *config)
pf_config_modules_count
WINPR_ATTR_NODISCARD FREERDP_API BOOL pf_config_clone(proxyConfig **dst, const proxyConfig *config)
pf_config_clone Create a copy of the configuration
WINPR_ATTR_NODISCARD FREERDP_API size_t pf_config_required_plugins_count(const proxyConfig *config)
pf_config_required_plugins_count
WINPR_ATTR_NODISCARD FREERDP_API BOOL pf_config_plugin(proxyPluginsManager *plugins_manager, void *userdata)
pf_config_plugin Register a proxy plugin handling event filtering defined in the configuration.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val, size_t len)
Sets a string settings value. The val is copied.
WINPR_ATTR_NODISCARD FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree