diff --git a/channels/rdpsnd/client/CMakeLists.txt b/channels/rdpsnd/client/CMakeLists.txt index fa1813e41..7a3ee2ccb 100644 --- a/channels/rdpsnd/client/CMakeLists.txt +++ b/channels/rdpsnd/client/CMakeLists.txt @@ -61,8 +61,4 @@ if(WITH_SNDIO) add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "sndio" "") endif() -if (WITH_SERVER) - add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "proxy" "") -endif() - add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "fake" "") diff --git a/channels/rdpsnd/client/proxy/CMakeLists.txt b/channels/rdpsnd/client/proxy/CMakeLists.txt deleted file mode 100644 index aaad6275f..000000000 --- a/channels/rdpsnd/client/proxy/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# FreeRDP: A Remote Desktop Protocol Implementation -# FreeRDP cmake build script -# -# Copyright 2019 Armin Novak -# Copyright 2019 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. - -define_channel_client_subsystem("rdpsnd" "proxy" "") - -set(${MODULE_PREFIX}_SRCS - rdpsnd_proxy.c) - -include_directories(..) - -add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") - -if(NOT BUILTIN_CHANNELS) - list(APPEND ${MODULE_PREFIX}_LIBS freerdp-client) -endif() -list(APPEND ${MODULE_PREFIX}_LIBS freerdp) -list(APPEND ${MODULE_PREFIX}_LIBS winpr) - -target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) - -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/proxy") diff --git a/channels/rdpsnd/client/proxy/rdpsnd_proxy.c b/channels/rdpsnd/client/proxy/rdpsnd_proxy.c deleted file mode 100644 index 01a8d47ee..000000000 --- a/channels/rdpsnd/client/proxy/rdpsnd_proxy.c +++ /dev/null @@ -1,144 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP rdpsnd proxy subsystem - * - * Copyright 2019 Kobi Mizrachi - * - * 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 - -#include -#include -#include -#include -#include -#include -#include - -#include "rdpsnd_main.h" -#include - -typedef struct rdpsnd_proxy_plugin rdpsndProxyPlugin; - -struct rdpsnd_proxy_plugin -{ - rdpsndDevicePlugin device; - RdpsndServerContext* rdpsnd_server; -}; - -static BOOL rdpsnd_proxy_open(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format, - UINT32 latency) -{ - rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device; - - /* update proxy's rdpsnd server latency */ - proxy->rdpsnd_server->latency = latency; - return TRUE; -} - -static void rdpsnd_proxy_close(rdpsndDevicePlugin* device) -{ - /* do nothing */ -} - -static BOOL rdpsnd_proxy_set_volume(rdpsndDevicePlugin* device, UINT32 value) -{ - rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device; - proxy->rdpsnd_server->SetVolume(proxy->rdpsnd_server, value, value); - return TRUE; -} - -static void rdpsnd_proxy_free(rdpsndDevicePlugin* device) -{ - rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device; - - if (!proxy) - return; - - free(proxy); -} - -static BOOL rdpsnd_proxy_format_supported(rdpsndDevicePlugin* device, const AUDIO_FORMAT* format) -{ - rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device; - - /* use the same format that proxy's server used */ - if (proxy->rdpsnd_server->selected_client_format == format->wFormatTag) - return TRUE; - - return FALSE; -} - -static UINT rdpsnd_proxy_play(rdpsndDevicePlugin* device, const BYTE* data, size_t size) -{ - rdpsndProxyPlugin* proxy = (rdpsndProxyPlugin*)device; - UINT64 start = GetTickCount(); - proxy->rdpsnd_server->SendSamples(proxy->rdpsnd_server, data, size / 4, start); - return GetTickCount() - start; -} - - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ - -#ifdef BUILTIN_CHANNELS -#define freerdp_rdpsnd_client_subsystem_entry proxy_freerdp_rdpsnd_client_subsystem_entry -#else -#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry -#endif - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) -{ - const ADDIN_ARGV* args; - rdpsndProxyPlugin* proxy; - pClientContext* pc; - proxy = (rdpsndProxyPlugin*)calloc(1, sizeof(rdpsndProxyPlugin)); - - if (!proxy) - return CHANNEL_RC_NO_MEMORY; - - proxy->device.Open = rdpsnd_proxy_open; - proxy->device.FormatSupported = rdpsnd_proxy_format_supported; - proxy->device.SetVolume = rdpsnd_proxy_set_volume; - proxy->device.Play = rdpsnd_proxy_play; - proxy->device.Close = rdpsnd_proxy_close; - proxy->device.Free = rdpsnd_proxy_free; - args = pEntryPoints->args; - - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, &proxy->device); - pc = (pClientContext*)freerdp_rdpsnd_get_context(pEntryPoints->rdpsnd); - if (pc == NULL) - { - free(proxy); - return ERROR_INTERNAL_ERROR; - } - - proxy->rdpsnd_server = pc->pdata->ps->rdpsnd; - return CHANNEL_RC_OK; -} diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c index 29c61f56f..ab2f954ee 100644 --- a/client/Sample/tf_freerdp.c +++ b/client/Sample/tf_freerdp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -390,6 +391,9 @@ int main(int argc, char* argv[]) goto fail; } + if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CONNECT)) + goto fail; + if (freerdp_client_start(context) != 0) goto fail; diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c index 7231927aa..82bc66354 100644 --- a/client/X11/cli/xfreerdp.c +++ b/client/X11/cli/xfreerdp.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -70,6 +71,9 @@ int main(int argc, char* argv[]) goto out; } + if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CONNECT)) + goto out; + if (freerdp_client_start(context) != 0) goto out; diff --git a/client/common/file.c b/client/common/file.c index 896f5e5d1..b39d4d3b5 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -32,6 +32,7 @@ #include #include +#include /** * Remote Desktop Plus - Overview of .rdp file settings: @@ -1023,10 +1024,12 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); file->RedirectSmartCards = freerdp_settings_get_bool(settings, FreeRDP_RedirectSmartCards); - redirectCameras = freerdp_client_channel_args_to_string(settings, "rdpecam", "device:"); + redirectCameras = + freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "device:"); if (redirectCameras) { - char* str = freerdp_client_channel_args_to_string(settings, "rdpecam", "encode:"); + char* str = + freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "encode:"); file->EncodeRedirectedVideoCapture = 0; if (str) { @@ -1038,7 +1041,7 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett } free(str); - str = freerdp_client_channel_args_to_string(settings, "rdpecam", "quality:"); + str = freerdp_client_channel_args_to_string(settings, RDPECAM_DVC_CHANNEL_NAME, "quality:"); file->RedirectedVideoCaptureEncodingQuality = 0; if (str) { @@ -1994,7 +1997,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* if (~((size_t)file->RedirectCameras)) { BOOL status; - ADDIN_ARGV* args = rdp_file_to_args("rdpecam", file->RedirectCameras); + ADDIN_ARGV* args = rdp_file_to_args(RDPECAM_DVC_CHANNEL_NAME, file->RedirectCameras); if (!args) return FALSE; diff --git a/client/common/test/TestClientRdpFile.c b/client/common/test/TestClientRdpFile.c index 117140439..024b106d5 100644 --- a/client/common/test/TestClientRdpFile.c +++ b/client/common/test/TestClientRdpFile.c @@ -8,6 +8,7 @@ #include #include +#include static const BYTE testRdpFileUTF16[] = { 0xff, 0xfe, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, @@ -162,7 +163,7 @@ static const BYTE testRdpFileUTF16[] = { 0x65, 0x00, 0x0d, 0x00, 0x0a, 0x00 }; -static const char* camera_args[] = { "rdpecam", +static const char* camera_args[] = { RDPECAM_DVC_CHANNEL_NAME, "device:*", "device:\\?\\usb#vid_0bda&pid_58b0&mi", "device:-\\?\\usb#vid_0bdc&pid_58b1&mi", @@ -426,7 +427,7 @@ int TestClientRdpFile(int argc, char* argv[]) iValue); goto fail; } - args = freerdp_dynamic_channel_collection_find(settings, "rdpecam"); + args = freerdp_dynamic_channel_collection_find(settings, RDPECAM_DVC_CHANNEL_NAME); if (!args) { printf("rdpecam channel was not loaded"); diff --git a/server/proxy/pf_gdi.h b/include/freerdp/channels/rdpecam.h similarity index 61% rename from server/proxy/pf_gdi.h rename to include/freerdp/channels/rdpecam.h index b419e5ee3..64daf5b9e 100644 --- a/server/proxy/pf_gdi.h +++ b/include/freerdp/channels/rdpecam.h @@ -1,10 +1,9 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server + * Video Optimized Remoting Virtual Channel Extension * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg + * 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. @@ -19,11 +18,10 @@ * limitations under the License. */ -#ifndef FREERDP_SERVER_PROXY_PFGDI_H -#define FREERDP_SERVER_PROXY_PFGDI_H +#ifndef FREERDP_CHANNEL_RDPECAM_H +#define FREERDP_CHANNEL_RDPECAM_H -#include +#define RDPECAM_DVC_CHANNEL_NAME "rdpecam" +#define RDPECAM_CONTROL_DVC_CHANNEL_NAME "RDCamera_Device_Enumerator" -void pf_gdi_register_update_callbacks(rdpUpdate* update); - -#endif /* FREERDP_SERVER_PROXY_PFGDI_H */ +#endif /* FREERDP_CHANNEL_RDPECAM_H */ diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index b413b1de4..066613495 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -57,6 +57,8 @@ typedef RDP_CLIENT_ENTRY_POINTS_V1 RDP_CLIENT_ENTRY_POINTS; #include #include +typedef struct stream_dump_context rdpStreamDumpContext; + #ifdef __cplusplus extern "C" { @@ -302,7 +304,9 @@ extern "C" ALIGN64 int disconnectUltimatum; /* 45 */ UINT64 paddingC[64 - 46]; /* 46 */ - UINT64 paddingD[96 - 64]; /* 64 */ + ALIGN64 rdpStreamDumpContext* dump; /* 64 */ + + UINT64 paddingD[96 - 65]; /* 65 */ UINT64 paddingE[128 - 96]; /* 96 */ }; diff --git a/include/freerdp/server/proxy/proxy_config.h b/include/freerdp/server/proxy/proxy_config.h index 65c995b3b..61cc26139 100644 --- a/include/freerdp/server/proxy/proxy_config.h +++ b/include/freerdp/server/proxy/proxy_config.h @@ -24,6 +24,7 @@ #include #include +#include typedef struct proxy_config proxyConfig; @@ -41,6 +42,7 @@ struct proxy_config /* input */ BOOL Keyboard; BOOL Mouse; + BOOL Multitouch; /* server security */ BOOL ServerTlsSecurity; @@ -58,7 +60,11 @@ struct proxy_config BOOL DisplayControl; BOOL Clipboard; BOOL AudioOutput; + BOOL AudioInput; BOOL RemoteApp; + BOOL DeviceRedirection; + BOOL VideoRedirection; + BOOL CameraRedirection; BOOL PassthroughIsBlacklist; char** Passthrough; @@ -186,6 +192,17 @@ extern "C" */ FREERDP_API BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config); + /** + * @brief pf_config_plugin Register a proxy plugin handling event filtering + * defined in the configuration. + * + * @param plugins_manager + * @param userdata A proxyConfig* to use as reference + * + * @return TRUE for success, FALSE for failure + */ + FREERDP_API BOOL pf_config_plugin(proxyPluginsManager* plugins_manager, void* userdata); + #ifdef __cplusplus }; #endif diff --git a/include/freerdp/server/proxy/proxy_context.h b/include/freerdp/server/proxy/proxy_context.h index 1512da082..dc873379c 100644 --- a/include/freerdp/server/proxy/proxy_context.h +++ b/include/freerdp/server/proxy/proxy_context.h @@ -24,15 +24,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include @@ -53,12 +44,6 @@ struct p_server_context HANDLE vcm; HANDLE dynvcReady; - - RailServerContext* rail; - RdpgfxServerContext* gfx; - DispServerContext* disp; - CliprdrServerContext* cliprdr; - RdpsndServerContext* rdpsnd; }; typedef struct p_server_context pServerContext; @@ -73,13 +58,6 @@ struct p_client_context proxyData* pdata; - RdpeiClientContext* rdpei; - RdpgfxClientContext* gfx_proxy; - RdpgfxClientContext* gfx_decoder; - DispClientContext* disp; - CliprdrClientContext* cliprdr; - RailClientContext* rail; - /* * In a case when freerdp_connect fails, * Used for NLA fallback feature, to check if the server should close the connection. diff --git a/include/freerdp/server/proxy/proxy_modules_api.h b/include/freerdp/server/proxy/proxy_modules_api.h index ea2fcceaf..87cc920b8 100644 --- a/include/freerdp/server/proxy/proxy_modules_api.h +++ b/include/freerdp/server/proxy/proxy_modules_api.h @@ -87,8 +87,9 @@ struct proxy_plugin proxyFilterFn DynamicChannelCreate; /* 132 passthrough drdynvc channel create data */ proxyFilterFn ServerFetchTargetAddr; /* 133 */ proxyFilterFn ServerPeerLogon; /* 134 */ + proxyFilterFn ChannelCreate; /* 135 passthrough drdynvc channel create data */ - UINT64 reserved5[160 - 135]; /* 135-159 */ + UINT64 reserved5[160 - 136]; /* 136-159 */ /* Runtime data fields */ proxyPluginsManager* mgr; /* 160 */ /** Set during plugin registration */ diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 6cb76402b..987dfa8ad 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -741,6 +741,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_PlayRemoteFx (1857) #define FreeRDP_DumpRemoteFxFile (1858) #define FreeRDP_PlayRemoteFxFile (1859) +#define FreeRDP_TransportDump (1860) +#define FreeRDP_TransportDumpFile (1861) +#define FreeRDP_TransportDumpReplay (1862) #define FreeRDP_DeactivateClientDecoding (1863) #define FreeRDP_GatewayUsageMethod (1984) #define FreeRDP_GatewayPort (1985) @@ -1247,7 +1250,9 @@ struct rdp_settings ALIGN64 BOOL PlayRemoteFx; /* 1857 */ ALIGN64 char* DumpRemoteFxFile; /* 1858 */ ALIGN64 char* PlayRemoteFxFile; /* 1859 */ - UINT64 padding1860[1863 - 1860]; /* 1860 */ + ALIGN64 BOOL TransportDump; /* 1860 */ + ALIGN64 char* TransportDumpFile; /* 1861 */ + ALIGN64 BOOL TransportDumpReplay; /* 1862 */ ALIGN64 BOOL DeactivateClientDecoding; /* 1863 */ UINT64 padding1920[1920 - 1864]; /* 1864 */ UINT64 padding1984[1984 - 1920]; /* 1920 */ diff --git a/include/freerdp/streamdump.h b/include/freerdp/streamdump.h new file mode 100644 index 000000000..b073a3894 --- /dev/null +++ b/include/freerdp/streamdump.h @@ -0,0 +1,54 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Interface to dump RDP session data to files + * + * 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_STREAM_DUMP_H +#define FREERDP_STREAM_DUMP_H + +#include +#include + +#include +#include + +typedef struct stream_dump_context rdpStreamDumpContext; + +#ifdef __cplusplus +extern "C" +{ +#endif + + FREERDP_API BOOL stream_dump_read_line(FILE* fp, wStream* s, UINT64* pts, size_t* pOffset); + FREERDP_API BOOL stream_dump_write_line(FILE* fp, wStream* s); + + FREERDP_API SSIZE_T stream_dump_append(const rdpContext* context, const char* name, wStream* s, + size_t* offset); + FREERDP_API SSIZE_T stream_dump_get(const rdpContext* context, const char* name, wStream* s, + size_t* offset, UINT64* pts); + + FREERDP_API BOOL stream_dump_register_handlers(rdpContext* context, CONNECTION_STATE state); + + FREERDP_API rdpStreamDumpContext* stream_dump_new(void); + FREERDP_API void stream_dump_free(rdpStreamDumpContext* dump); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_STREAM_DUMP_H */ diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index 17a858bc9..8d3508588 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -510,6 +510,12 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id) case FreeRDP_ToggleFullscreen: return settings->ToggleFullscreen; + case FreeRDP_TransportDump: + return settings->TransportDump; + + case FreeRDP_TransportDumpReplay: + return settings->TransportDumpReplay; + case FreeRDP_UnicodeInput: return settings->UnicodeInput; @@ -1193,6 +1199,14 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val) settings->ToggleFullscreen = val; break; + case FreeRDP_TransportDump: + settings->TransportDump = val; + break; + + case FreeRDP_TransportDumpReplay: + settings->TransportDumpReplay = val; + break; + case FreeRDP_UnicodeInput: settings->UnicodeInput = val; break; @@ -2420,6 +2434,9 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id) case FreeRDP_TargetNetAddress: return settings->TargetNetAddress; + case FreeRDP_TransportDumpFile: + return settings->TransportDumpFile; + case FreeRDP_Username: return settings->Username; @@ -2637,6 +2654,9 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* case FreeRDP_TargetNetAddress: return update_string(&settings->TargetNetAddress, val, len, cleanup); + case FreeRDP_TransportDumpFile: + return update_string(&settings->TransportDumpFile, val, len, cleanup); + case FreeRDP_Username: return update_string(&settings->Username, val, len, cleanup); diff --git a/libfreerdp/common/settings_str.c b/libfreerdp/common/settings_str.c index 5a038549f..3a05c7b3e 100644 --- a/libfreerdp/common/settings_str.c +++ b/libfreerdp/common/settings_str.c @@ -175,6 +175,8 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_TcpKeepAlive, 0, "FreeRDP_TcpKeepAlive" }, { FreeRDP_TlsSecurity, 0, "FreeRDP_TlsSecurity" }, { FreeRDP_ToggleFullscreen, 0, "FreeRDP_ToggleFullscreen" }, + { FreeRDP_TransportDump, 0, "FreeRDP_TransportDump" }, + { FreeRDP_TransportDumpReplay, 0, "FreeRDP_TransportDumpReplay" }, { FreeRDP_UnicodeInput, 0, "FreeRDP_UnicodeInput" }, { FreeRDP_UnmapButtons, 0, "FreeRDP_UnmapButtons" }, { FreeRDP_UseMultimon, 0, "FreeRDP_UseMultimon" }, @@ -368,6 +370,7 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_ServerHostname, 7, "FreeRDP_ServerHostname" }, { FreeRDP_ShellWorkingDirectory, 7, "FreeRDP_ShellWorkingDirectory" }, { FreeRDP_TargetNetAddress, 7, "FreeRDP_TargetNetAddress" }, + { FreeRDP_TransportDumpFile, 7, "FreeRDP_TransportDumpFile" }, { FreeRDP_Username, 7, "FreeRDP_Username" }, { FreeRDP_WindowTitle, 7, "FreeRDP_WindowTitle" }, { FreeRDP_WmClass, 7, "FreeRDP_WmClass" }, diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index b934e94ee..654257e3b 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -54,6 +54,7 @@ set(${MODULE_PREFIX}_SRCS utils.h bulk.c bulk.h + streamdump.c activation.c activation.h gcc.c diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 8cb6d3217..035d0cca8 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -340,27 +340,31 @@ BOOL rdp_client_connect(rdpRdp* rdp) return FALSE; } - rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO); - - if (!nego_connect(rdp->nego)) + if (!freerdp_settings_get_bool(settings, FreeRDP_TransportDumpReplay)) { - if (!freerdp_get_last_error(rdp->context)) + rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO); + + if (!nego_connect(rdp->nego)) { - freerdp_set_last_error_log(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED); - WLog_ERR(TAG, "Error: protocol security negotiation or connection failure"); + if (!freerdp_get_last_error(rdp->context)) + { + freerdp_set_last_error_log(rdp->context, + FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED); + WLog_ERR(TAG, "Error: protocol security negotiation or connection failure"); + } + + return FALSE; } - return FALSE; - } + SelectedProtocol = nego_get_selected_protocol(rdp->nego); - SelectedProtocol = nego_get_selected_protocol(rdp->nego); - - if ((SelectedProtocol & PROTOCOL_SSL) || (SelectedProtocol == PROTOCOL_RDP)) - { - if ((settings->Username != NULL) && - ((settings->Password != NULL) || - (settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0))) - settings->AutoLogonEnabled = TRUE; + if ((SelectedProtocol & PROTOCOL_SSL) || (SelectedProtocol == PROTOCOL_RDP)) + { + if ((settings->Username != NULL) && + ((settings->Password != NULL) || (settings->RedirectionPassword != NULL && + settings->RedirectionPasswordLength > 0))) + settings->AutoLogonEnabled = TRUE; + } } /* everything beyond this point is event-driven and non blocking */ diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 13c4fd33f..255391cf0 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -45,6 +45,7 @@ #include #include +#include #include #include #include @@ -684,6 +685,10 @@ BOOL freerdp_context_new(freerdp* instance) if (!(context->channels = freerdp_channels_new(instance))) goto fail; + context->dump = stream_dump_new(); + if (!context->dump) + goto fail; + IFCALLRET(instance->ContextNew, ret, instance, instance->context); if (ret) @@ -745,6 +750,9 @@ void freerdp_context_free(freerdp* instance) codecs_free(ctx->codecs); ctx->codecs = NULL; + stream_dump_free(ctx->dump); + ctx->dump = NULL; + free(ctx); instance->context = NULL; instance->settings = NULL; /* owned by rdpRdp */ diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 49927fb28..ae4094cbc 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -30,6 +30,7 @@ #include "certificate.h" #include +#include #include "rdp.h" #include "peer.h" @@ -917,6 +918,9 @@ BOOL freerdp_peer_context_new(freerdp_peer* client) context->ServerMode = TRUE; context->settings = client->settings; + context->dump = stream_dump_new(); + if (!context->dump) + goto fail; if (!(context->metrics = metrics_new(context))) goto fail; @@ -954,8 +958,9 @@ BOOL freerdp_peer_context_new(freerdp_peer* client) client->LicenseCallback = freerdp_peer_nolicense; IFCALLRET(client->ContextNew, ret, client, client->context); - if (ret) - return TRUE; + if (!ret) + goto fail; + return TRUE; fail: WLog_ERR(TAG, "ContextNew callback failed"); @@ -980,6 +985,8 @@ void freerdp_peer_context_free(freerdp_peer* client) ctx->rdp = NULL; metrics_free(ctx->metrics); ctx->metrics = NULL; + stream_dump_free(ctx->dump); + ctx->dump = NULL; free(ctx); } client->context = NULL; diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index 423b0e71a..0cf53a263 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -1335,8 +1335,6 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) } else { - ArrayList_Remove(vcm->dynamicVirtualChannels, channel); - if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED) { ULONG written; @@ -1355,18 +1353,8 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) Stream_Free(s, TRUE); } } + ArrayList_Remove(vcm->dynamicVirtualChannels, channel); } - - if (channel->receiveData) - Stream_Free(channel->receiveData, TRUE); - - if (channel->queue) - { - MessageQueue_Free(channel->queue); - channel->queue = NULL; - } - - free(channel); } return ret; diff --git a/libfreerdp/core/streamdump.c b/libfreerdp/core/streamdump.c new file mode 100644 index 000000000..cdb441767 --- /dev/null +++ b/libfreerdp/core/streamdump.c @@ -0,0 +1,391 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Static Virtual Channel Interface + * + * 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. + */ + +#include +#include +#include + +#include +#include + +struct stream_dump_context +{ + rdpTransportIo io; + size_t writeDumpOffset; + size_t readDumpOffset; + size_t replayOffset; + UINT64 replayTime; + CONNECTION_STATE state; +}; + +BOOL stream_dump_read_line(FILE* fp, wStream* s, UINT64* pts, size_t* pOffset) +{ + BOOL rc = FALSE; + UINT64 ts; + UINT64 size = 0; + size_t r; + + if (!fp || !s) + return FALSE; + + if (pOffset) + _fseeki64(fp, *pOffset, SEEK_SET); + + r = fread(&ts, 1, sizeof(ts), fp); + if (r != sizeof(ts)) + goto fail; + r = fread(&size, 1, sizeof(size), fp); + if (r != sizeof(size)) + goto fail; + if (!Stream_EnsureRemainingCapacity(s, size)) + goto fail; + r = fread(Stream_Pointer(s), 1, size, fp); + if (r != size) + goto fail; + Stream_Seek(s, size); + + if (pOffset) + { + INT64 tmp = _ftelli64(fp); + if (tmp < 0) + goto fail; + *pOffset = (size_t)tmp; + } + + if (pts) + *pts = ts; + rc = TRUE; + +fail: + Stream_SealLength(s); + return rc; +} + +BOOL stream_dump_write_line(FILE* fp, wStream* s) +{ + BOOL rc = FALSE; + const UINT64 t = GetTickCount64(); + const BYTE* data = Stream_Buffer(s); + const UINT64 size = Stream_Length(s); + + if (!fp || !s) + return FALSE; + + { + size_t r = fwrite(&t, 1, sizeof(t), fp); + if (r != sizeof(t)) + goto fail; + r = fwrite(&size, 1, sizeof(size), fp); + if (r != sizeof(size)) + goto fail; + r = fwrite(data, 1, size, fp); + if (r != size) + goto fail; + } + + rc = TRUE; +fail: + return rc; +} + +static FILE* stream_dump_get_file(const rdpSettings* settings, const char* name, const char* mode) +{ + const char* cfolder; + char* folder = NULL; + char* file = NULL; + FILE* fp = NULL; + + if (!settings || !mode) + return NULL; + + cfolder = freerdp_settings_get_string(settings, FreeRDP_TransportDumpFile); + if (!cfolder) + folder = GetKnownSubPath(KNOWN_PATH_TEMP, "freerdp-transport-dump"); + else + folder = _strdup(cfolder); + + if (!folder) + goto fail; + + if (name) + { + char buffer[8192] = { 0 }; + int rc = _snprintf(buffer, sizeof(buffer), "%s.dump", name); + if ((rc <= 0) || ((size_t)rc >= sizeof(buffer))) + goto fail; + + if (!winpr_PathFileExists(folder)) + { + if (!winpr_PathMakePath(folder, NULL)) + goto fail; + } + file = GetCombinedPath(folder, buffer); + } + else + { + if (!winpr_PathFileExists(folder)) + goto fail; + file = _strdup(folder); + } + + if (!file) + goto fail; + + fp = winpr_fopen(file, mode); +fail: + free(folder); + free(file); + return fp; +} + +SSIZE_T stream_dump_append(const rdpContext* context, const char* name, wStream* s, size_t* offset) +{ + SSIZE_T rc = -1; + FILE* fp; + CONNECTION_STATE state = freerdp_get_state(context); + int r; + + if (!context || !s || !offset) + return -1; + + if (state < context->dump->state) + return 0; + + fp = stream_dump_get_file(context->settings, name, "ab"); + if (!fp) + return -1; + + r = _fseeki64(fp, *offset, SEEK_SET); + if (r < 0) + goto fail; + + if (!stream_dump_write_line(fp, s)) + goto fail; + rc = _ftelli64(fp); + if (rc < 0) + goto fail; + *offset = (size_t)rc; +fail: + fclose(fp); + return rc; +} + +SSIZE_T stream_dump_get(const rdpContext* context, const char* name, wStream* s, size_t* offset, + UINT64* pts) +{ + SSIZE_T rc = -1; + FILE* fp; + int r; + + if (!context || !s || !offset) + return -1; + fp = stream_dump_get_file(context->settings, name, "rb"); + if (!fp) + return -1; + r = _fseeki64(fp, *offset, SEEK_SET); + if (r < 0) + goto fail; + + if (!stream_dump_read_line(fp, s, pts, offset)) + goto fail; + + rc = _ftelli64(fp); +fail: + fclose(fp); + return rc; +} + +static int stream_dump_transport_write(rdpTransport* transport, wStream* s) +{ + SSIZE_T r; + rdpContext* ctx = transport_get_context(transport); + + WINPR_ASSERT(ctx); + WINPR_ASSERT(ctx->dump); + WINPR_ASSERT(s); + + r = stream_dump_append(ctx, "write", s, &ctx->dump->writeDumpOffset); + if (r < 0) + return -1; + + WINPR_ASSERT(ctx->dump->io.WritePdu); + return ctx->dump->io.WritePdu(transport, s); +} + +static int stream_dump_transport_read(rdpTransport* transport, wStream* s) +{ + int rc; + rdpContext* ctx = transport_get_context(transport); + + WINPR_ASSERT(ctx); + WINPR_ASSERT(ctx->dump); + WINPR_ASSERT(s); + + WINPR_ASSERT(ctx->dump->io.ReadPdu); + rc = ctx->dump->io.ReadPdu(transport, s); + if (rc > 0) + { + SSIZE_T r = stream_dump_append(ctx, "read", s, &ctx->dump->readDumpOffset); + if (r < 0) + return -1; + } + return rc; +} + +static BOOL stream_dump_register_write_handlers(rdpContext* context) +{ + rdpTransportIo dump; + const rdpTransportIo* dfl = freerdp_get_io_callbacks(context); + + if (!freerdp_settings_get_bool(context->settings, FreeRDP_TransportDump)) + return TRUE; + + WINPR_ASSERT(dfl); + dump = *dfl; + + /* Remember original callbacks for later */ + WINPR_ASSERT(context->dump); + context->dump->io.ReadPdu = dfl->ReadPdu; + context->dump->io.WritePdu = dfl->WritePdu; + + /* Set our dump wrappers */ + dump.WritePdu = stream_dump_transport_write; + dump.ReadPdu = stream_dump_transport_read; + return freerdp_set_io_callbacks(context, &dump); +} + +static int stream_dump_replay_transport_write(rdpTransport* transport, wStream* s) +{ + rdpContext* ctx = transport_get_context(transport); + size_t size; + + WINPR_ASSERT(ctx); + WINPR_ASSERT(s); + + size = Stream_Length(s); + WLog_ERR("abc", "replay write %" PRIuz, size); + // TODO: Compare with write file + + return 1; +} + +static int stream_dump_replay_transport_read(rdpTransport* transport, wStream* s) +{ + rdpContext* ctx = transport_get_context(transport); + + size_t size = 0; + time_t slp = 0; + UINT64 ts = 0; + + WINPR_ASSERT(ctx); + WINPR_ASSERT(ctx->dump); + WINPR_ASSERT(s); + + if (stream_dump_get(ctx, NULL, s, &ctx->dump->replayOffset, &ts) < 0) + return -1; + + if ((ctx->dump->replayTime > 0) && (ts > ctx->dump->replayTime)) + slp = ts - ctx->dump->replayTime; + ctx->dump->replayTime = ts; + + size = Stream_Length(s); + Stream_SetPosition(s, 0); + WLog_ERR("abc", "replay read %" PRIuz, size); + + if (slp > 0) + Sleep(slp); + + return 1; +} + +static int stream_dump_replay_transport_tcp_connect(rdpContext* context, rdpSettings* settings, + const char* hostname, int port, DWORD timeout) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(settings); + WINPR_ASSERT(hostname); + + return 42; +} + +static BOOL stream_dump_replay_transport_tls_connect(rdpTransport* transport) +{ + WINPR_ASSERT(transport); + return TRUE; +} + +static BOOL stream_dump_replay_transport_accept(rdpTransport* transport) +{ + WINPR_ASSERT(transport); + return TRUE; +} + +static BOOL stream_dump_register_read_handlers(rdpContext* context) +{ + rdpTransportIo dump; + const rdpTransportIo* dfl = freerdp_get_io_callbacks(context); + + if (!freerdp_settings_get_bool(context->settings, FreeRDP_TransportDumpReplay)) + return TRUE; + + WINPR_ASSERT(dfl); + dump = *dfl; + + /* Remember original callbacks for later */ + WINPR_ASSERT(context->dump); + context->dump->io.ReadPdu = dfl->ReadPdu; + context->dump->io.WritePdu = dfl->WritePdu; + + /* Set our dump wrappers */ + dump.WritePdu = stream_dump_transport_write; + dump.ReadPdu = stream_dump_transport_read; + + /* Set our dump wrappers */ + dump.WritePdu = stream_dump_replay_transport_write; + dump.ReadPdu = stream_dump_replay_transport_read; + dump.TCPConnect = stream_dump_replay_transport_tcp_connect; + dump.TLSAccept = stream_dump_replay_transport_accept; + dump.TLSConnect = stream_dump_replay_transport_tls_connect; + return freerdp_set_io_callbacks(context, &dump); +} + +BOOL stream_dump_register_handlers(rdpContext* context, CONNECTION_STATE state) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(context->dump); + context->dump->state = state; + if (!stream_dump_register_write_handlers(context)) + return FALSE; + return stream_dump_register_read_handlers(context); +} + +void stream_dump_free(rdpStreamDumpContext* dump) +{ + free(dump); +} + +rdpStreamDumpContext* stream_dump_new(void) +{ + rdpStreamDumpContext* dump = calloc(1, sizeof(rdpStreamDumpContext)); + if (!dump) + return NULL; + + return dump; +} diff --git a/libfreerdp/core/test/CMakeLists.txt b/libfreerdp/core/test/CMakeLists.txt index 9e8be8b14..bc618726b 100644 --- a/libfreerdp/core/test/CMakeLists.txt +++ b/libfreerdp/core/test/CMakeLists.txt @@ -6,6 +6,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS TestVersion.c + TestStreamDump.c TestSettings.c) if(WITH_SAMPLE AND WITH_SERVER) diff --git a/libfreerdp/core/test/TestStreamDump.c b/libfreerdp/core/test/TestStreamDump.c new file mode 100644 index 000000000..3ff2aff0e --- /dev/null +++ b/libfreerdp/core/test/TestStreamDump.c @@ -0,0 +1,97 @@ +#include + +#include +#include +#include + +#include +#include + +static BOOL test_entry_read_write(void) +{ + BOOL rc = FALSE; + FILE* fp = NULL; + wStream *sw = NULL, *sr = NULL; + size_t offset = 0, x; + UINT64 ts = 0; + BYTE tmp[16] = { 0 }; + char tmp2[64] = { 0 }; + char* name = NULL; + size_t entrysize = sizeof(UINT64) + sizeof(UINT64); + + winpr_RAND(tmp, sizeof(tmp)); + + for (x = 0; x < sizeof(tmp); x++) + _snprintf(&tmp2[x * 2], sizeof(tmp2) - 2 * x, "%02" PRIx8, tmp[x]); + name = GetKnownSubPath(KNOWN_PATH_TEMP, tmp2); + if (!name) + { + fprintf(stderr, "[%s] Could not create temporary path\n", __FUNCTION__); + goto fail; + } + + sw = Stream_New(NULL, 8123); + sr = Stream_New(NULL, 1024); + if (!sr || !sw) + { + fprintf(stderr, "[%s] Could not create iostreams sw=%p, sr=%p\n", __FUNCTION__, sw, sr); + goto fail; + } + + winpr_RAND(Stream_Buffer(sw), Stream_Capacity(sw)); + entrysize += Stream_Capacity(sw); + Stream_SetLength(sw, Stream_Capacity(sw)); + + fp = fopen(name, "wb"); + if (!fp) + goto fail; + if (!stream_dump_write_line(fp, sw)) + goto fail; + fclose(fp); + + fp = fopen(name, "rb"); + if (!fp) + goto fail; + if (!stream_dump_read_line(fp, sr, &ts, &offset)) + goto fail; + + if (entrysize != offset) + { + fprintf(stderr, "[%s] offset %" PRIuz " bytes, entrysize %" PRIuz " bytes\n", __FUNCTION__, + offset, entrysize); + goto fail; + } + + if (Stream_Length(sr) != Stream_Capacity(sw)) + { + fprintf(stderr, "[%s] Written %" PRIuz " bytes, read %" PRIuz " bytes\n", __FUNCTION__, + Stream_Length(sr), Stream_Capacity(sw)); + goto fail; + } + + if (memcmp(Stream_Buffer(sw), Stream_Buffer(sr), Stream_Capacity(sw)) != 0) + { + fprintf(stderr, "[%s] Written data does not match data read back\n", __FUNCTION__); + goto fail; + } + rc = TRUE; +fail: + Stream_Free(sr, TRUE); + Stream_Free(sw, TRUE); + fclose(fp); + if (name) + DeleteFileA(name); + free(name); + fprintf(stderr, "xxxxxxxxxxxxx %d\n", rc); + return rc; +} + +int TestStreamDump(int argc, char* argv[]) +{ + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + + if (!test_entry_read_write()) + return -1; + return 0; +} diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index 7eded4eb1..f13099ec2 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -164,6 +164,8 @@ static const size_t bool_list_indices[] = { FreeRDP_TcpKeepAlive, FreeRDP_TlsSecurity, FreeRDP_ToggleFullscreen, + FreeRDP_TransportDump, + FreeRDP_TransportDumpReplay, FreeRDP_UnicodeInput, FreeRDP_UnmapButtons, FreeRDP_UseMultimon, @@ -377,6 +379,7 @@ static const size_t string_list_indices[] = { FreeRDP_ServerHostname, FreeRDP_ShellWorkingDirectory, FreeRDP_TargetNetAddress, + FreeRDP_TransportDumpFile, FreeRDP_Username, FreeRDP_WindowTitle, FreeRDP_WmClass, diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index b586d72a7..c68b338e6 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -36,6 +36,9 @@ #include #include +#include +#include + #include #include #include @@ -60,6 +63,7 @@ struct server_info { BOOL test_dump_rfx_realtime; const char* test_pcap_file; + const char* replay_dump; const char* cert; const char* key; }; @@ -877,6 +881,67 @@ static BOOL tf_peer_suppress_output(rdpContext* context, BYTE allow, const RECTA return TRUE; } +static int hook_peer_write_pdu(rdpTransport* transport, wStream* s) +{ + UINT64 ts = 0; + wStream* ls = NULL; + UINT64 last_ts = 0; + const struct server_info* info; + freerdp_peer* client; + CONNECTION_STATE state; + testPeerContext* peerCtx; + size_t offset = 0; + rdpContext* context = transport_get_context(transport); + + WINPR_ASSERT(context); + WINPR_ASSERT(s); + + client = context->peer; + WINPR_ASSERT(client); + + peerCtx = (testPeerContext*)client->context; + WINPR_ASSERT(peerCtx); + WINPR_ASSERT(peerCtx->io.WritePdu); + + info = client->ContextExtra; + WINPR_ASSERT(info); + + /* Let the client authenticate. + * After that is done, we stop the normal operation and send + * a previously recorded session PDU by PDU to the client. + * + * This is fragile and the connecting client needs to use the same + * configuration as the one that recorded the session! + */ + WINPR_ASSERT(info); + state = freerdp_get_state(context); + if (state < CONNECTION_STATE_NEGO) + return peerCtx->io.WritePdu(transport, s); + + ls = Stream_New(NULL, 4096); + if (!ls) + goto fail; + + while (stream_dump_get(context, NULL, ls, &offset, &ts) > 0) + { + int rc; + if ((last_ts > 0) && (ts > last_ts)) + { + UINT64 diff = ts - last_ts; + Sleep(diff); + } + last_ts = ts; + rc = peerCtx->io.WritePdu(transport, ls); + if (rc < 0) + goto fail; + Stream_SetPosition(ls, 0); + } + +fail: + Stream_Free(ls, TRUE); + return -1; +} + static DWORD WINAPI test_peer_mainloop(LPVOID arg) { BOOL rc; @@ -909,6 +974,16 @@ static DWORD WINAPI test_peer_mainloop(LPVOID arg) /* Initialize the real server settings here */ WINPR_ASSERT(client->settings); + if (info->replay_dump) + { + if (!freerdp_settings_set_bool(client->settings, FreeRDP_TransportDumpReplay, TRUE) || + !freerdp_settings_set_string(client->settings, FreeRDP_TransportDumpFile, + info->replay_dump)) + { + freerdp_peer_free(client); + return 0; + } + } if (!freerdp_settings_set_string(client->settings, FreeRDP_CertificateFile, cert) || !freerdp_settings_set_string(client->settings, FreeRDP_PrivateKeyFile, key) || !freerdp_settings_set_string(client->settings, FreeRDP_RdpKeyFile, key)) @@ -952,6 +1027,18 @@ static DWORD WINAPI test_peer_mainloop(LPVOID arg) context = (testPeerContext*)client->context; WINPR_ASSERT(context); + if (info->replay_dump) + { + const rdpTransportIo* cb = freerdp_get_io_callbacks(client->context); + rdpTransportIo replay; + + WINPR_ASSERT(cb); + replay = *cb; + context->io = *cb; + replay.WritePdu = hook_peer_write_pdu; + freerdp_set_io_callbacks(client->context, &replay); + } + WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname); while (error == CHANNEL_RC_OK) diff --git a/server/Sample/sfreerdp.h b/server/Sample/sfreerdp.h index da7d7b7ac..f686f72d5 100644 --- a/server/Sample/sfreerdp.h +++ b/server/Sample/sfreerdp.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,8 @@ struct test_peer_context UINT32 frame_id; RdpsndServerContext* rdpsnd; EncomspServerContext* encomsp; + + rdpTransportIo io; }; typedef struct test_peer_context testPeerContext; diff --git a/server/proxy/CMakeLists.txt b/server/proxy/CMakeLists.txt index 9d9605ffc..d01fa5420 100644 --- a/server/proxy/CMakeLists.txt +++ b/server/proxy/CMakeLists.txt @@ -25,32 +25,16 @@ set(MODULE_PREFIX "FREERDP_SERVER_PROXY") set(${MODULE_PREFIX}_SRCS pf_context.c - pf_channels.c - pf_channels.h pf_client.c pf_client.h pf_input.c pf_input.h pf_update.c pf_update.h - pf_rail.c - pf_rail.h - pf_rdpgfx.c - pf_rdpgfx.h - pf_disp.c - pf_disp.h pf_server.c pf_server.h - pf_gdi.c - pf_gdi.h pf_config.c - pf_graphics.c - pf_graphics.h pf_modules.c - pf_cliprdr.c - pf_cliprdr.h - pf_rdpsnd.c - pf_rdpsnd.h pf_utils.h pf_utils.c ) diff --git a/server/proxy/pf_channels.c b/server/proxy/pf_channels.c deleted file mode 100644 index fc83db73e..000000000 --- a/server/proxy/pf_channels.c +++ /dev/null @@ -1,340 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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 -#include -#include -#include -#include - -#include - -#include "pf_channels.h" -#include "pf_client.h" -#include -#include -#include "pf_rail.h" -#include "pf_rdpgfx.h" -#include "pf_cliprdr.h" -#include "pf_disp.h" -#include "proxy_modules.h" - -#include "pf_rdpsnd.h" - -#define TAG PROXY_TAG("channels") - -static void pf_channels_wait_for_server_dynvc(pServerContext* ps) -{ - WINPR_ASSERT(ps); - - WLog_DBG(TAG, "pf_channels_wait_for_server_dynvc(): waiting for server's drdynvc to be ready"); - WaitForSingleObject(ps->dynvcReady, INFINITE); - WLog_DBG(TAG, "pf_channels_wait_for_server_dynvc(): server's drdynvc is ready!"); -} - -void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs* e) -{ - pClientContext* pc = (pClientContext*)data; - pServerContext* ps; - - WINPR_ASSERT(pc); - WINPR_ASSERT(pc->pdata); - WINPR_ASSERT(e); - WINPR_ASSERT(e->name); - - ps = pc->pdata->ps; - WINPR_ASSERT(ps); - - PROXY_LOG_INFO(TAG, pc, "Channel connected: %s", e->name); - - if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) - { - pc->rdpei = (RdpeiClientContext*)e->pInterface; - } - else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) - { - if (!ps->rail) - return; - pc->rail = (RailClientContext*)e->pInterface; - - WINPR_ASSERT(ps->rail->Start); - if (ps->rail->Start(ps->rail) != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "failed to start RAIL server"); - return; - } - - pf_rail_pipeline_init(pc->rail, ps->rail, pc->pdata); - } - else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) - { - pf_channels_wait_for_server_dynvc(ps); - if (!ps->gfx) - return; - pc->gfx_proxy = (RdpgfxClientContext*)e->pInterface; - pf_rdpgfx_pipeline_init(pc->gfx_proxy, ps->gfx, pc->pdata); - - WINPR_ASSERT(ps->gfx->Open); - if (!ps->gfx->Open(ps->gfx)) - { - WLog_ERR(TAG, "failed to open GFX server"); - return; - } - - SetEvent(pc->pdata->gfx_server_ready); - } - else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) - { - UINT ret; - - if (!ps->disp) - return; - - WINPR_ASSERT(ps->disp->Open); - ret = ps->disp->Open(ps->disp); - if (ret != CHANNEL_RC_OK) - { - if (ret == ERROR_NOT_FOUND) - { - /* client did not connect with disp */ - return; - } - } - else - { - pf_channels_wait_for_server_dynvc(ps); - if (ps->disp->Open(ps->disp) != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "failed to open disp channel"); - return; - } - } - - pc->disp = (DispClientContext*)e->pInterface; - pf_disp_register_callbacks(pc->disp, ps->disp, pc->pdata); - } - else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) - { - if (!ps->cliprdr) - return; - - WINPR_ASSERT(ps->cliprdr->Start); - if (ps->cliprdr->Start(ps->cliprdr) != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "failed to open cliprdr channel"); - return; - } - - pc->cliprdr = (CliprdrClientContext*)e->pInterface; - pf_cliprdr_register_callbacks(pc->cliprdr, ps->cliprdr, pc->pdata); - } - else if (strcmp(e->name, RDPSND_CHANNEL_NAME) == 0) - { - /* sound is disabled */ - if (ps->rdpsnd == NULL) - return; - - WINPR_ASSERT(ps->rdpsnd->Initialize); - if (ps->rdpsnd->Initialize(ps->rdpsnd, TRUE) != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "failed to open rdpsnd channel"); - return; - } - } -} - -void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEventArgs* e) -{ - rdpContext* context = (rdpContext*)data; - pClientContext* pc = (pClientContext*)data; - pServerContext* ps; - - WINPR_ASSERT(pc); - WINPR_ASSERT(pc->pdata); - WINPR_ASSERT(e); - WINPR_ASSERT(e->name); - - ps = pc->pdata->ps; - WINPR_ASSERT(ps); - WINPR_ASSERT(context); - - PROXY_LOG_INFO(TAG, pc, "Channel disconnected: %s", e->name); - - if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) - { - pc->rdpei = NULL; - } - else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) - { - if (!ps->gfx) - return; - WINPR_ASSERT(ps->gfx->Close); - if (!ps->gfx->Close(ps->gfx)) - WLog_ERR(TAG, "failed to close gfx server"); - - gdi_graphics_pipeline_uninit(context->gdi, pc->gfx_decoder); - rdpgfx_client_context_free(pc->gfx_decoder); - } - else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) - { - if (!ps->rail) - return; - WINPR_ASSERT(ps->rail->Stop); - if (!ps->rail->Stop(ps->rail)) - WLog_ERR(TAG, "failed to close rail server"); - - pc->rail = NULL; - } - else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) - { - if (!ps->disp) - return; - WINPR_ASSERT(ps->disp->Close); - if (ps->disp->Close(ps->disp) != CHANNEL_RC_OK) - WLog_ERR(TAG, "failed to close disp server"); - - pc->disp = NULL; - } - else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) - { - if (!ps->cliprdr) - return; - WINPR_ASSERT(ps->cliprdr->Stop); - if (ps->cliprdr->Stop(ps->cliprdr) != CHANNEL_RC_OK) - WLog_ERR(TAG, "failed to stop cliprdr server"); - - pc->cliprdr = NULL; - } - else if (strcmp(e->name, RDPSND_CHANNEL_NAME) == 0) - { - /* sound is disabled */ - if (ps->rdpsnd == NULL) - return; - - WINPR_ASSERT(ps->rdpsnd->Stop); - if (ps->rdpsnd->Stop(ps->rdpsnd) != CHANNEL_RC_OK) - WLog_ERR(TAG, "failed to close rdpsnd server"); - } -} - -BOOL pf_server_channels_init(pServerContext* ps, freerdp_peer* peer) -{ - rdpContext* context = (rdpContext*)ps; - rdpContext* client; - const proxyConfig* config; - - WINPR_ASSERT(peer); - WINPR_ASSERT(ps); - WINPR_ASSERT(ps->pdata); - WINPR_ASSERT(context); - client = (rdpContext*)ps->pdata->pc; - WINPR_ASSERT(client); - config = ps->pdata->config; - WINPR_ASSERT(config); - - WINPR_ASSERT(context->settings); - - if (context->settings->SupportGraphicsPipeline && config->GFX) - { - if (!pf_server_rdpgfx_init(ps)) - return FALSE; - } - - if (config->DisplayControl) - { - if (!pf_server_disp_init(ps)) - return FALSE; - } - - if (config->Clipboard && - WTSVirtualChannelManagerIsChannelJoined(ps->vcm, CLIPRDR_SVC_CHANNEL_NAME)) - { - client->settings->RedirectClipboard = TRUE; - - if (!pf_server_cliprdr_init(ps)) - return FALSE; - } - - if (config->AudioOutput && - WTSVirtualChannelManagerIsChannelJoined(ps->vcm, RDPSND_CHANNEL_NAME)) - { - if (!pf_server_rdpsnd_init(ps)) - return FALSE; - } - - if (config->RemoteApp && - WTSVirtualChannelManagerIsChannelJoined(ps->vcm, RAIL_SVC_CHANNEL_NAME)) - { - if (!pf_rail_context_init(ps)) - return FALSE; - } - - return pf_modules_run_hook(ps->pdata->module, HOOK_TYPE_SERVER_CHANNELS_INIT, ps->pdata, peer); -} - -void pf_server_channels_free(pServerContext* ps, freerdp_peer* peer) -{ - WINPR_ASSERT(peer); - WINPR_ASSERT(ps); - WINPR_ASSERT(ps->pdata); - - if (ps->gfx) - { - rdpgfx_server_context_free(ps->gfx); - ps->gfx = NULL; - } - - if (ps->disp) - { - disp_server_context_free(ps->disp); - ps->disp = NULL; - } - - if (ps->cliprdr) - { - cliprdr_server_context_free(ps->cliprdr); - ps->cliprdr = NULL; - } - - if (ps->rdpsnd) - { - rdpsnd_server_context_free(ps->rdpsnd); - ps->rdpsnd = NULL; - } - - if (ps->rail) - { - rail_server_context_free(ps->rail); - ps->rail = NULL; - } - - pf_modules_run_hook(ps->pdata->module, HOOK_TYPE_SERVER_CHANNELS_FREE, ps->pdata, peer); -} diff --git a/server/proxy/pf_channels.h b/server/proxy/pf_channels.h deleted file mode 100644 index 3fa79a794..000000000 --- a/server/proxy/pf_channels.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * - * 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_SERVER_PROXY_PFCHANNELS_H -#define FREERDP_SERVER_PROXY_PFCHANNELS_H - -#include -#include - -#include - -void pf_channels_on_client_channel_connect(void* context, ChannelConnectedEventArgs* e); -void pf_channels_on_client_channel_disconnect(void* context, ChannelDisconnectedEventArgs* e); - -BOOL pf_server_channels_init(pServerContext* ps, freerdp_peer* peer); -void pf_server_channels_free(pServerContext* ps, freerdp_peer* peer); - -#endif /* FREERDP_SERVER_PROXY_PFCHANNELS_H */ diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c index 7c659cb6c..922a5e3b2 100644 --- a/server/proxy/pf_client.c +++ b/server/proxy/pf_client.c @@ -33,10 +33,10 @@ #include #include #include +#include +#include +#include -#include "pf_channels.h" -#include "pf_gdi.h" -#include "pf_graphics.h" #include "pf_client.h" #include #include "pf_update.h" @@ -212,9 +212,27 @@ static BOOL pf_client_pre_connect(freerdp* instance) settings->UseMultimon = TRUE; /* Sound */ - settings->AudioPlayback = config->AudioOutput; - if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, "rdpdr")) - settings->DeviceRedirection = TRUE; + if (!freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, config->AudioInput) || + !freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, config->AudioOutput) || + !freerdp_settings_set_bool(settings, FreeRDP_DeviceRedirection, + config->DeviceRedirection) || + !freerdp_settings_set_bool(settings, FreeRDP_SupportDisplayControl, + config->DisplayControl) || + !freerdp_settings_set_bool(settings, FreeRDP_RemoteAssistanceMode, config->RemoteApp) || + !freerdp_settings_set_bool(settings, FreeRDP_MultiTouchInput, config->Multitouch)) + return FALSE; + + if (config->RemoteApp) + { + if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, RAIL_SVC_CHANNEL_NAME)) + settings->RemoteApplicationMode = TRUE; + } + + if (config->DeviceRedirection) + { + if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, RDPDR_SVC_CHANNEL_NAME)) + settings->DeviceRedirection = TRUE; + } /* Display control */ settings->SupportDisplayControl = config->DisplayControl; @@ -223,22 +241,14 @@ static BOOL pf_client_pre_connect(freerdp* instance) if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, ENCOMSP_SVC_CHANNEL_NAME)) settings->EncomspVirtualChannel = TRUE; - if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, CLIPRDR_SVC_CHANNEL_NAME)) - settings->RedirectClipboard = config->Clipboard; + if (config->Clipboard) + { + if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, CLIPRDR_SVC_CHANNEL_NAME)) + settings->RedirectClipboard = config->Clipboard; + } settings->AutoReconnectionEnabled = TRUE; - /** - * Register the channel listeners. - * They are required to set up / tear down channels if they are loaded. - */ - if (!config->PassthroughIsBlacklist || (config->PassthroughCount != 0)) - { - PubSub_SubscribeChannelConnected(instance->context->pubSub, - pf_channels_on_client_channel_connect); - PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - pf_channels_on_client_channel_disconnect); - } PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); PubSub_SubscribeActivated(instance->context->pubSub, pf_client_on_activated); /** @@ -256,12 +266,53 @@ static BOOL pf_client_pre_connect(freerdp* instance) return FALSE; } - if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) + if (!pf_utils_is_passthrough(config)) { - PROXY_LOG_ERR(TAG, pc, "Failed to load addins"); - return FALSE; + if (!freerdp_client_load_addins(instance->context->channels, instance->settings)) + { + PROXY_LOG_ERR(TAG, pc, "Failed to load addins"); + return FALSE; + } } + else + { + /* Copy the current channel settings from the peer connection to the client. */ + if (!freerdp_channels_from_mcs(settings, &ps->context)) + return FALSE; + /* Filter out channels we do not want */ + { + CHANNEL_DEF* channels = (CHANNEL_DEF*)freerdp_settings_get_pointer_array( + settings, FreeRDP_ChannelDefArray, 0); + size_t x, size = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount); + + WINPR_ASSERT(channels || (size == 0)); + + for (x = 0; x < size;) + { + CHANNEL_DEF* cur = &channels[x]; + proxyChannelDataEventInfo dev = { 0 }; + + dev.channel_name = cur->name; + dev.flags = cur->options; + + /* Filter out channels blocked by config */ + if (!pf_modules_run_filter(pc->pdata->module, + FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_CREATE, pc->pdata, + &dev)) + { + const size_t s = size - MIN(size, x + 1); + memmove(cur, &cur[1], sizeof(CHANNEL_DEF) * s); + size--; + } + else + x++; + } + + if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, x)) + return FALSE; + } + } return pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_PRE_CONNECT, pc->pdata, pc); } @@ -497,24 +548,7 @@ static BOOL pf_client_post_connect(freerdp* instance) if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) return FALSE; - if (!pf_register_pointer(context->graphics)) - return FALSE; - - if (!settings->SoftwareGdi) - { - if (!pf_register_graphics(context->graphics)) - { - PROXY_LOG_ERR(TAG, pc, "failed to register graphics"); - return FALSE; - } - - pf_gdi_register_update_callbacks(update); - brush_cache_register_callbacks(update); - glyph_cache_register_callbacks(update); - bitmap_cache_register_callbacks(update); - offscreen_cache_register_callbacks(update); - palette_cache_register_callbacks(update); - } + WINPR_ASSERT(settings->SoftwareGdi); pf_client_register_update_callbacks(update); @@ -559,10 +593,6 @@ static void pf_client_post_disconnect(freerdp* instance) pc->connected = FALSE; pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_POST_CONNECT, pc->pdata, pc); - PubSub_UnsubscribeChannelConnected(instance->context->pubSub, - pf_channels_on_client_channel_connect); - PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub, - pf_channels_on_client_channel_disconnect); PubSub_UnsubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info); gdi_free(instance); diff --git a/server/proxy/pf_cliprdr.c b/server/proxy/pf_cliprdr.c deleted file mode 100644 index 948f85fa7..000000000 --- a/server/proxy/pf_cliprdr.c +++ /dev/null @@ -1,714 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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. - */ - -#include -#include - -#include "pf_cliprdr.h" -#include - -#define TAG PROXY_TAG("cliprdr") -#define TEXT_FORMATS_COUNT 2 - -/* used for createing a fake format list response, containing only text formats */ -static CLIPRDR_FORMAT g_text_formats[] = { { CF_TEXT, "\0" }, { CF_UNICODETEXT, "\0" } }; - -BOOL pf_server_cliprdr_init(pServerContext* ps) -{ - CliprdrServerContext* cliprdr; - - WINPR_ASSERT(ps); - cliprdr = ps->cliprdr = cliprdr_server_context_new(ps->vcm); - - if (!cliprdr) - { - WLog_ERR(TAG, "cliprdr_server_context_new failed."); - return FALSE; - } - - cliprdr->rdpcontext = (rdpContext*)ps; - - /* enable all capabilities */ - cliprdr->useLongFormatNames = TRUE; - cliprdr->streamFileClipEnabled = TRUE; - cliprdr->fileClipNoFilePaths = TRUE; - cliprdr->canLockClipData = TRUE; - cliprdr->hasHugeFileSupport = TRUE; - - /* disable initialization sequence, for caps sync */ - cliprdr->autoInitializationSequence = FALSE; - return TRUE; -} - -static INLINE BOOL pf_cliprdr_is_text_format(UINT32 format) -{ - switch (format) - { - case CF_TEXT: - case CF_UNICODETEXT: - return TRUE; - } - - return FALSE; -} - -static INLINE void pf_cliprdr_create_text_only_format_list(CLIPRDR_FORMAT_LIST* list) -{ - WINPR_ASSERT(list); - list->msgFlags = CB_RESPONSE_OK; - list->msgType = CB_FORMAT_LIST; - list->dataLen = (4 + 1) * TEXT_FORMATS_COUNT; - list->numFormats = TEXT_FORMATS_COUNT; - list->formats = g_text_formats; -} - -/* format data response PDU returns the copied text as a unicode buffer. - * pf_cliprdr_is_copy_paste_valid returns TRUE if the length of the copied - * text is valid according to the configuration value of `MaxTextLength`. - */ -static BOOL pf_cliprdr_is_copy_paste_valid(const proxyConfig* config, - const CLIPRDR_FORMAT_DATA_RESPONSE* pdu, UINT32 format) -{ - size_t copy_len; - - WINPR_ASSERT(config); - WINPR_ASSERT(pdu); - - if (config->MaxTextLength == 0) - { - /* no size limit */ - return TRUE; - } - - if (pdu->dataLen == 0) - { - /* no data */ - return FALSE; - } - - WLog_DBG(TAG, "pf_cliprdr_is_copy_paste_valid(): checking format %" PRIu32 "", format); - - switch (format) - { - case CF_UNICODETEXT: - copy_len = (pdu->dataLen / 2) - 1; - break; - case CF_TEXT: - copy_len = pdu->dataLen; - break; - default: - WLog_WARN(TAG, "received unknown format: %" PRIu32 ", format"); - return FALSE; - } - - if (copy_len > config->MaxTextLength) - { - WLog_WARN(TAG, "text size is too large: %" PRIu32 " (max %" PRIu32 ")", copy_len, - config->MaxTextLength); - return FALSE; - } - - return TRUE; -} - -/* - * if the requested text size is too long, we need a way to return a message to the other side of - * the connection, indicating that the copy/paste operation failed, instead of just not forwarding - * the response (because that destroys the state of the RDPECLIP channel). This is done by sending a - * `format_data_response` PDU with msgFlags = CB_RESPONSE_FAIL. - */ -static INLINE void pf_cliprdr_create_failed_format_data_response(CLIPRDR_FORMAT_DATA_RESPONSE* dst) -{ - WINPR_ASSERT(dst); - - dst->requestedFormatData = NULL; - dst->dataLen = 0; - dst->msgType = CB_FORMAT_DATA_RESPONSE; - dst->msgFlags = CB_RESPONSE_FAIL; -} - -/* server callbacks */ -static UINT pf_cliprdr_ClientCapabilities(CliprdrServerContext* context, - const CLIPRDR_CAPABILITIES* capabilities) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(capabilities); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientCapabilities); - - WLog_VRB(TAG, __FUNCTION__); - return client->ClientCapabilities(client, capabilities); -} - -static UINT pf_cliprdr_TempDirectory(CliprdrServerContext* context, - const CLIPRDR_TEMP_DIRECTORY* tempDirectory) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(tempDirectory); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->TempDirectory); - - WLog_VRB(TAG, __FUNCTION__); - return client->TempDirectory(client, tempDirectory); -} - -static UINT pf_cliprdr_ClientFormatList(CliprdrServerContext* context, - const CLIPRDR_FORMAT_LIST* formatList) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatList); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFormatList); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - { - CLIPRDR_FORMAT_LIST list = { 0 }; - pf_cliprdr_create_text_only_format_list(&list); - return client->ClientFormatList(client, &list); - } - - /* send a format list that allows only text */ - return client->ClientFormatList(client, formatList); -} - -static UINT -pf_cliprdr_ClientFormatListResponse(CliprdrServerContext* context, - const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatListResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFormatListResponse); - - WLog_VRB(TAG, __FUNCTION__); - return client->ClientFormatListResponse(client, formatListResponse); -} - -static UINT pf_cliprdr_ClientLockClipboardData(CliprdrServerContext* context, - const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(lockClipboardData); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientLockClipboardData); - - WLog_VRB(TAG, __FUNCTION__); - return client->ClientLockClipboardData(client, lockClipboardData); -} - -static UINT -pf_cliprdr_ClientUnlockClipboardData(CliprdrServerContext* context, - const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(unlockClipboardData); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientUnlockClipboardData); - - WLog_VRB(TAG, __FUNCTION__); - return client->ClientUnlockClipboardData(client, unlockClipboardData); -} - -static UINT pf_cliprdr_ClientFormatDataRequest(CliprdrServerContext* context, - const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatDataRequest); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->pc); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly && !pf_cliprdr_is_text_format(formatDataRequest->requestedFormatId)) - { - CLIPRDR_FORMAT_DATA_RESPONSE resp = { 0 }; - CliprdrServerContext* server; - - WINPR_ASSERT(pdata->ps); - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFormatDataResponse); - - pf_cliprdr_create_failed_format_data_response(&resp); - return server->ServerFormatDataResponse(server, &resp); - } - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFormatDataRequest); - return client->ClientFormatDataRequest(client, formatDataRequest); -} - -static UINT -pf_cliprdr_ClientFormatDataResponse(CliprdrServerContext* context, - const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatDataResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFormatDataResponse); - - WLog_VRB(TAG, __FUNCTION__); - - if (pf_cliprdr_is_text_format(client->lastRequestedFormatId)) - { - if (!pf_cliprdr_is_copy_paste_valid(pdata->config, formatDataResponse, - client->lastRequestedFormatId)) - { - CLIPRDR_FORMAT_DATA_RESPONSE resp; - pf_cliprdr_create_failed_format_data_response(&resp); - return client->ClientFormatDataResponse(client, &resp); - } - } - - return client->ClientFormatDataResponse(client, formatDataResponse); -} - -static UINT -pf_cliprdr_ClientFileContentsRequest(CliprdrServerContext* context, - const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(fileContentsRequest); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFileContentsRequest); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - return CHANNEL_RC_OK; - - return client->ClientFileContentsRequest(client, fileContentsRequest); -} - -static UINT -pf_cliprdr_ClientFileContentsResponse(CliprdrServerContext* context, - const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) -{ - proxyData* pdata; - CliprdrClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(fileContentsResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->pc); - - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFileContentsResponse); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - return CHANNEL_RC_OK; - - return client->ClientFileContentsResponse(client, fileContentsResponse); -} - -/* client callbacks */ - -static UINT pf_cliprdr_ServerCapabilities(CliprdrClientContext* context, - const CLIPRDR_CAPABILITIES* capabilities) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(capabilities); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerCapabilities); - - WLog_VRB(TAG, __FUNCTION__); - return server->ServerCapabilities(server, capabilities); -} - -static UINT pf_cliprdr_MonitorReady(CliprdrClientContext* context, - const CLIPRDR_MONITOR_READY* monitorReady) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(monitorReady); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->MonitorReady); - - WLog_VRB(TAG, __FUNCTION__); - return server->MonitorReady(server, monitorReady); -} - -static UINT pf_cliprdr_ServerFormatList(CliprdrClientContext* context, - const CLIPRDR_FORMAT_LIST* formatList) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatList); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFormatList); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - { - CLIPRDR_FORMAT_LIST list = { 0 }; - pf_cliprdr_create_text_only_format_list(&list); - return server->ServerFormatList(server, &list); - } - - return server->ServerFormatList(server, formatList); -} - -static UINT -pf_cliprdr_ServerFormatListResponse(CliprdrClientContext* context, - const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatListResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFormatListResponse); - - WLog_VRB(TAG, __FUNCTION__); - return server->ServerFormatListResponse(server, formatListResponse); -} - -static UINT pf_cliprdr_ServerLockClipboardData(CliprdrClientContext* context, - const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(lockClipboardData); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerLockClipboardData); - - WLog_VRB(TAG, __FUNCTION__); - return server->ServerLockClipboardData(server, lockClipboardData); -} - -static UINT -pf_cliprdr_ServerUnlockClipboardData(CliprdrClientContext* context, - const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(unlockClipboardData); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerUnlockClipboardData); - - WLog_VRB(TAG, __FUNCTION__); - return server->ServerUnlockClipboardData(server, unlockClipboardData); -} - -static UINT pf_cliprdr_ServerFormatDataRequest(CliprdrClientContext* context, - const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatDataRequest); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly && !pf_cliprdr_is_text_format(formatDataRequest->requestedFormatId)) - { - /* proxy's client needs to return a failed response directly to the client */ - CLIPRDR_FORMAT_DATA_RESPONSE resp = { 0 }; - CliprdrClientContext* client; - - WINPR_ASSERT(pdata->pc); - client = pdata->pc->cliprdr; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientFormatDataResponse); - - pf_cliprdr_create_failed_format_data_response(&resp); - return client->ClientFormatDataResponse(client, &resp); - } - - WINPR_ASSERT(pdata->ps); - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFormatDataRequest); - return server->ServerFormatDataRequest(server, formatDataRequest); -} - -static UINT -pf_cliprdr_ServerFormatDataResponse(CliprdrClientContext* context, - const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(formatDataResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFormatDataResponse); - - WLog_VRB(TAG, __FUNCTION__); - - if (pf_cliprdr_is_text_format(server->lastRequestedFormatId)) - { - if (!pf_cliprdr_is_copy_paste_valid(pdata->config, formatDataResponse, - server->lastRequestedFormatId)) - { - CLIPRDR_FORMAT_DATA_RESPONSE resp; - pf_cliprdr_create_failed_format_data_response(&resp); - return server->ServerFormatDataResponse(server, &resp); - } - } - - return server->ServerFormatDataResponse(server, formatDataResponse); -} - -static UINT -pf_cliprdr_ServerFileContentsRequest(CliprdrClientContext* context, - const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(fileContentsRequest); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFileContentsRequest); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - return CHANNEL_RC_OK; - - return server->ServerFileContentsRequest(server, fileContentsRequest); -} - -static UINT -pf_cliprdr_ServerFileContentsResponse(CliprdrClientContext* context, - const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) -{ - CliprdrServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(fileContentsResponse); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->config); - WINPR_ASSERT(pdata->ps); - - server = pdata->ps->cliprdr; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerFileContentsResponse); - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->TextOnly) - return CHANNEL_RC_OK; - - return server->ServerFileContentsResponse(server, fileContentsResponse); -} - -void pf_cliprdr_register_callbacks(CliprdrClientContext* cliprdr_client, - CliprdrServerContext* cliprdr_server, proxyData* pdata) -{ - WINPR_ASSERT(cliprdr_client); - WINPR_ASSERT(cliprdr_server); - WINPR_ASSERT(pdata); - - /* Set server and client side references to proxy data */ - cliprdr_server->custom = (void*)pdata; - cliprdr_client->custom = (void*)pdata; - /* Set server callbacks */ - cliprdr_server->ClientCapabilities = pf_cliprdr_ClientCapabilities; - cliprdr_server->TempDirectory = pf_cliprdr_TempDirectory; - cliprdr_server->ClientFormatList = pf_cliprdr_ClientFormatList; - cliprdr_server->ClientFormatListResponse = pf_cliprdr_ClientFormatListResponse; - cliprdr_server->ClientLockClipboardData = pf_cliprdr_ClientLockClipboardData; - cliprdr_server->ClientUnlockClipboardData = pf_cliprdr_ClientUnlockClipboardData; - cliprdr_server->ClientFormatDataRequest = pf_cliprdr_ClientFormatDataRequest; - cliprdr_server->ClientFormatDataResponse = pf_cliprdr_ClientFormatDataResponse; - cliprdr_server->ClientFileContentsRequest = pf_cliprdr_ClientFileContentsRequest; - cliprdr_server->ClientFileContentsResponse = pf_cliprdr_ClientFileContentsResponse; - /* Set client callbacks */ - cliprdr_client->ServerCapabilities = pf_cliprdr_ServerCapabilities; - cliprdr_client->MonitorReady = pf_cliprdr_MonitorReady; - cliprdr_client->ServerFormatList = pf_cliprdr_ServerFormatList; - cliprdr_client->ServerFormatListResponse = pf_cliprdr_ServerFormatListResponse; - cliprdr_client->ServerLockClipboardData = pf_cliprdr_ServerLockClipboardData; - cliprdr_client->ServerUnlockClipboardData = pf_cliprdr_ServerUnlockClipboardData; - cliprdr_client->ServerFormatDataRequest = pf_cliprdr_ServerFormatDataRequest; - cliprdr_client->ServerFormatDataResponse = pf_cliprdr_ServerFormatDataResponse; - cliprdr_client->ServerFileContentsRequest = pf_cliprdr_ServerFileContentsRequest; - cliprdr_client->ServerFileContentsResponse = pf_cliprdr_ServerFileContentsResponse; -} diff --git a/server/proxy/pf_cliprdr.h b/server/proxy/pf_cliprdr.h deleted file mode 100644 index e22c98a08..000000000 --- a/server/proxy/pf_cliprdr.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * - * 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_SERVER_PROXY_PFCLIPRDR_H -#define FREERDP_SERVER_PROXY_PFCLIPRDR_H - -#include -#include - -#include - -BOOL pf_server_cliprdr_init(pServerContext* ps); -void pf_cliprdr_register_callbacks(CliprdrClientContext* cliprdr_client, - CliprdrServerContext* cliprdr_server, proxyData* pdata); - -#endif /* FREERDP_SERVER_PROXY_PFCLIPRDR_H */ diff --git a/server/proxy/pf_config.c b/server/proxy/pf_config.c index 1a3675800..4661bb48a 100644 --- a/server/proxy/pf_config.c +++ b/server/proxy/pf_config.c @@ -33,6 +33,19 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pf_utils.h" + #define TAG PROXY_TAG("config") #define CONFIG_PRINT_SECTION(section) WLog_INFO(TAG, "\t%s:", section) @@ -202,6 +215,10 @@ static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config) config->DisplayControl = pf_config_get_bool(ini, "Channels", "DisplayControl", TRUE); config->Clipboard = pf_config_get_bool(ini, "Channels", "Clipboard", FALSE); config->AudioOutput = pf_config_get_bool(ini, "Channels", "AudioOutput", TRUE); + config->AudioInput = pf_config_get_bool(ini, "Channels", "AudioInput", TRUE); + config->DeviceRedirection = pf_config_get_bool(ini, "Channels", "DeviceRedirection", TRUE); + config->VideoRedirection = pf_config_get_bool(ini, "Channels", "VideoRedirection", TRUE); + config->CameraRedirection = pf_config_get_bool(ini, "Channels", "CameraRedirection", TRUE); config->RemoteApp = pf_config_get_bool(ini, "Channels", "RemoteApp", FALSE); config->PassthroughIsBlacklist = pf_config_get_bool(ini, "Channels", "PassthroughIsBlacklist", FALSE); @@ -232,6 +249,7 @@ static BOOL pf_config_load_input(wIniFile* ini, proxyConfig* config) WINPR_ASSERT(config); config->Keyboard = pf_config_get_bool(ini, "Input", "Keyboard", TRUE); config->Mouse = pf_config_get_bool(ini, "Input", "Mouse", TRUE); + config->Multitouch = pf_config_get_bool(ini, "Input", "Multitouch", TRUE); return TRUE; } @@ -465,8 +483,16 @@ BOOL pf_server_config_dump(const char* file) goto fail; if (IniFile_SetKeyValueString(ini, "Channels", "Clipboard", "true") < 0) goto fail; + if (IniFile_SetKeyValueString(ini, "Channels", "AudioInput", "true") < 0) + goto fail; if (IniFile_SetKeyValueString(ini, "Channels", "AudioOutput", "true") < 0) goto fail; + if (IniFile_SetKeyValueString(ini, "Channels", "DeviceRedirection", "true") < 0) + goto fail; + if (IniFile_SetKeyValueString(ini, "Channels", "VideoRedirection", "true") < 0) + goto fail; + if (IniFile_SetKeyValueString(ini, "Channels", "CameraRedirection", "true") < 0) + goto fail; if (IniFile_SetKeyValueString(ini, "Channels", "RemoteApp", "false") < 0) goto fail; @@ -480,6 +506,8 @@ BOOL pf_server_config_dump(const char* file) goto fail; if (IniFile_SetKeyValueString(ini, "Input", "Mouse", "true") < 0) goto fail; + if (IniFile_SetKeyValueString(ini, "Input", "Multitouch", "true") < 0) + goto fail; /* Security settings */ if (IniFile_SetKeyValueString(ini, "Security", "ServerTlsSecurity", "true") < 0) @@ -546,6 +574,7 @@ fail: IniFile_Free(ini); return rc; } + proxyConfig* pf_server_config_load_buffer(const char* buffer) { proxyConfig* config = NULL; @@ -624,6 +653,7 @@ void pf_server_config_print(const proxyConfig* config) CONFIG_PRINT_SECTION("Input"); CONFIG_PRINT_BOOL(config, Keyboard); CONFIG_PRINT_BOOL(config, Mouse); + CONFIG_PRINT_BOOL(config, Multitouch); CONFIG_PRINT_SECTION("Server Security"); CONFIG_PRINT_BOOL(config, ServerTlsSecurity); @@ -640,6 +670,10 @@ void pf_server_config_print(const proxyConfig* config) CONFIG_PRINT_BOOL(config, DisplayControl); CONFIG_PRINT_BOOL(config, Clipboard); CONFIG_PRINT_BOOL(config, AudioOutput); + CONFIG_PRINT_BOOL(config, AudioInput); + CONFIG_PRINT_BOOL(config, DeviceRedirection); + CONFIG_PRINT_BOOL(config, VideoRedirection); + CONFIG_PRINT_BOOL(config, CameraRedirection); CONFIG_PRINT_BOOL(config, RemoteApp); CONFIG_PRINT_BOOL(config, PassthroughIsBlacklist); @@ -775,7 +809,6 @@ BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config) if (!pf_config_copy_string_list(&tmp->RequiredPlugins, &tmp->RequiredPluginsCount, config->RequiredPlugins, config->RequiredPluginsCount)) goto fail; - if (!pf_config_copy_string(&tmp->CertificateFile, config->CertificateFile)) goto fail; if (!pf_config_copy_string(&tmp->CertificateContent, config->CertificateContent)) @@ -796,3 +829,231 @@ fail: pf_server_config_free(tmp); return FALSE; } + +struct config_plugin_data +{ + proxyPluginsManager* mgr; + const proxyConfig* config; +}; + +static const char config_plugin_name[] = "config"; +static const char config_plugin_desc[] = + "A plugin filtering according to proxy configuration file rules"; + +static BOOL config_plugin_unload(proxyPlugin* plugin) +{ + WINPR_ASSERT(plugin); + + /* Here we have to free up our custom data storage. */ + if (plugin) + { + free(plugin->custom); + plugin->custom = NULL; + } + + return TRUE; +} + +static BOOL config_plugin_keyboard_event(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + BOOL rc; + const struct config_plugin_data* custom; + const proxyConfig* cfg; + const proxyKeyboardEventInfo* event_data = (const proxyKeyboardEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(event_data); + + WINPR_UNUSED(event_data); + + custom = plugin->custom; + WINPR_ASSERT(custom); + + cfg = custom->config; + WINPR_ASSERT(cfg); + + rc = cfg->Keyboard; + WLog_DBG(TAG, "%s: %s", __FUNCTION__, rc ? "TRUE" : "FALSE"); + return rc; +} + +static BOOL config_plugin_mouse_event(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + BOOL rc; + const struct config_plugin_data* custom; + const proxyConfig* cfg; + const proxyMouseEventInfo* event_data = (const proxyMouseEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(event_data); + + WINPR_UNUSED(event_data); + + custom = plugin->custom; + WINPR_ASSERT(custom); + + cfg = custom->config; + WINPR_ASSERT(cfg); + + rc = cfg->Mouse; + WLog_DBG(TAG, "%s: %s", __FUNCTION__, rc ? "TRUE" : "FALSE"); + return rc; +} + +static BOOL config_plugin_client_channel_data(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(channel); + + WLog_DBG(TAG, "%s: %s [0x%04" PRIx16 "] got %" PRIuz, __FUNCTION__, channel->channel_name, + channel->channel_id, channel->data_len); + return TRUE; +} + +static BOOL config_plugin_server_channel_data(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(channel); + + WLog_DBG(TAG, "%s: %s [0x%04" PRIx16 "] got %" PRIuz, __FUNCTION__, channel->channel_name, + channel->channel_id, channel->data_len); + return TRUE; +} + +static BOOL config_plugin_dynamic_channel_create(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + int rc; + BOOL accept; + const struct config_plugin_data* custom; + const proxyConfig* cfg; + const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(channel); + + custom = plugin->custom; + WINPR_ASSERT(custom); + + cfg = custom->config; + WINPR_ASSERT(cfg); + + rc = pf_utils_channel_is_passthrough(cfg, channel->channel_name); + accept = rc > 0; + if (accept) + { + if (strncmp(RDPGFX_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPGFX_DVC_CHANNEL_NAME)) == 0) + accept = cfg->GFX; + else if (strncmp(RDPSND_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPSND_DVC_CHANNEL_NAME)) == 0) + accept = cfg->AudioOutput; + else if (strncmp(RDPSND_LOSSY_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPSND_LOSSY_DVC_CHANNEL_NAME)) == 0) + accept = cfg->AudioOutput; + else if (strncmp(AUDIN_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(AUDIN_DVC_CHANNEL_NAME)) == 0) + accept = cfg->AudioInput; + else if (strncmp(RDPEI_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPEI_DVC_CHANNEL_NAME)) == 0) + accept = cfg->Multitouch; + else if (strncmp(TSMF_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(TSMF_DVC_CHANNEL_NAME)) == 0) + accept = cfg->VideoRedirection; + else if (strncmp(VIDEO_CONTROL_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(VIDEO_CONTROL_DVC_CHANNEL_NAME)) == 0) + accept = cfg->VideoRedirection; + else if (strncmp(VIDEO_DATA_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(VIDEO_DATA_DVC_CHANNEL_NAME)) == 0) + accept = cfg->VideoRedirection; + else if (strncmp(RDPECAM_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPECAM_DVC_CHANNEL_NAME)) == 0) + accept = cfg->CameraRedirection; + } + + WLog_DBG(TAG, "%s: %s [0x%04" PRIx16 "]: %s", __FUNCTION__, channel->channel_name, + channel->channel_id, accept ? "TRUE" : "FALSE"); + return accept; +} + +static BOOL config_plugin_channel_create(proxyPlugin* plugin, proxyData* pdata, void* param) +{ + int rc; + BOOL accept; + const struct config_plugin_data* custom; + const proxyConfig* cfg; + const proxyChannelDataEventInfo* channel = (const proxyChannelDataEventInfo*)(param); + + WINPR_ASSERT(plugin); + WINPR_ASSERT(pdata); + WINPR_ASSERT(channel); + + custom = plugin->custom; + WINPR_ASSERT(custom); + + cfg = custom->config; + WINPR_ASSERT(cfg); + + rc = pf_utils_channel_is_passthrough(cfg, channel->channel_name); + accept = rc > 0; + if (accept) + { + if (strncmp(CLIPRDR_SVC_CHANNEL_NAME, channel->channel_name, + sizeof(CLIPRDR_SVC_CHANNEL_NAME)) == 0) + accept = cfg->Clipboard; + else if (strncmp(RDPSND_CHANNEL_NAME, channel->channel_name, sizeof(RDPSND_CHANNEL_NAME)) == + 0) + accept = cfg->AudioOutput; + else if (strncmp(RDPDR_SVC_CHANNEL_NAME, channel->channel_name, + sizeof(RDPDR_SVC_CHANNEL_NAME)) == 0) + accept = cfg->DeviceRedirection; + else if (strncmp(DISP_DVC_CHANNEL_NAME, channel->channel_name, + sizeof(DISP_DVC_CHANNEL_NAME)) == 0) + accept = cfg->DisplayControl; + else if (strncmp(RAIL_SVC_CHANNEL_NAME, channel->channel_name, + sizeof(RAIL_SVC_CHANNEL_NAME)) == 0) + accept = cfg->RemoteApp; + } + + WLog_DBG(TAG, "%s: %s [static]: %s", __FUNCTION__, channel->channel_name, + accept ? "TRUE" : "FALSE"); + return accept; +} + +BOOL pf_config_plugin(proxyPluginsManager* plugins_manager, void* userdata) +{ + struct config_plugin_data* custom; + proxyPlugin plugin = { 0 }; + + plugin.name = config_plugin_name; + plugin.description = config_plugin_desc; + plugin.PluginUnload = config_plugin_unload; + + plugin.KeyboardEvent = config_plugin_keyboard_event; + plugin.MouseEvent = config_plugin_mouse_event; + plugin.ClientChannelData = config_plugin_client_channel_data; + plugin.ServerChannelData = config_plugin_server_channel_data; + plugin.ChannelCreate = config_plugin_channel_create; + plugin.DynamicChannelCreate = config_plugin_dynamic_channel_create; + plugin.userdata = userdata; + + custom = calloc(1, sizeof(struct config_plugin_data)); + if (!custom) + return FALSE; + + custom->mgr = plugins_manager; + custom->config = userdata; + + plugin.custom = custom; + plugin.userdata = userdata; + + return plugins_manager->RegisterPlugin(plugins_manager, &plugin); +} diff --git a/server/proxy/pf_disp.c b/server/proxy/pf_disp.c deleted file mode 100644 index 474ccc326..000000000 --- a/server/proxy/pf_disp.c +++ /dev/null @@ -1,105 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * 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. - */ - -#include -#include -#include - -#include "pf_disp.h" - -#define TAG PROXY_TAG("disp") - -BOOL pf_server_disp_init(pServerContext* ps) -{ - DispServerContext* disp; - WINPR_ASSERT(ps); - disp = ps->disp = disp_server_context_new(ps->vcm); - - if (!disp) - { - return FALSE; - } - - disp->rdpcontext = (rdpContext*)ps; - return TRUE; -} - -static UINT pf_disp_monitor_layout(DispServerContext* context, - const DISPLAY_CONTROL_MONITOR_LAYOUT_PDU* pdu) -{ - proxyData* pdata; - DispClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(pdu); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (DispClientContext*)pdata->pc->disp; - WINPR_ASSERT(client); - WINPR_ASSERT(client->SendMonitorLayout); - - WLog_DBG(TAG, __FUNCTION__); - return client->SendMonitorLayout(client, pdu->NumMonitors, pdu->Monitors); -} - -static UINT pf_disp_on_caps_control(DispClientContext* context, UINT32 MaxNumMonitors, - UINT32 MaxMonitorAreaFactorA, UINT32 MaxMonitorAreaFactorB) -{ - DispServerContext* server; - proxyData* pdata; - - WINPR_ASSERT(context); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - server = (DispServerContext*)pdata->ps->disp; - WINPR_ASSERT(server); - WINPR_ASSERT(server->DisplayControlCaps); - - WLog_DBG(TAG, __FUNCTION__); - - /* Update caps of proxy's disp server */ - server->MaxMonitorAreaFactorA = MaxMonitorAreaFactorA; - server->MaxMonitorAreaFactorB = MaxMonitorAreaFactorB; - server->MaxNumMonitors = MaxNumMonitors; - /* Send CapsControl to client */ - return server->DisplayControlCaps(server); -} - -void pf_disp_register_callbacks(DispClientContext* client, DispServerContext* server, - proxyData* pdata) -{ - WINPR_ASSERT(client); - WINPR_ASSERT(server); - WINPR_ASSERT(pdata); - - client->custom = (void*)pdata; - server->custom = (void*)pdata; - /* client receives from server, forward using disp server to original client */ - client->DisplayControlCaps = pf_disp_on_caps_control; - /* server receives from client, forward to target server using disp client */ - server->DispMonitorLayout = pf_disp_monitor_layout; -} diff --git a/server/proxy/pf_disp.h b/server/proxy/pf_disp.h deleted file mode 100644 index 72629e99f..000000000 --- a/server/proxy/pf_disp.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * - * 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_SERVER_PROXY_RDPEDISP_H -#define FREERDP_SERVER_PROXY_RDPEDISP_H - -#include -#include - -#include - -BOOL pf_server_disp_init(pServerContext* ps); -void pf_disp_register_callbacks(DispClientContext* client, DispServerContext* server, - proxyData* pdata); - -#endif /*FREERDP_SERVER_PROXY_RDPEDISP_H*/ diff --git a/server/proxy/pf_gdi.c b/server/proxy/pf_gdi.c deleted file mode 100644 index 5ded731e9..000000000 --- a/server/proxy/pf_gdi.c +++ /dev/null @@ -1,195 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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 -#include -#include -#include -#include -#include - -#include - -#include "pf_gdi.h" - -#define TAG PROXY_TAG("gdi") - -/* TODO: Figure how to use functions decleared in update.c */ -static BOOL pf_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(bounds); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(dstblt); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(patblt); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(scrblt); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(opaque_rect); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_multi_opaque_rect(rdpContext* context, - const MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(multi_opaque_rect); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_line_to(rdpContext* context, const LINE_TO_ORDER* line_to) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(line_to); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_polyline(rdpContext* context, const POLYLINE_ORDER* polyline) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(polyline); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(memblt); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(mem3blt); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_polygon_sc(rdpContext* context, const POLYGON_SC_ORDER* polygon_sc) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(polygon_sc); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(polygon_cb); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_surface_frame_marker(rdpContext* context, - const SURFACE_FRAME_MARKER* surface_frame_marker) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(surface_frame_marker); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -static BOOL pf_gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(cmd); - - WLog_INFO(TAG, __FUNCTION__); - return TRUE; -} - -void pf_gdi_register_update_callbacks(rdpUpdate* update) -{ - rdpPrimaryUpdate* primary; - - WINPR_ASSERT(update); - primary = update->primary; - WINPR_ASSERT(primary); - - update->SetBounds = pf_gdi_set_bounds; - primary->DstBlt = pf_gdi_dstblt; - primary->PatBlt = pf_gdi_patblt; - primary->ScrBlt = pf_gdi_scrblt; - primary->OpaqueRect = pf_gdi_opaque_rect; - primary->MultiOpaqueRect = pf_gdi_multi_opaque_rect; - primary->LineTo = pf_gdi_line_to; - primary->Polyline = pf_gdi_polyline; - primary->MemBlt = pf_gdi_memblt; - primary->Mem3Blt = pf_gdi_mem3blt; - primary->PolygonSC = pf_gdi_polygon_sc; - primary->PolygonCB = pf_gdi_polygon_cb; - update->SurfaceBits = pf_gdi_surface_bits; - update->SurfaceFrameMarker = pf_gdi_surface_frame_marker; -} diff --git a/server/proxy/pf_graphics.c b/server/proxy/pf_graphics.c deleted file mode 100644 index 39d0eb272..000000000 --- a/server/proxy/pf_graphics.c +++ /dev/null @@ -1,205 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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 - -#include - -#include "pf_graphics.h" -#include "pf_gdi.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#define TAG PROXY_TAG("graphics") - -/* Bitmap Class */ -static BOOL pf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(bitmap); - - return TRUE; -} - -static void pf_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(bitmap); -} - -static BOOL pf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(bitmap); - - return TRUE; -} - -static BOOL pf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(bitmap); - - return TRUE; -} - -/* Pointer Class */ -static BOOL pf_Pointer_New(rdpContext* context, rdpPointer* pointer) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(pointer); - - return TRUE; -} - -static void pf_Pointer_Free(rdpContext* context, rdpPointer* pointer) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(pointer); -} - -static BOOL pf_Pointer_Set(rdpContext* context, const rdpPointer* pointer) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(pointer); - - return TRUE; -} - -static BOOL pf_Pointer_SetNull(rdpContext* context) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -static BOOL pf_Pointer_SetDefault(rdpContext* context) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -static BOOL pf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -/* Glyph Class */ -static BOOL pf_Glyph_New(rdpContext* context, rdpGlyph* glyph) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(glyph); - - return TRUE; -} - -static void pf_Glyph_Free(rdpContext* context, rdpGlyph* glyph) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(glyph); -} - -static BOOL pf_Glyph_Draw(rdpContext* context, const rdpGlyph* glyph, INT32 x, INT32 y, INT32 w, - INT32 h, INT32 sx, INT32 sy, BOOL fOpRedundant) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -static BOOL pf_Glyph_BeginDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, - UINT32 bgcolor, UINT32 fgcolor, BOOL fOpRedundant) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -static BOOL pf_Glyph_EndDraw(rdpContext* context, INT32 x, INT32 y, INT32 width, INT32 height, - UINT32 bgcolor, UINT32 fgcolor) -{ - WINPR_ASSERT(context); - - return TRUE; -} - -/* Graphics Module */ -BOOL pf_register_pointer(rdpGraphics* graphics) -{ - rdpPointer pointer = { 0 }; - - WINPR_ASSERT(graphics); - - pointer.size = sizeof(rdpPointer); - pointer.New = pf_Pointer_New; - pointer.Free = pf_Pointer_Free; - pointer.Set = pf_Pointer_Set; - pointer.SetNull = pf_Pointer_SetNull; - pointer.SetDefault = pf_Pointer_SetDefault; - pointer.SetPosition = pf_Pointer_SetPosition; - graphics_register_pointer(graphics, &pointer); - return TRUE; -} - -BOOL pf_register_graphics(rdpGraphics* graphics) -{ - rdpBitmap bitmap = { 0 }; - rdpGlyph glyph = { 0 }; - - if (!graphics || !graphics->Bitmap_Prototype || !graphics->Glyph_Prototype) - return FALSE; - - bitmap = *graphics->Bitmap_Prototype; - glyph = *graphics->Glyph_Prototype; - bitmap.size = sizeof(rdpBitmap); - bitmap.New = pf_Bitmap_New; - bitmap.Free = pf_Bitmap_Free; - bitmap.Paint = pf_Bitmap_Paint; - bitmap.SetSurface = pf_Bitmap_SetSurface; - graphics_register_bitmap(graphics, &bitmap); - - glyph.size = sizeof(rdpGlyph); - glyph.New = pf_Glyph_New; - glyph.Free = pf_Glyph_Free; - glyph.Draw = pf_Glyph_Draw; - glyph.BeginDraw = pf_Glyph_BeginDraw; - glyph.EndDraw = pf_Glyph_EndDraw; - graphics_register_glyph(graphics, &glyph); - return TRUE; -} diff --git a/server/proxy/pf_graphics.h b/server/proxy/pf_graphics.h deleted file mode 100644 index 08763a64f..000000000 --- a/server/proxy/pf_graphics.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * - * 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_SERVER_PROXY_PFGRAPHICS_H -#define FREERDP_SERVER_PROXY_PFGRAPHICS_H - -#include -#include "pf_client.h" - -BOOL pf_register_pointer(rdpGraphics* graphics); -BOOL pf_register_graphics(rdpGraphics* graphics); - -#endif /* FREERDP_SERVER_PROXY_PFGRAPHICS_H */ diff --git a/server/proxy/pf_modules.c b/server/proxy/pf_modules.c index 74e3a4434..692f07d8e 100644 --- a/server/proxy/pf_modules.c +++ b/server/proxy/pf_modules.c @@ -200,6 +200,10 @@ static BOOL pf_modules_ArrayList_ForEachFkt(void* data, size_t index, va_list ap result = IFCALLRESULT(TRUE, plugin->ServerChannelData, plugin, pdata, param); break; + case FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_CREATE: + result = IFCALLRESULT(TRUE, plugin->ChannelCreate, plugin, pdata, param); + break; + case FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE: result = IFCALLRESULT(TRUE, plugin->DynamicChannelCreate, plugin, pdata, param); break; diff --git a/server/proxy/pf_rail.c b/server/proxy/pf_rail.c deleted file mode 100644 index f28110560..000000000 --- a/server/proxy/pf_rail.c +++ /dev/null @@ -1,696 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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. - */ - -#include - -#include -#include -#include - -#include "pf_rail.h" -#include - -#define TAG PROXY_TAG("rail") - -BOOL pf_rail_context_init(pServerContext* ps) -{ - RailServerContext* rail; - - WINPR_ASSERT(ps); - - rail = ps->rail = rail_server_context_new(ps->vcm); - - if (!rail) - { - return FALSE; - } - - /* - * when mstsc reconnects, it doesn't wait for a second handshake, so update all handshake flags - * to be SET, then set them again when the remote server sends his handshake. - */ - rail_server_set_handshake_ex_flags(rail, - TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF | - TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED | - TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED); - - rail->rdpcontext = (rdpContext*)ps; - return TRUE; -} - -static UINT pf_rail_client_on_open(RailClientContext* context, BOOL* sendHandshake) -{ - WINPR_ASSERT(context); - WINPR_ASSERT(sendHandshake); - - if (NULL != sendHandshake) - *sendHandshake = FALSE; - - return CHANNEL_RC_OK; -} - -/* Callbacks from client side */ -static UINT pf_rail_server_handshake(RailClientContext* client, - const RAIL_HANDSHAKE_ORDER* handshake) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(handshake); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerHandshake); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerHandshake(server, handshake); -} - -static UINT pf_rail_server_handshake_ex(RailClientContext* client, - const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(handshakeEx); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerHandshakeEx); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerHandshakeEx(server, handshakeEx); -} - -static UINT pf_rail_server_sysparam(RailClientContext* client, const RAIL_SYSPARAM_ORDER* sysparam) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(sysparam); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerSysparam); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerSysparam(server, sysparam); -} - -static UINT pf_rail_server_local_move_size(RailClientContext* client, - const RAIL_LOCALMOVESIZE_ORDER* localMoveSize) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(localMoveSize); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerLocalMoveSize); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerLocalMoveSize(server, localMoveSize); -} - -static UINT pf_rail_server_min_max_info(RailClientContext* client, - const RAIL_MINMAXINFO_ORDER* minMaxInfo) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(minMaxInfo); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerMinMaxInfo); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerMinMaxInfo(server, minMaxInfo); -} - -static UINT pf_rail_server_taskbar_info(RailClientContext* client, - const RAIL_TASKBAR_INFO_ORDER* taskbarInfo) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(taskbarInfo); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerTaskbarInfo); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerTaskbarInfo(server, taskbarInfo); -} - -static UINT pf_rail_server_langbar_info(RailClientContext* client, - const RAIL_LANGBAR_INFO_ORDER* langbarInfo) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(langbarInfo); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerLangbarInfo); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerLangbarInfo(server, langbarInfo); -} - -static UINT pf_rail_server_exec_result(RailClientContext* client, - const RAIL_EXEC_RESULT_ORDER* execResult) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(execResult); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerExecResult); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerExecResult(server, execResult); -} - -static UINT pf_rail_server_z_order_sync(RailClientContext* client, - const RAIL_ZORDER_SYNC* zOrderSync) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(zOrderSync); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerZOrderSync); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerZOrderSync(server, zOrderSync); -} - -static UINT pf_rail_server_cloak(RailClientContext* client, const RAIL_CLOAK* cloak) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(cloak); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerCloak); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerCloak(server, cloak); -} - -static UINT -pf_rail_server_power_display_request(RailClientContext* client, - const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(powerDisplayRequest); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerPowerDisplayRequest); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerPowerDisplayRequest(server, powerDisplayRequest); -} - -static UINT pf_rail_server_get_appid_resp(RailClientContext* client, - const RAIL_GET_APPID_RESP_ORDER* getAppidResp) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(getAppidResp); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerGetAppidResp); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerGetAppidResp(server, getAppidResp); -} - -static UINT pf_rail_server_get_appid_resp_ex(RailClientContext* client, - const RAIL_GET_APPID_RESP_EX* getAppidRespEx) -{ - proxyData* pdata; - RailServerContext* server; - - WINPR_ASSERT(client); - WINPR_ASSERT(getAppidRespEx); - - pdata = (proxyData*)client->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->ps); - - server = (RailServerContext*)pdata->ps->rail; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ServerGetAppidRespEx); - - WLog_DBG(TAG, __FUNCTION__); - return server->ServerGetAppidRespEx(server, getAppidRespEx); -} - -/* Callbacks from server side */ - -static UINT pf_rail_client_handshake(RailServerContext* server, - const RAIL_HANDSHAKE_ORDER* handshake) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(handshake); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientHandshake); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientHandshake(client, handshake); -} - -static UINT pf_rail_client_client_status(RailServerContext* server, - const RAIL_CLIENT_STATUS_ORDER* clientStatus) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(clientStatus); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientInformation); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientInformation(client, clientStatus); -} - -static UINT pf_rail_client_exec(RailServerContext* server, const RAIL_EXEC_ORDER* exec) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(exec); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientExecute); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientExecute(client, exec); -} - -static UINT pf_rail_client_sysparam(RailServerContext* server, const RAIL_SYSPARAM_ORDER* sysparam) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(sysparam); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientSystemParam); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientSystemParam(client, sysparam); -} - -static UINT pf_rail_client_activate(RailServerContext* server, const RAIL_ACTIVATE_ORDER* activate) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(activate); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientActivate); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientActivate(client, activate); -} - -static UINT pf_rail_client_sysmenu(RailServerContext* server, const RAIL_SYSMENU_ORDER* sysmenu) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(sysmenu); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientSystemMenu); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientSystemMenu(client, sysmenu); -} - -static UINT pf_rail_client_syscommand(RailServerContext* server, - const RAIL_SYSCOMMAND_ORDER* syscommand) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(syscommand); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientSystemCommand); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientSystemCommand(client, syscommand); -} - -static UINT pf_rail_client_notify_event(RailServerContext* server, - const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(notifyEvent); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientNotifyEvent); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientNotifyEvent(client, notifyEvent); -} - -static UINT pf_rail_client_window_move(RailServerContext* server, - const RAIL_WINDOW_MOVE_ORDER* windowMove) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(windowMove); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientWindowMove); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientWindowMove(client, windowMove); -} - -static UINT pf_rail_client_snap_arrange(RailServerContext* server, - const RAIL_SNAP_ARRANGE* snapArrange) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(snapArrange); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientSnapArrange); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientSnapArrange(client, snapArrange); -} - -static UINT pf_rail_client_get_appid_req(RailServerContext* server, - const RAIL_GET_APPID_REQ_ORDER* getAppidReq) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(getAppidReq); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientGetAppIdRequest); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientGetAppIdRequest(client, getAppidReq); -} - -static UINT pf_rail_client_langbar_info(RailServerContext* server, - const RAIL_LANGBAR_INFO_ORDER* langbarInfo) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(langbarInfo); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientLanguageBarInfo); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientLanguageBarInfo(client, langbarInfo); -} - -static UINT pf_rail_client_language_ime_info(RailServerContext* server, - const RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(languageImeInfo); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientLanguageIMEInfo); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientLanguageIMEInfo(client, languageImeInfo); -} - -static UINT pf_rail_client_compartment_info(RailServerContext* server, - const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(compartmentInfo); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - - WLog_DBG(TAG, __FUNCTION__); - return 0; -} - -static UINT pf_rail_client_cloak(RailServerContext* server, const RAIL_CLOAK* cloak) -{ - proxyData* pdata; - RailClientContext* client; - - WINPR_ASSERT(server); - WINPR_ASSERT(cloak); - - pdata = (proxyData*)server->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RailClientContext*)pdata->pc->rail; - WINPR_ASSERT(client); - WINPR_ASSERT(client->ClientCloak); - - WLog_DBG(TAG, __FUNCTION__); - return client->ClientCloak(client, cloak); -} - -void pf_rail_pipeline_init(RailClientContext* client, RailServerContext* server, proxyData* pdata) -{ - WINPR_ASSERT(client); - WINPR_ASSERT(server); - WINPR_ASSERT(pdata); - - /* Set server and client side references to proxy data */ - client->custom = (void*)pdata; - server->custom = (void*)pdata; - /* Set client callbacks */ - client->OnOpen = pf_rail_client_on_open; - client->ServerHandshake = pf_rail_server_handshake; - client->ServerHandshakeEx = pf_rail_server_handshake_ex; - client->ServerSystemParam = pf_rail_server_sysparam; - client->ServerLocalMoveSize = pf_rail_server_local_move_size; - client->ServerMinMaxInfo = pf_rail_server_min_max_info; - client->ServerTaskBarInfo = pf_rail_server_taskbar_info; - client->ServerLanguageBarInfo = pf_rail_server_langbar_info; - client->ServerExecuteResult = pf_rail_server_exec_result; - client->ServerZOrderSync = pf_rail_server_z_order_sync; - client->ServerCloak = pf_rail_server_cloak; - client->ServerPowerDisplayRequest = pf_rail_server_power_display_request; - client->ServerGetAppIdResponse = pf_rail_server_get_appid_resp; - client->ServerGetAppidResponseExtended = pf_rail_server_get_appid_resp_ex; - /* Set server callbacks */ - server->ClientHandshake = pf_rail_client_handshake; - server->ClientClientStatus = pf_rail_client_client_status; - server->ClientExec = pf_rail_client_exec; - server->ClientSysparam = pf_rail_client_sysparam; - server->ClientActivate = pf_rail_client_activate; - server->ClientSysmenu = pf_rail_client_sysmenu; - server->ClientSyscommand = pf_rail_client_syscommand; - server->ClientNotifyEvent = pf_rail_client_notify_event; - server->ClientGetAppidReq = pf_rail_client_get_appid_req; - server->ClientWindowMove = pf_rail_client_window_move; - server->ClientSnapArrange = pf_rail_client_snap_arrange; - server->ClientLangbarInfo = pf_rail_client_langbar_info; - server->ClientLanguageImeInfo = pf_rail_client_language_ime_info; - server->ClientCompartmentInfo = pf_rail_client_compartment_info; - server->ClientCloak = pf_rail_client_cloak; -} diff --git a/server/proxy/pf_rail.h b/server/proxy/pf_rail.h deleted file mode 100644 index 5126998fd..000000000 --- a/server/proxy/pf_rail.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * - * 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_SERVER_PROXY_PFRAIL_H -#define FREERDP_SERVER_PROXY_PFRAIL_H - -#include -#include - -#include - -BOOL pf_rail_context_init(pServerContext* ps); -void pf_rail_pipeline_init(RailClientContext* client, RailServerContext* server, proxyData* pdata); - -#endif /*FREERDP_SERVER_PROXY_PFRAIL_H*/ diff --git a/server/proxy/pf_rdpgfx.c b/server/proxy/pf_rdpgfx.c deleted file mode 100644 index 003e57f33..000000000 --- a/server/proxy/pf_rdpgfx.c +++ /dev/null @@ -1,903 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * 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. - */ - -#include -#include -#include - -#include -#include - -#include "pf_rdpgfx.h" -#include -#include - -#define TAG PROXY_TAG("gfx") - -BOOL pf_server_rdpgfx_init(pServerContext* ps) -{ - RdpgfxServerContext* gfx; - - WINPR_ASSERT(ps); - gfx = ps->gfx = rdpgfx_server_context_new(ps->vcm); - - if (!gfx) - { - return FALSE; - } - - gfx->rdpcontext = (rdpContext*)ps; - return TRUE; -} - -static UINT pf_rdpgfx_reset_graphics(RdpgfxClientContext* context, - const RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(resetGraphics); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->ResetGraphics); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->ResetGraphics(server, resetGraphics))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->ResetGraphics); - return gfx_decoder->ResetGraphics(gfx_decoder, resetGraphics); -} - -static UINT pf_rdpgfx_start_frame(RdpgfxClientContext* context, - const RDPGFX_START_FRAME_PDU* startFrame) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(startFrame); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->StartFrame); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->StartFrame(server, startFrame))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->StartFrame); - return gfx_decoder->StartFrame(gfx_decoder, startFrame); -} - -static UINT pf_rdpgfx_end_frame(RdpgfxClientContext* context, const RDPGFX_END_FRAME_PDU* endFrame) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(endFrame); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->EndFrame); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->EndFrame(server, endFrame))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->EndFrame); - return gfx_decoder->EndFrame(gfx_decoder, endFrame); -} - -static UINT pf_rdpgfx_surface_command(RdpgfxClientContext* context, - const RDPGFX_SURFACE_COMMAND* cmd) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(cmd); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->SurfaceCommand); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->SurfaceCommand(server, cmd))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->SurfaceCommand); - return gfx_decoder->SurfaceCommand(gfx_decoder, cmd); -} - -static UINT -pf_rdpgfx_delete_encoding_context(RdpgfxClientContext* context, - const RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(deleteEncodingContext); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->DeleteEncodingContext); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->DeleteEncodingContext(server, deleteEncodingContext))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->DeleteEncodingContext); - return gfx_decoder->DeleteEncodingContext(gfx_decoder, deleteEncodingContext); -} - -static UINT pf_rdpgfx_create_surface(RdpgfxClientContext* context, - const RDPGFX_CREATE_SURFACE_PDU* createSurface) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(createSurface); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->CreateSurface); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->CreateSurface(server, createSurface))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->CreateSurface); - return gfx_decoder->CreateSurface(gfx_decoder, createSurface); -} - -static UINT pf_rdpgfx_delete_surface(RdpgfxClientContext* context, - const RDPGFX_DELETE_SURFACE_PDU* deleteSurface) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(deleteSurface); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->DeleteSurface); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->DeleteSurface(server, deleteSurface))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->DeleteSurface); - return gfx_decoder->DeleteSurface(gfx_decoder, deleteSurface); -} - -static UINT pf_rdpgfx_solid_fill(RdpgfxClientContext* context, - const RDPGFX_SOLID_FILL_PDU* solidFill) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(solidFill); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->SolidFill); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->SolidFill(server, solidFill))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->SolidFill); - return gfx_decoder->SolidFill(gfx_decoder, solidFill); -} - -static UINT pf_rdpgfx_surface_to_surface(RdpgfxClientContext* context, - const RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToSurface); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->SurfaceToSurface); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->SurfaceToSurface(server, surfaceToSurface))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->SurfaceToSurface); - return gfx_decoder->SurfaceToSurface(gfx_decoder, surfaceToSurface); -} - -static UINT pf_rdpgfx_surface_to_cache(RdpgfxClientContext* context, - const RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToCache); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->SurfaceToCache); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->SurfaceToCache(server, surfaceToCache))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->SurfaceToCache); - return gfx_decoder->SurfaceToCache(gfx_decoder, surfaceToCache); -} - -static UINT pf_rdpgfx_cache_to_surface(RdpgfxClientContext* context, - const RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(cacheToSurface); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->CacheToSurface); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->CacheToSurface(server, cacheToSurface))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->CacheToSurface); - return gfx_decoder->CacheToSurface(gfx_decoder, cacheToSurface); -} - -static UINT pf_rdpgfx_cache_import_reply(RdpgfxClientContext* context, - const RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply) -{ - proxyData* pdata; - RdpgfxServerContext* server; - - WINPR_ASSERT(context); - WINPR_ASSERT(cacheImportReply); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->CacheImportReply); - - WLog_VRB(TAG, __FUNCTION__); - return server->CacheImportReply(server, cacheImportReply); -} - -static UINT pf_rdpgfx_evict_cache_entry(RdpgfxClientContext* context, - const RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(evictCacheEntry); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->EvictCacheEntry); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->EvictCacheEntry(server, evictCacheEntry))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->EvictCacheEntry); - return gfx_decoder->EvictCacheEntry(gfx_decoder, evictCacheEntry); -} - -static UINT pf_rdpgfx_map_surface_to_output(RdpgfxClientContext* context, - const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToOutput); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->MapSurfaceToOutput); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->MapSurfaceToOutput(server, surfaceToOutput))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->MapSurfaceToOutput); - return gfx_decoder->MapSurfaceToOutput(gfx_decoder, surfaceToOutput); -} - -static UINT pf_rdpgfx_map_surface_to_window(RdpgfxClientContext* context, - const RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToWindow); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->MapSurfaceToWindow); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->MapSurfaceToWindow(server, surfaceToWindow))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->MapSurfaceToWindow); - return gfx_decoder->MapSurfaceToWindow(gfx_decoder, surfaceToWindow); -} - -static UINT pf_rdpgfx_map_surface_to_scaled_window( - RdpgfxClientContext* context, - const RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* surfaceToScaledWindow) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToScaledWindow); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->MapSurfaceToScaledWindow); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->MapSurfaceToScaledWindow(server, surfaceToScaledWindow))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->MapSurfaceToScaledWindow); - return gfx_decoder->MapSurfaceToScaledWindow(gfx_decoder, surfaceToScaledWindow); -} - -static UINT pf_rdpgfx_map_surface_to_scaled_output( - RdpgfxClientContext* context, - const RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToScaledOutput) -{ - UINT error; - proxyData* pdata; - const proxyConfig* config; - RdpgfxServerContext* server; - RdpgfxClientContext* gfx_decoder; - - WINPR_ASSERT(context); - WINPR_ASSERT(surfaceToScaledOutput); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - config = pdata->config; - WINPR_ASSERT(config); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->MapSurfaceToScaledOutput); - - WLog_VRB(TAG, __FUNCTION__); - - if ((error = server->MapSurfaceToScaledOutput(server, surfaceToScaledOutput))) - return error; - - if (!config->DecodeGFX) - return CHANNEL_RC_OK; - - gfx_decoder = pdata->pc->gfx_decoder; - WINPR_ASSERT(gfx_decoder); - WINPR_ASSERT(gfx_decoder->MapSurfaceToScaledOutput); - return gfx_decoder->MapSurfaceToScaledOutput(gfx_decoder, surfaceToScaledOutput); -} - -static UINT pf_rdpgfx_on_open(RdpgfxClientContext* context, BOOL* do_caps_advertise, - BOOL* send_frame_acks) -{ - proxyData* pdata; - - WINPR_ASSERT(context); - WINPR_ASSERT(do_caps_advertise); - WINPR_ASSERT(send_frame_acks); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->gfx_server_ready); - - WLog_VRB(TAG, __FUNCTION__); - - if (NULL != do_caps_advertise) - *do_caps_advertise = FALSE; - - if (NULL != send_frame_acks) - *send_frame_acks = FALSE; - - /* do not open the channel before gfx server side is in ready state */ - WaitForSingleObject(pdata->gfx_server_ready, INFINITE); - return CHANNEL_RC_OK; -} - -static UINT pf_rdpgfx_caps_confirm(RdpgfxClientContext* context, - const RDPGFX_CAPS_CONFIRM_PDU* capsConfirm) -{ - proxyData* pdata; - RdpgfxServerContext* server; - - WINPR_ASSERT(context); - WINPR_ASSERT(capsConfirm); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - WINPR_ASSERT(pdata->ps); - - server = (RdpgfxServerContext*)pdata->ps->gfx; - WINPR_ASSERT(server); - WINPR_ASSERT(server->CapsConfirm); - - WLog_VRB(TAG, __FUNCTION__); - - return server->CapsConfirm(server, capsConfirm); -} - -/* Proxy server side callbacks */ -static UINT pf_rdpgfx_caps_advertise(RdpgfxServerContext* context, - const RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise) -{ - UINT16 index; - UINT16 proxySupportedCapsSetCount = 0; - RDPGFX_CAPS_ADVERTISE_PDU supportedCapsAdvertise = { 0 }; - RDPGFX_CAPSET* proxySupportedCapsSet; - RDPGFX_CAPSET proxySupportedCapsSets[RDPGFX_NUMBER_CAPSETS] = { 0 }; - proxyData* pdata; - RdpgfxClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(capsAdvertise); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RdpgfxClientContext*)pdata->pc->gfx_proxy; - for (index = 0; index < capsAdvertise->capsSetCount; index++) - { - const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; - - /* Add cap to supported caps list if supported by FreeRDP. - * TODO: Have a better way of expressing max supported GFX caps version - * by FreeRDP. - */ - if (currentCaps->version <= RDPGFX_CAPVERSION_106) - { - proxySupportedCapsSet = &proxySupportedCapsSets[proxySupportedCapsSetCount++]; - proxySupportedCapsSet->version = currentCaps->version; - proxySupportedCapsSet->length = currentCaps->length; - proxySupportedCapsSet->flags = currentCaps->flags; - } - } - - supportedCapsAdvertise.capsSetCount = proxySupportedCapsSetCount; - supportedCapsAdvertise.capsSets = proxySupportedCapsSets; - WLog_VRB(TAG, __FUNCTION__); - - WINPR_ASSERT(client); - WINPR_ASSERT(client->CapsAdvertise); - return client->CapsAdvertise(client, &supportedCapsAdvertise); -} - -static UINT pf_rdpgfx_frame_acknowledge(RdpgfxServerContext* context, - const RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge) -{ - proxyData* pdata; - RdpgfxClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(frameAcknowledge); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RdpgfxClientContext*)pdata->pc->gfx_proxy; - WLog_VRB(TAG, __FUNCTION__); - - WINPR_ASSERT(client); - WINPR_ASSERT(client->FrameAcknowledge); - return client->FrameAcknowledge(client, frameAcknowledge); -} - -static UINT -pf_rdpgfx_qoe_frame_acknowledge(RdpgfxServerContext* context, - const RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* qoeFrameAcknowledge) -{ - proxyData* pdata; - RdpgfxClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(qoeFrameAcknowledge); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RdpgfxClientContext*)pdata->pc->gfx_proxy; - WLog_VRB(TAG, __FUNCTION__); - - WINPR_ASSERT(client); - WINPR_ASSERT(client->QoeFrameAcknowledge); - return client->QoeFrameAcknowledge(client, qoeFrameAcknowledge); -} - -static UINT pf_rdpgfx_cache_import_offer(RdpgfxServerContext* context, - const RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer) -{ - proxyData* pdata; - RdpgfxClientContext* client; - - WINPR_ASSERT(context); - WINPR_ASSERT(cacheImportOffer); - - pdata = (proxyData*)context->custom; - WINPR_ASSERT(pdata); - WINPR_ASSERT(pdata->pc); - - client = (RdpgfxClientContext*)pdata->pc->gfx_proxy; - - WLog_VRB(TAG, __FUNCTION__); - - if (pdata->config->DecodeGFX) - { - /* do not proxy CacheImportOffer, as is it currently not supported by FREERDP. */ - return CHANNEL_RC_OK; - } - - WINPR_ASSERT(client); - WINPR_ASSERT(client->CacheImportOffer); - return client->CacheImportOffer(client, cacheImportOffer); -} - -void pf_rdpgfx_pipeline_init(RdpgfxClientContext* gfx, RdpgfxServerContext* server, - proxyData* pdata) -{ - pClientContext* pc; - - WINPR_ASSERT(gfx); - WINPR_ASSERT(server); - WINPR_ASSERT(pdata); - - pc = pdata->pc; - WINPR_ASSERT(pc); - - /* create another gfx client and register it to the gdi graphics pipeline */ - pc->gfx_decoder = rdpgfx_client_context_new(pc->context.settings); - if (!pc->gfx_decoder) - { - WLog_ERR(TAG, "failed to initialize gfx capture client!"); - return; - } - - /* start GFX pipeline for fake client */ - gdi_graphics_pipeline_init(pc->context.gdi, pc->gfx_decoder); - - /* Set server and client side references to proxy data */ - gfx->custom = (void*)pdata; - server->custom = (void*)pdata; - /* Set client callbacks */ - gfx->ResetGraphics = pf_rdpgfx_reset_graphics; - gfx->StartFrame = pf_rdpgfx_start_frame; - gfx->EndFrame = pf_rdpgfx_end_frame; - gfx->SurfaceCommand = pf_rdpgfx_surface_command; - gfx->DeleteEncodingContext = pf_rdpgfx_delete_encoding_context; - gfx->CreateSurface = pf_rdpgfx_create_surface; - gfx->DeleteSurface = pf_rdpgfx_delete_surface; - gfx->SolidFill = pf_rdpgfx_solid_fill; - gfx->SurfaceToSurface = pf_rdpgfx_surface_to_surface; - gfx->SurfaceToCache = pf_rdpgfx_surface_to_cache; - gfx->CacheToSurface = pf_rdpgfx_cache_to_surface; - gfx->CacheImportReply = pf_rdpgfx_cache_import_reply; - gfx->EvictCacheEntry = pf_rdpgfx_evict_cache_entry; - gfx->MapSurfaceToOutput = pf_rdpgfx_map_surface_to_output; - gfx->MapSurfaceToWindow = pf_rdpgfx_map_surface_to_window; - gfx->MapSurfaceToScaledOutput = pf_rdpgfx_map_surface_to_scaled_output; - gfx->MapSurfaceToScaledWindow = pf_rdpgfx_map_surface_to_scaled_window; - /* No need to register to OnClose callback. GFX termination is handled in pf_server */ - gfx->OnOpen = pf_rdpgfx_on_open; - gfx->CapsConfirm = pf_rdpgfx_caps_confirm; - /* Set server callbacks */ - server->CapsAdvertise = pf_rdpgfx_caps_advertise; - server->FrameAcknowledge = pf_rdpgfx_frame_acknowledge; - server->CacheImportOffer = pf_rdpgfx_cache_import_offer; - server->QoeFrameAcknowledge = pf_rdpgfx_qoe_frame_acknowledge; -} diff --git a/server/proxy/pf_rdpgfx.h b/server/proxy/pf_rdpgfx.h deleted file mode 100644 index 70b1f84e3..000000000 --- a/server/proxy/pf_rdpgfx.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Mati Shabtay - * Copyright 2019 Kobi Mizrachi - * Copyright 2019 Idan Freiberg - * - * 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_SERVER_PROXY_PFRDPGFX_H -#define FREERDP_SERVER_PROXY_PFRDPGFX_H - -#include -#include -#include - -#include - -BOOL pf_server_rdpgfx_init(pServerContext* ps); -void pf_rdpgfx_pipeline_init(RdpgfxClientContext* gfx, RdpgfxServerContext* server, - proxyData* pdata); - -#endif /*FREERDP_SERVER_PROXY_PFRDPGFX_H*/ diff --git a/server/proxy/pf_rdpsnd.c b/server/proxy/pf_rdpsnd.c deleted file mode 100644 index b95de82d0..000000000 --- a/server/proxy/pf_rdpsnd.c +++ /dev/null @@ -1,91 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * 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. - */ - -#include -#include - -#include -#include -#include -#include - -#include -#include "pf_rdpsnd.h" - -#define TAG PROXY_TAG("rdpsnd") - -static void rdpsnd_activated(RdpsndServerContext* context) -{ - const AUDIO_FORMAT* agreed_format = NULL; - UINT16 i = 0, j = 0; - - WINPR_ASSERT(context); - for (i = 0; i < context->num_client_formats; i++) - { - for (j = 0; j < context->num_server_formats; j++) - { - WINPR_ASSERT(context->server_formats); - WINPR_ASSERT(context->client_formats); - if (audio_format_compatible(&context->server_formats[j], &context->client_formats[i])) - { - agreed_format = &context->server_formats[j]; - break; - } - } - - if (agreed_format != NULL) - break; - } - - if (agreed_format == NULL) - { - WLog_ERR(TAG, "rdpsnd_activated(): Could not agree on a audio format with the server"); - return; - } - - WINPR_ASSERT(context->SelectFormat); - context->SelectFormat(context, i); -} - -BOOL pf_server_rdpsnd_init(pServerContext* ps) -{ - RdpsndServerContext* rdpsnd; - - WINPR_ASSERT(ps); - - rdpsnd = ps->rdpsnd = rdpsnd_server_context_new(ps->vcm); - - if (!rdpsnd) - { - return FALSE; - } - - rdpsnd->rdpcontext = (rdpContext*)ps; - rdpsnd->data = (rdpContext*)ps; - - rdpsnd->num_server_formats = server_rdpsnd_get_formats(&rdpsnd->server_formats); - - if (rdpsnd->num_server_formats > 0) - rdpsnd->src_format = &rdpsnd->server_formats[0]; - - rdpsnd->Activated = rdpsnd_activated; - return TRUE; -} diff --git a/server/proxy/pf_rdpsnd.h b/server/proxy/pf_rdpsnd.h deleted file mode 100644 index 613587b3c..000000000 --- a/server/proxy/pf_rdpsnd.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * FreeRDP Proxy Server - * - * Copyright 2019 Kobi Mizrachi - * - * 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_SERVER_PROXY_RDPSND_H -#define FREERDP_SERVER_PROXY_RDPSND_H - -#include -#include - -#include - -BOOL pf_server_rdpsnd_init(pServerContext* ps); -void pf_server_rdpsnd_free(pServerContext* ps); - -#endif /* FREERDP_SERVER_PROXY_RDPSND_H */ diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c index be54d869e..703efa62b 100644 --- a/server/proxy/pf_server.c +++ b/server/proxy/pf_server.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -46,10 +47,6 @@ #include "pf_client.h" #include #include "pf_update.h" -#include "pf_rdpgfx.h" -#include "pf_disp.h" -#include "pf_rail.h" -#include "pf_channels.h" #include "proxy_modules.h" #include "pf_utils.h" @@ -229,12 +226,6 @@ static BOOL pf_server_post_connect(freerdp_peer* peer) PROXY_LOG_INFO(TAG, ps, "remote target is %s:%" PRIu16 "", client_settings->ServerHostname, client_settings->ServerPort); - if (!pf_server_channels_init(ps, peer)) - { - PROXY_LOG_INFO(TAG, ps, "failed to initialize server's channels!"); - return FALSE; - } - if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_POST_CONNECT, pdata, peer)) return FALSE; @@ -396,7 +387,7 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) settings->SupportMonitorLayoutPdu = TRUE; settings->SupportGraphicsPipeline = config->GFX; - if ((config->PassthroughCount > 0) || config->PassthroughIsBlacklist) + if (pf_utils_is_passthrough(config)) { if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE)) return FALSE; @@ -445,6 +436,8 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer) pdata->server_receive_channel_data_original = peer->ReceiveChannelData; peer->ReceiveChannelData = pf_server_receive_channel_data_hook; + if (!stream_dump_register_handlers(peer->context, CONNECTION_STATE_NEGO)) + return FALSE; return TRUE; } @@ -463,20 +456,14 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg) freerdp_peer* client = (freerdp_peer*)arg; proxyServer* server; size_t count; - BOOL rc; WINPR_ASSERT(client); server = (proxyServer*)client->ContextExtra; WINPR_ASSERT(server); - ArrayList_Lock(server->peer_list); - rc = ArrayList_Append(server->peer_list, _GetCurrentThread()); count = ArrayList_Count(server->peer_list); - ArrayList_Unlock(server->peer_list); - if (!rc) - goto out_free_peer; if (!pf_context_init_server_context(client)) goto out_free_peer; @@ -596,7 +583,6 @@ fail: PROXY_LOG_INFO(TAG, ps, "freeing server's channels"); - pf_server_channels_free(ps, client); WINPR_ASSERT(client->Close); client->Close(client); @@ -613,10 +599,16 @@ out_free_peer: WaitForSingleObject(pdata->client_thread, INFINITE); } - ArrayList_Lock(server->peer_list); - ArrayList_Remove(server->peer_list, _GetCurrentThread()); - count = ArrayList_Count(server->peer_list); - ArrayList_Unlock(server->peer_list); + /* If the server is shutting down the peer_list is already + * locked and we should not try to remove it here but instead + * let the ArrayList_Clear handle that. */ + if (WaitForSingleObject(server->stopEvent, 0) != WAIT_OBJECT_0) + { + ArrayList_Lock(server->peer_list); + ArrayList_Remove(server->peer_list, _GetCurrentThread()); + count = ArrayList_Count(server->peer_list); + ArrayList_Unlock(server->peer_list); + } PROXY_LOG_DBG(TAG, ps, "Removed peer, %" PRIuz " connected", count); freerdp_peer_context_free(client); freerdp_peer_free(client); @@ -639,11 +631,17 @@ static BOOL pf_server_start_peer(freerdp_peer* client) server = (proxyServer*)client->ContextExtra; WINPR_ASSERT(server); - hThread = CreateThread(NULL, 0, pf_server_handle_peer, (void*)client, 0, NULL); + hThread = CreateThread(NULL, 0, pf_server_handle_peer, (void*)client, CREATE_SUSPENDED, NULL); if (!hThread) return FALSE; - return TRUE; + if (!ArrayList_Append(server->peer_list, hThread)) + { + CloseHandle(hThread); + return FALSE; + } + + return ResumeThread(hThread) == 0; } static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* client) @@ -739,10 +737,14 @@ BOOL pf_server_start_with_peer_socket(proxyServer* server, int peer_fd) { struct sockaddr_storage peer_addr; socklen_t len = sizeof(peer_addr); - freerdp_peer* client = freerdp_peer_new(peer_fd); + freerdp_peer* client = NULL; WINPR_ASSERT(server); + if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0) + goto fail; + + client = freerdp_peer_new(peer_fd); if (!client) goto fail; @@ -839,6 +841,10 @@ proxyServer* pf_server_new(const proxyConfig* config) server->listener->info = server; server->listener->PeerAccepted = pf_server_peer_accepted; + + if (!pf_modules_add(server->module, pf_config_plugin, (void*)config)) + goto out; + return server; out: @@ -901,17 +907,6 @@ BOOL pf_server_run(proxyServer* server) return rc; } -static BOOL disconnect_client(void* data, size_t index, va_list ap) -{ - proxyData* pdata = data; - - WINPR_UNUSED(index); - WINPR_UNUSED(ap); - - proxy_data_abort_connect(pdata); - return TRUE; -} - void pf_server_stop(proxyServer* server) { diff --git a/server/proxy/pf_update.c b/server/proxy/pf_update.c index c52c03b96..aab5878f3 100644 --- a/server/proxy/pf_update.c +++ b/server/proxy/pf_update.c @@ -604,6 +604,7 @@ void pf_client_register_update_callbacks(rdpUpdate* update) update->ServerStatusInfo = pf_client_server_status_info; update->SetKeyboardIndicators = pf_client_set_keyboard_indicators; update->SetKeyboardImeStatus = pf_client_set_keyboard_ime_status; + /* Rail window updates */ update->window->WindowCreate = pf_client_window_create; update->window->WindowUpdate = pf_client_window_update; @@ -615,6 +616,7 @@ void pf_client_register_update_callbacks(rdpUpdate* update) update->window->NotifyIconDelete = pf_client_notify_icon_delete; update->window->MonitoredDesktop = pf_client_monitored_desktop; update->window->NonMonitoredDesktop = pf_client_non_monitored_desktop; + /* Pointer updates */ update->pointer->PointerSystem = pf_client_send_pointer_system; update->pointer->PointerPosition = pf_client_send_pointer_position; diff --git a/server/proxy/pf_utils.c b/server/proxy/pf_utils.c index e3dd92016..25b4f40f1 100644 --- a/server/proxy/pf_utils.c +++ b/server/proxy/pf_utils.c @@ -53,3 +53,11 @@ int pf_utils_channel_is_passthrough(const proxyConfig* config, const char* name) return 1; return -1; } + +BOOL pf_utils_is_passthrough(const proxyConfig* config) +{ + WINPR_ASSERT(config); + + /* TODO: For the time being only passthrough mode is supported. */ + return TRUE; +} diff --git a/server/proxy/pf_utils.h b/server/proxy/pf_utils.h index 104154b7f..b54d81c4f 100644 --- a/server/proxy/pf_utils.h +++ b/server/proxy/pf_utils.h @@ -34,4 +34,6 @@ */ int pf_utils_channel_is_passthrough(const proxyConfig* config, const char* name); +BOOL pf_utils_is_passthrough(const proxyConfig* config); + #endif /* FREERDP_SERVER_PROXY_PFUTILS_H */ diff --git a/server/proxy/proxy_modules.h b/server/proxy/proxy_modules.h index eccca8f42..38aab1b38 100644 --- a/server/proxy/proxy_modules.h +++ b/server/proxy/proxy_modules.h @@ -35,6 +35,7 @@ enum _PF_FILTER_TYPE FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE, /* proxyChannelDataEventInfo */ FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, /* proxyFetchTargetEventInfo */ FILTER_TYPE_SERVER_PEER_LOGON, /* proxyServerPeerLogon */ + FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_CREATE, /* proxyChannelDataEventInfo */ FILTER_LAST };