mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 09:54:26 +08:00
Refactored proxy and proxy-modules:
* Split out proxy headers and moved to public API to allow external modules to be built. * Split proxy into proxy library and proxy binary. The library can be used by other applications and provides a simple API * Improved channel passthrough, now all channels including dynamic channels work. * Extended module API to hook more events, improved module samples * Cleaned up proxy code, removed global static variables used, added WINPR_ASSERT
This commit is contained in:
parent
81a2f9e434
commit
976c3c2ab9
@ -882,7 +882,7 @@ set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSIO
|
||||
# Proxy plugins path
|
||||
if(NOT DEFINED PROXY_PLUGINDIR)
|
||||
message("using default plugins location")
|
||||
set(FREERDP_PROXY_PLUGINDIR "${PROJECT_BINARY_DIR}/server/proxy/plugins")
|
||||
set(FREERDP_PROXY_PLUGINDIR "${FREERDP_PLUGIN_PATH}/proxy/")
|
||||
else()
|
||||
set(FREERDP_PROXY_PLUGINDIR "${PROXY_PLUGINDIR}")
|
||||
endif()
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <freerdp/client/rdpsnd.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
#include "../../../../server/proxy/pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
typedef struct rdpsnd_proxy_plugin rdpsndProxyPlugin;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
message("PRELOADING windows cache")
|
||||
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
|
||||
set (WITH_SERVER "ON" CACHE BOOL "Build server binaries")
|
||||
set (WITH_PROXY_MODULES "OFF" CACHE BOOL "Do not build proxy modules")
|
||||
set (CHANNEL_URBDRC OFF CACHE BOOL "USB redirection")
|
||||
set (BUILD_TESTING ON CACHE BOOL "build testing")
|
||||
set (WITH_SANITIZE_ADDRESS ON)
|
||||
|
185
include/freerdp/server/proxy/proxy_config.h
Normal file
185
include/freerdp/server/proxy/proxy_config.h
Normal file
@ -0,0 +1,185 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
* 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_SERVER_PROXY_CONFIG_H
|
||||
#define FREERDP_SERVER_PROXY_CONFIG_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/ini.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
typedef struct proxy_config proxyConfig;
|
||||
|
||||
struct proxy_config
|
||||
{
|
||||
/* server */
|
||||
char* Host;
|
||||
UINT16 Port;
|
||||
|
||||
/* target */
|
||||
BOOL FixedTarget;
|
||||
char* TargetHost;
|
||||
UINT16 TargetPort;
|
||||
|
||||
/* input */
|
||||
BOOL Keyboard;
|
||||
BOOL Mouse;
|
||||
|
||||
/* server security */
|
||||
BOOL ServerTlsSecurity;
|
||||
BOOL ServerRdpSecurity;
|
||||
BOOL ServerNlaSecurity;
|
||||
|
||||
/* client security */
|
||||
BOOL ClientNlaSecurity;
|
||||
BOOL ClientTlsSecurity;
|
||||
BOOL ClientRdpSecurity;
|
||||
BOOL ClientAllowFallbackToTls;
|
||||
|
||||
/* channels */
|
||||
BOOL GFX;
|
||||
BOOL DisplayControl;
|
||||
BOOL Clipboard;
|
||||
BOOL AudioOutput;
|
||||
BOOL RemoteApp;
|
||||
|
||||
BOOL PassthroughIsBlacklist;
|
||||
char** Passthrough;
|
||||
size_t PassthroughCount;
|
||||
|
||||
/* clipboard specific settings */
|
||||
BOOL TextOnly;
|
||||
UINT32 MaxTextLength;
|
||||
|
||||
/* gfx settings */
|
||||
BOOL DecodeGFX;
|
||||
|
||||
/* modules */
|
||||
char** Modules; /* module file names to load */
|
||||
size_t ModulesCount;
|
||||
|
||||
char** RequiredPlugins; /* required plugin names */
|
||||
size_t RequiredPluginsCount;
|
||||
|
||||
char* CertificateFile;
|
||||
char* CertificateContent;
|
||||
|
||||
char* PrivateKeyFile;
|
||||
char* PrivateKeyContent;
|
||||
|
||||
char* RdpKeyFile;
|
||||
char* RdpKeyContent;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief server_config_load_ini Create a proxyConfig from a already loaded
|
||||
* INI file.
|
||||
*
|
||||
* @param ini A pointer to the parsed INI file. Must NOT be NULL.
|
||||
*
|
||||
* @return A proxyConfig or NULL in case of failure.
|
||||
*/
|
||||
FREERDP_API proxyConfig* server_config_load_ini(wIniFile* ini);
|
||||
/**
|
||||
* @brief pf_server_config_load_file Create a proxyConfig from a INI file found at path.
|
||||
*
|
||||
* @param path The path of the INI file
|
||||
*
|
||||
* @return A proxyConfig or NULL in case of failure.
|
||||
*/
|
||||
FREERDP_API proxyConfig* pf_server_config_load_file(const char* path);
|
||||
|
||||
/**
|
||||
* @brief pf_server_config_load_buffer Create a proxyConfig from a memory string buffer in INI
|
||||
* file format
|
||||
*
|
||||
* @param buffer A pointer to the '\0' terminated INI string.
|
||||
*
|
||||
* @return A proxyConfig or NULL in case of failure.
|
||||
*/
|
||||
FREERDP_API proxyConfig* pf_server_config_load_buffer(const char* buffer);
|
||||
|
||||
/**
|
||||
* @brief pf_server_config_print Print the configuration to stdout
|
||||
*
|
||||
* @param config A pointer to the configuration to print. Must NOT be NULL.
|
||||
*/
|
||||
FREERDP_API void pf_server_config_print(const proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_server_config_free Releases all resources associated with proxyConfig
|
||||
*
|
||||
* @param config A pointer to the proxyConfig to clean up. Might be NULL.
|
||||
*/
|
||||
FREERDP_API void pf_server_config_free(proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_config_required_plugins_count
|
||||
*
|
||||
* @param config A pointer to the proxyConfig. Must NOT be NULL.
|
||||
*
|
||||
* @return The number of required plugins configured.
|
||||
*/
|
||||
FREERDP_API size_t pf_config_required_plugins_count(const proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_config_required_plugin
|
||||
* @param config A pointer to the proxyConfig. Must NOT be NULL.
|
||||
* @param index The index of the plugin to return
|
||||
*
|
||||
* @return The name of the plugin or NULL.
|
||||
*/
|
||||
FREERDP_API const char* pf_config_required_plugin(const proxyConfig* config, size_t index);
|
||||
|
||||
/**
|
||||
* @brief pf_config_modules_count
|
||||
*
|
||||
* @param config A pointer to the proxyConfig. Must NOT be NULL.
|
||||
*
|
||||
* @return The number of proxy modules configured.
|
||||
*/
|
||||
FREERDP_API size_t pf_config_modules_count(const proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_config_modules
|
||||
* @param config A pointer to the proxyConfig. Must NOT be NULL.
|
||||
*
|
||||
* @return An array of strings of size pf_config_modules_count with the module names.
|
||||
*/
|
||||
FREERDP_API const char** pf_config_modules(const proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_config_clone Create a copy of the configuration
|
||||
* @param dst A pointer that receives the newly allocated copy
|
||||
* @param config The source configuration to copy
|
||||
*
|
||||
* @return TRUE for success, FALSE otherwise
|
||||
*/
|
||||
FREERDP_API BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
#endif /* FREERDP_SERVER_PROXY_CONFIG_H */
|
@ -34,12 +34,13 @@
|
||||
#include <freerdp/server/cliprdr.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
|
||||
#include "pf_config.h"
|
||||
#include "pf_server.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
|
||||
#define PROXY_SESSION_ID_LENGTH 32
|
||||
|
||||
typedef struct proxy_data proxyData;
|
||||
typedef struct proxy_module proxyModule;
|
||||
typedef struct channel_data_event_info proxyChannelDataEventInfo;
|
||||
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's server.
|
||||
@ -58,15 +59,14 @@ struct p_server_context
|
||||
DispServerContext* disp;
|
||||
CliprdrServerContext* cliprdr;
|
||||
RdpsndServerContext* rdpsnd;
|
||||
|
||||
HANDLE* vc_handles; /* static virtual channels open handles */
|
||||
wHashTable* vc_ids; /* channel_name -> channel_id map */
|
||||
};
|
||||
typedef struct p_server_context pServerContext;
|
||||
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's client.
|
||||
*/
|
||||
typedef struct p_client_context pClientContext;
|
||||
|
||||
struct p_client_context
|
||||
{
|
||||
rdpContext context;
|
||||
@ -91,16 +91,26 @@ struct p_client_context
|
||||
*/
|
||||
BOOL allow_next_conn_failure;
|
||||
|
||||
wHashTable* vc_ids; /* channel_name -> channel_id map */
|
||||
BOOL connected; /* Set after client post_connect. */
|
||||
|
||||
pReceiveChannelData client_receive_channel_data_original;
|
||||
wArrayList* cached_server_channel_data;
|
||||
BOOL (*sendChannelData)(pClientContext* pc, const proxyChannelDataEventInfo* ev);
|
||||
|
||||
/* X509 specific */
|
||||
char* remote_hostname;
|
||||
wStream* remote_pem;
|
||||
UINT16 remote_port;
|
||||
UINT32 remote_flags;
|
||||
};
|
||||
typedef struct p_client_context pClientContext;
|
||||
|
||||
/**
|
||||
* Holds data common to both sides of a proxy's session.
|
||||
*/
|
||||
struct proxy_data
|
||||
{
|
||||
proxyConfig* config;
|
||||
proxyModule* module;
|
||||
const proxyConfig* config;
|
||||
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
@ -113,6 +123,7 @@ struct proxy_data
|
||||
|
||||
/* used to external modules to store per-session info */
|
||||
wHashTable* modules_info;
|
||||
psPeerReceiveChannelData server_receive_channel_data_original;
|
||||
};
|
||||
|
||||
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
|
@ -19,8 +19,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_SERVER_PROXY_PFLOG_H
|
||||
#define FREERDP_SERVER_PROXY_PFLOG_H
|
||||
#ifndef FREERDP_SERVER_PROXY_LOG_H
|
||||
#define FREERDP_SERVER_PROXY_LOG_H
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
@ -34,17 +34,17 @@
|
||||
*/
|
||||
|
||||
/* log macros that prepends session id and function name tp the log message */
|
||||
#define LOG_INFO(_tag, _context, _format, ...) \
|
||||
#define PROXY_LOG_INFO(_tag, _context, _format, ...) \
|
||||
WLog_INFO(TAG, "[SessionID=%s][%s]: " _format, _context->pdata->session_id, __FUNCTION__, \
|
||||
##__VA_ARGS__)
|
||||
#define LOG_ERR(_tag, _context, _format, ...) \
|
||||
#define PROXY_LOG_ERR(_tag, _context, _format, ...) \
|
||||
WLog_ERR(TAG, "[SessionID=%s][%s]: " _format, _context->pdata->session_id, __FUNCTION__, \
|
||||
##__VA_ARGS__)
|
||||
#define LOG_DBG(_tag, _context, _format, ...) \
|
||||
#define PROXY_LOG_DBG(_tag, _context, _format, ...) \
|
||||
WLog_DBG(TAG, "[SessionID=%s][%s]: " _format, _context->pdata->session_id, __FUNCTION__, \
|
||||
##__VA_ARGS__)
|
||||
#define LOG_WARN(_tag, _context, _format, ...) \
|
||||
#define PROXY_LOG_WARN(_tag, _context, _format, ...) \
|
||||
WLog_WARN(TAG, "[SessionID=%s][%s]: " _format, _context->pdata->session_id, __FUNCTION__, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFLOG_H */
|
||||
#endif /* FREERDP_SERVER_PROXY_LOG_H */
|
187
include/freerdp/server/proxy/proxy_modules_api.h
Normal file
187
include/freerdp/server/proxy/proxy_modules_api.h
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
|
||||
*
|
||||
* 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_MODULES_API_H
|
||||
#define FREERDP_SERVER_PROXY_MODULES_API_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/sspi.h>
|
||||
|
||||
#define MODULE_TAG(module) "proxy.modules." module
|
||||
|
||||
typedef struct proxy_data proxyData;
|
||||
typedef struct proxy_module proxyModule;
|
||||
typedef struct proxy_plugin proxyPlugin;
|
||||
typedef struct proxy_plugins_manager proxyPluginsManager;
|
||||
|
||||
/* hook callback. should return TRUE on success or FALSE on error. */
|
||||
typedef BOOL (*proxyHookFn)(proxyPlugin*, proxyData*, void*);
|
||||
|
||||
/*
|
||||
* Filter callback:
|
||||
* It MUST return TRUE if the related event should be proxied,
|
||||
* or FALSE if it should be ignored.
|
||||
*/
|
||||
typedef BOOL (*proxyFilterFn)(proxyPlugin*, proxyData*, void*);
|
||||
|
||||
/* describes a plugin: name, description and callbacks to execute.
|
||||
*
|
||||
* This is public API, so always add new fields at the end of the struct to keep
|
||||
* some backward compatibility.
|
||||
*/
|
||||
struct proxy_plugin
|
||||
{
|
||||
const char* name; /* 0: unique module name */
|
||||
const char* description; /* 1: module description */
|
||||
|
||||
UINT64 reserved1[32 - 2]; /* 2-32 */
|
||||
|
||||
BOOL (*PluginUnload)(proxyPlugin* plugin); /* 33 */
|
||||
UINT64 reserved2[66 - 34]; /* 34 - 65 */
|
||||
|
||||
/* proxy hooks. a module can set these function pointers to register hooks */
|
||||
proxyHookFn ClientInitConnect; /* 66 custom=rdpContext* */
|
||||
proxyHookFn ClientUninitConnect; /* 67 custom=rdpContext* */
|
||||
proxyHookFn ClientPreConnect; /* 68 custom=rdpContext* */
|
||||
proxyHookFn ClientPostConnect; /* 69 custom=rdpContext* */
|
||||
proxyHookFn ClientPostDisconnect; /* 70 custom=rdpContext* */
|
||||
proxyHookFn ClientX509Certificate; /* 71 custom=rdpContext* */
|
||||
proxyHookFn ClientLoginFailure; /* 72 custom=rdpContext* */
|
||||
proxyHookFn ClientEndPaint; /* 73 custom=rdpContext* */
|
||||
|
||||
UINT64 reserved3[96 - 74]; /* 74-95 */
|
||||
|
||||
proxyHookFn ServerPostConnect; /* 96 custom=freerdp_peer* */
|
||||
proxyHookFn ServerPeerActivate; /* 97 custom=freerdp_peer* */
|
||||
proxyHookFn ServerChannelsInit; /* 98 custom=freerdp_peer* */
|
||||
proxyHookFn ServerChannelsFree; /* 99 custom=freerdp_peer* */
|
||||
proxyHookFn ServerSessionEnd; /* 100 custom=freerdp_peer* */
|
||||
|
||||
UINT64 reserved4[128 - 101]; /* 101 - 127 */
|
||||
|
||||
/* proxy filters. a module can set these function pointers to register filters */
|
||||
proxyFilterFn KeyboardEvent; /* 128 */
|
||||
proxyFilterFn MouseEvent; /* 129 */
|
||||
proxyFilterFn ClientChannelData; /* 130 passthrough channels data */
|
||||
proxyFilterFn ServerChannelData; /* 131 passthrough channels data */
|
||||
proxyFilterFn DynamicChannelCreate; /* 132 passthrough drdynvc channel create data */
|
||||
proxyFilterFn ServerFetchTargetAddr; /* 133 */
|
||||
proxyFilterFn ServerPeerLogon; /* 134 */
|
||||
|
||||
UINT64 reserved5[160 - 135]; /* 135-159 */
|
||||
|
||||
/* Runtime data fields */
|
||||
proxyPluginsManager* mgr; /* 160 */ /** Set during plugin registration */
|
||||
void* userdata; /* 161 */ /** Custom data provided with RegisterPlugin, memory managed
|
||||
outside of plugin. */
|
||||
void* custom; /* 162 */ /** Custom configuration data, must be allocated in RegisterPlugin and
|
||||
freed in PluginUnload */
|
||||
|
||||
UINT64 reserved6[192 - 163]; /* 163-191 Add some filler data to allow for new callbacks or
|
||||
* fields without breaking API */
|
||||
};
|
||||
|
||||
/*
|
||||
* Main API for use by external modules.
|
||||
* Supports:
|
||||
* - Registering a plugin.
|
||||
* - Setting/getting plugin's per-session specific data.
|
||||
* - Aborting a session.
|
||||
*/
|
||||
struct proxy_plugins_manager
|
||||
{
|
||||
/* 0 used for registering a fresh new proxy plugin. */
|
||||
BOOL(*RegisterPlugin)
|
||||
(struct proxy_plugins_manager* mgr, const proxyPlugin* plugin);
|
||||
|
||||
/* 1 used for setting plugin's per-session info. */
|
||||
BOOL (*SetPluginData)(struct proxy_plugins_manager* mgr, const char*, proxyData*, void*);
|
||||
|
||||
/* 2 used for getting plugin's per-session info. */
|
||||
void* (*GetPluginData)(struct proxy_plugins_manager* mgr, const char*, proxyData*);
|
||||
|
||||
/* 3 used for aborting a session. */
|
||||
void (*AbortConnect)(struct proxy_plugins_manager* mgr, proxyData*);
|
||||
|
||||
UINT64 reserved[128 - 4]; /* 4-127 reserved fields */
|
||||
};
|
||||
|
||||
typedef BOOL (*proxyModuleEntryPoint)(proxyPluginsManager* plugins_manager, void* userdata);
|
||||
|
||||
/* filter events parameters */
|
||||
#define WINPR_PACK_PUSH
|
||||
#include <winpr/pack.h>
|
||||
typedef struct proxy_keyboard_event_info
|
||||
{
|
||||
UINT16 flags;
|
||||
UINT16 rdp_scan_code;
|
||||
} proxyKeyboardEventInfo;
|
||||
|
||||
typedef struct proxy_mouse_event_info
|
||||
{
|
||||
UINT16 flags;
|
||||
UINT16 x;
|
||||
UINT16 y;
|
||||
} proxyMouseEventInfo;
|
||||
|
||||
typedef struct channel_data_event_info
|
||||
{
|
||||
/* channel metadata */
|
||||
const char* channel_name;
|
||||
UINT16 channel_id;
|
||||
|
||||
/* actual data */
|
||||
const BYTE* data;
|
||||
size_t data_len;
|
||||
size_t total_size;
|
||||
UINT32 flags;
|
||||
} proxyChannelDataEventInfo;
|
||||
|
||||
typedef enum proxy_fetch_target_method
|
||||
{
|
||||
PROXY_FETCH_TARGET_METHOD_DEFAULT,
|
||||
PROXY_FETCH_TARGET_METHOD_CONFIG,
|
||||
PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO,
|
||||
PROXY_FETCH_TARGET_USE_CUSTOM_ADDR
|
||||
} ProxyFetchTargetMethod;
|
||||
|
||||
typedef struct fetch_target_event_info
|
||||
{
|
||||
/* out values */
|
||||
char* target_address;
|
||||
UINT16 target_port;
|
||||
|
||||
/*
|
||||
* If this value is set to true by a plugin, target info will be fetched from config and proxy
|
||||
* will connect any client to the same remote server.
|
||||
*/
|
||||
ProxyFetchTargetMethod fetch_method;
|
||||
} proxyFetchTargetEventInfo;
|
||||
|
||||
typedef struct server_peer_logon
|
||||
{
|
||||
const SEC_WINNT_AUTH_IDENTITY* identity;
|
||||
BOOL automatic;
|
||||
} proxyServerPeerLogon;
|
||||
#define WINPR_PACK_POP
|
||||
#include <winpr/pack.h>
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_MODULES_API_H */
|
114
include/freerdp/server/proxy/proxy_server.h
Normal file
114
include/freerdp/server/proxy/proxy_server.h
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
* 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_SERVER_PROXY_SERVER_H
|
||||
#define FREERDP_SERVER_PROXY_SERVER_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include <freerdp/server/proxy/proxy_modules_api.h>
|
||||
|
||||
typedef struct proxy_server proxyServer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief pf_server_new Creates a new proxy server instance
|
||||
*
|
||||
* @param config The proxy server configuration to use. Must NOT be NULL.
|
||||
*
|
||||
* @return A new proxy server instance or NULL on failure.
|
||||
*/
|
||||
FREERDP_API proxyServer* pf_server_new(const proxyConfig* config);
|
||||
|
||||
/**
|
||||
* @brief pf_server_free Cleans up a (stopped) proxy server instance.
|
||||
*
|
||||
* @param server The proxy server to clean up. Might be NULL.
|
||||
*/
|
||||
FREERDP_API void pf_server_free(proxyServer* server);
|
||||
|
||||
/**
|
||||
* @brief pf_server_add_module Allows registering proxy modules that are
|
||||
* build-in instead of shipped as separate
|
||||
* module loaded at runtime.
|
||||
*
|
||||
* @param server A proxy instance to add the module to. Must NOT be NULL
|
||||
* @param ep The proxy entry function to add. Must NOT be NULL
|
||||
* @param userdata Custom data for the module. May be NULL
|
||||
*
|
||||
* @return TRUE for success, FALSE otherwise.
|
||||
*/
|
||||
FREERDP_API BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep,
|
||||
void* userdata);
|
||||
|
||||
/**
|
||||
* @brief pf_server_start Starts the proxy, binding the configured port.
|
||||
*
|
||||
* @param server The server instance. Must NOT be NULL.
|
||||
*
|
||||
* @return TRUE for success, FALSE on error
|
||||
*/
|
||||
FREERDP_API BOOL pf_server_start(proxyServer* server);
|
||||
|
||||
/**
|
||||
* @brief pf_server_start_from_socket Starts the proxy using an existing bound socket
|
||||
*
|
||||
* @param server The server instance. Must NOT be NULL.
|
||||
* @param socket The bound socket to wait for events on.
|
||||
*
|
||||
* @return TRUE for success, FALSE on error
|
||||
*/
|
||||
FREERDP_API BOOL pf_server_start_from_socket(proxyServer* server, int socket);
|
||||
|
||||
/**
|
||||
* @brief pf_server_start_with_peer_socket Use existing peer socket
|
||||
*
|
||||
* @param server The server instance. Must NOT be NULL.
|
||||
* @param socket Ready to use peer socket
|
||||
*
|
||||
* @return TRUE for success, FALSE on error
|
||||
*/
|
||||
FREERDP_API BOOL pf_server_start_with_peer_socket(proxyServer* server, int socket);
|
||||
|
||||
/**
|
||||
* @brief pf_server_stop Stops a server instance asynchronously.
|
||||
* Can be called from any thread to stop a running server instance.
|
||||
* @param server A pointer to the server instance to stop. May be NULL.
|
||||
*/
|
||||
FREERDP_API void pf_server_stop(proxyServer* server);
|
||||
|
||||
/**
|
||||
* @brief pf_server_run This (blocking) function runs the main loop of the
|
||||
* proxy.
|
||||
*
|
||||
* @param server The server instance. Must NOT be NULL.
|
||||
*
|
||||
* @return TRUE for successful termination, FALSE otherwise.
|
||||
*/
|
||||
FREERDP_API BOOL pf_server_run(proxyServer* server);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_SERVER_H */
|
@ -329,7 +329,6 @@ BOOL freerdp_peer_set_local_and_hostname(freerdp_peer* client,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
|
||||
{
|
||||
int i;
|
||||
|
@ -893,6 +893,7 @@ BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings)
|
||||
BIO* bio;
|
||||
EVP_PKEY* privkey;
|
||||
X509* x509;
|
||||
|
||||
/**
|
||||
* SSL_OP_NO_SSLv2:
|
||||
*
|
||||
|
@ -18,13 +18,11 @@
|
||||
# limitations under the License.
|
||||
|
||||
include(CMakeDependentOption)
|
||||
set(MODULE_NAME "freerdp-proxy")
|
||||
set(MODULE_NAME "freerdp-server-proxy")
|
||||
set(MODULE_PREFIX "FREERDP_SERVER_PROXY")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
freerdp_proxy.c
|
||||
pf_context.c
|
||||
pf_context.h
|
||||
pf_channels.c
|
||||
pf_channels.h
|
||||
pf_client.c
|
||||
@ -44,18 +42,19 @@ set(${MODULE_PREFIX}_SRCS
|
||||
pf_gdi.c
|
||||
pf_gdi.h
|
||||
pf_config.c
|
||||
pf_config.h
|
||||
pf_graphics.c
|
||||
pf_graphics.h
|
||||
pf_modules.c
|
||||
pf_modules.h
|
||||
pf_cliprdr.c
|
||||
pf_cliprdr.h
|
||||
pf_rdpsnd.c
|
||||
pf_rdpsnd.h
|
||||
pf_log.h
|
||||
pf_utils.h
|
||||
pf_utils.c
|
||||
)
|
||||
|
||||
set(PROXY_APP_SRCS freerdp_proxy.c)
|
||||
|
||||
# On windows create dll version information.
|
||||
# Vendor, product and year are already set in top level CMakeLists.txt
|
||||
if (WIN32)
|
||||
@ -70,24 +69,61 @@ if (WIN32)
|
||||
@ONLY)
|
||||
|
||||
set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
list(APPEND PROXY_APP_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
|
||||
|
||||
if (WITH_LIBRARY_VERSIONING)
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
|
||||
endif()
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-server)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rdpgfx-client)
|
||||
if (NOT BUILTIN_CHANNELS)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rdpgfx-client)
|
||||
get_target_property(CUR_INSTALL_RPATH ${MODULE_NAME} INSTALL_RPATH)
|
||||
if (NOT APPLE)
|
||||
set(CUR_INSTALL_RPATH "${CUR_INSTALL_RPATH}:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}")
|
||||
endif()
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES INSTALL_RPATH ${CUR_INSTALL_RPATH})
|
||||
endif()
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server EXPORT FreeRDP-ProxyTargets)
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC)
|
||||
install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
|
||||
install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
|
||||
endif()
|
||||
# pkg-config
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp-proxy.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp-server-proxy${FREERDP_VERSION_MAJOR}.pc @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp-server-proxy${FREERDP_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
||||
export(PACKAGE freerdp-proxy)
|
||||
|
||||
SetFreeRDPCMakeInstallDir(FREERDP_PROXY_CMAKE_INSTALL_DIR "FreeRDP-Proxy${FREERDP_VERSION_MAJOR}")
|
||||
|
||||
configure_package_config_file(FreeRDP-ProxyConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ProxyConfig.cmake
|
||||
INSTALL_DESTINATION ${FREERDP_PROXY_CMAKE_INSTALL_DIR}
|
||||
PATH_VARS FREERDP_INCLUDE_DIR)
|
||||
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ProxyConfigVersion.cmake
|
||||
VERSION ${FREERDP_VERSION} COMPATIBILITY SameMajorVersion)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ProxyConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ProxyConfigVersion.cmake
|
||||
DESTINATION ${FREERDP_PROXY_CMAKE_INSTALL_DIR})
|
||||
install(EXPORT FreeRDP-ProxyTargets DESTINATION ${FREERDP_PROXY_CMAKE_INSTALL_DIR})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/proxy")
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(WITH_PROXY_MODULES "Compile proxy modules" OFF "WITH_PROXY" OFF)
|
||||
option(WITH_PROXY_APP "Compile proxy application" ON)
|
||||
|
||||
if (WITH_PROXY_APP)
|
||||
add_subdirectory("cli")
|
||||
endif()
|
||||
|
||||
option(WITH_PROXY_MODULES "Compile proxy modules" ON)
|
||||
if (WITH_PROXY_MODULES)
|
||||
add_subdirectory("modules")
|
||||
endif()
|
||||
|
10
server/proxy/FreeRDP-ProxyConfig.cmake.in
Normal file
10
server/proxy/FreeRDP-ProxyConfig.cmake.in
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(FreeRDP-Proxy_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@")
|
||||
set(FreeRDP-Proxy_VERSION_MINOR "@FREERDP_VERSION_MINOR@")
|
||||
set(FreeRDP-Proxy_VERSION_REVISION "@FREERDP_VERSION_REVISION@")
|
||||
|
||||
set_and_check(FreeRDP-Proxy_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@")
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FreeRDP-ProxyTargets.cmake")
|
46
server/proxy/cli/CMakeLists.txt
Normal file
46
server/proxy/cli/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP Proxy Server
|
||||
#
|
||||
# Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
# 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.
|
||||
|
||||
set(PROXY_APP_SRCS freerdp_proxy.c)
|
||||
|
||||
# On windows create dll version information.
|
||||
# Vendor, product and year are already set in top level CMakeLists.txt
|
||||
if (WIN32)
|
||||
set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
|
||||
set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
|
||||
set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
|
||||
set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
|
||||
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
@ONLY)
|
||||
|
||||
list(APPEND PROXY_APP_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
set(APP_NAME "freerdp-proxy")
|
||||
add_executable(${APP_NAME}
|
||||
${PROXY_APP_SRCS})
|
||||
target_link_libraries(${APP_NAME} ${MODULE_NAME})
|
||||
install(TARGETS ${APP_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC)
|
||||
install(FILES ${CMAKE_PDB_BINARY_DIR}/${APP_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${APP_NAME} PROPERTY FOLDER "Server/proxy")
|
@ -19,14 +19,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "pf_server.h"
|
||||
#include "pf_config.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_modules.h"
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/version.h>
|
||||
#include <freerdp/build-config.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_server.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
@ -34,22 +34,29 @@
|
||||
|
||||
static proxyServer* server = NULL;
|
||||
|
||||
static WINPR_NORETURN(void cleanup_handler(int signum))
|
||||
#if defined(_WIN32)
|
||||
static const char* strsignal(int signum)
|
||||
{
|
||||
switch (signum)
|
||||
{
|
||||
case SIGINT:
|
||||
return "SIGINT";
|
||||
case SIGTERM:
|
||||
return "SIGTERM";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cleanup_handler(int signum)
|
||||
{
|
||||
printf("\n");
|
||||
WLog_INFO(TAG, "[%s]: caught signal %d, starting cleanup...", __FUNCTION__, signum);
|
||||
WLog_INFO(TAG, "[%s]: caught signal %s [%d], starting cleanup...", __FUNCTION__,
|
||||
strsignal(signum), signum);
|
||||
|
||||
WLog_INFO(TAG, "stopping all connections.");
|
||||
pf_server_stop(server);
|
||||
|
||||
WLog_INFO(TAG, "freeing loaded modules and plugins.");
|
||||
pf_modules_free();
|
||||
|
||||
pf_server_config_free(server->config);
|
||||
pf_server_free(server);
|
||||
|
||||
WLog_INFO(TAG, "exiting.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void pf_server_register_signal_handlers(void)
|
||||
@ -62,30 +69,14 @@ static void pf_server_register_signal_handlers(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL is_all_required_modules_loaded(proxyConfig* config)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < config->RequiredPluginsCount; i++)
|
||||
{
|
||||
const char* plugin_name = config->RequiredPlugins[i];
|
||||
|
||||
if (!pf_modules_is_plugin_loaded(plugin_name))
|
||||
{
|
||||
WLog_ERR(TAG, "Required plugin '%s' is not loaded. stopping.", plugin_name);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
proxyConfig* config = NULL;
|
||||
char* config_path = "config.ini";
|
||||
int status = -1;
|
||||
|
||||
pf_server_register_signal_handlers();
|
||||
|
||||
WLog_INFO(TAG, "freerdp-proxy version info:");
|
||||
WLog_INFO(TAG, "\tFreeRDP version: %s", FREERDP_VERSION_FULL);
|
||||
WLog_INFO(TAG, "\tGit commit: %s", FREERDP_GIT_REVISION);
|
||||
@ -94,25 +85,12 @@ int main(int argc, char* argv[])
|
||||
if (argc >= 2)
|
||||
config_path = argv[1];
|
||||
|
||||
config = pf_server_config_load(config_path);
|
||||
config = pf_server_config_load_file(config_path);
|
||||
if (!config)
|
||||
goto fail;
|
||||
|
||||
pf_server_config_print(config);
|
||||
|
||||
if (!pf_modules_init(FREERDP_PROXY_PLUGINDIR, (const char**)config->Modules,
|
||||
config->ModulesCount))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to initialize proxy modules!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pf_modules_list_loaded_plugins();
|
||||
if (!is_all_required_modules_loaded(config))
|
||||
goto fail;
|
||||
|
||||
pf_server_register_signal_handlers();
|
||||
|
||||
server = pf_server_new(config);
|
||||
if (!server)
|
||||
goto fail;
|
||||
@ -120,13 +98,14 @@ int main(int argc, char* argv[])
|
||||
if (!pf_server_start(server))
|
||||
goto fail;
|
||||
|
||||
if (WaitForSingleObject(server->thread, INFINITE) != WAIT_OBJECT_0)
|
||||
if (!pf_server_run(server))
|
||||
goto fail;
|
||||
|
||||
status = 0;
|
||||
|
||||
fail:
|
||||
pf_server_free(server);
|
||||
pf_modules_free();
|
||||
pf_server_config_free(config);
|
||||
|
||||
return status;
|
||||
}
|
16
server/proxy/freerdp-proxy.pc.in
Normal file
16
server/proxy/freerdp-proxy.pc.in
Normal file
@ -0,0 +1,16 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=${prefix}/@FREERDP_INCLUDE_DIR@
|
||||
libs=-lfreerdp-server-proxy@FREERDP_API_VERSION@
|
||||
|
||||
Name: FreeRDP proxy
|
||||
Description: FreeRDP: A Remote Desktop Protocol Implementation
|
||||
URL: http://www.freerdp.com/
|
||||
Version: @FREERDP_VERSION@
|
||||
Requires:
|
||||
Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@ freerdp-server@FREERDP_VERSION_MAJOR@ freerdp-client@FREERDP_VERSION_MAJOR@
|
||||
|
||||
Libs: -L${libdir} ${libs}
|
||||
Libs.private: -ldl -lpthread
|
||||
Cflags: -I${includedir}
|
@ -1,27 +1,66 @@
|
||||
# Proxy filter API
|
||||
# Proxy module API
|
||||
|
||||
`freerdp-proxy` has an API for filtering certain messages. A filter can register callbacks to events, allowing to record the data and control whether to pass/ignore the message, or right out drop the connection.
|
||||
`freerdp-proxy` has an API for hooking/filtering certain events/messages.
|
||||
A module can register callbacks to events, allowing to record the data and control whether to pass/ignore, or right out drop the connection.
|
||||
|
||||
During startup, the proxy reads its modules from the configuration:
|
||||
|
||||
During startup, the proxy loads its filters from the configuration:
|
||||
```ini
|
||||
[Filters]
|
||||
; FilterName = FilterPath
|
||||
DemoFilter = "server/proxy/demo.so"
|
||||
[Plugins]
|
||||
Modules = demo,cap
|
||||
```
|
||||
|
||||
## Currently supported events
|
||||
* Mouse event
|
||||
* Keyboard event
|
||||
These modules are loaded in a best effort manner. Additionally there is a configuration field for modules that must be loaded,
|
||||
so the proxy refuses to start if they are not found:
|
||||
|
||||
## Developing a new filter
|
||||
* Create a new file that includes `filters_api.h`.
|
||||
* Implement the `filter_init` function and register the callbacks you are interested in.
|
||||
```ini
|
||||
[Plugins]
|
||||
Required = demo,cap
|
||||
```
|
||||
|
||||
Modules must be installed as shared libraris in the `<base install>/lib/freerdp3/proxy` folder and match the pattern
|
||||
`proxy-<name>-plugin.<ext>` (e.g. `proxy-demo-plugin.so`) to be found.
|
||||
For security reasons loading by full path is not supported and only the installation path is used for lookup.
|
||||
|
||||
## Currently supported hook events
|
||||
|
||||
### Client
|
||||
|
||||
* ClientInitConnect: Called before the client tries to open a connection
|
||||
* ClientUninitConnect: Called after the client has disconnected
|
||||
* ClientPreConnect: Called in client PreConnect callback
|
||||
* ClientPostConnect: Called in client PostConnect callback
|
||||
* ClientPostDisconnect: Called in client PostDisconnect callback
|
||||
* ClientX509Certificate: Called in client X509 certificate verification callback
|
||||
* ClientLoginFailure: Called in client login failure callback
|
||||
* ClientEndPaint: Called in client EndPaint callback
|
||||
|
||||
### Server
|
||||
|
||||
* ServerPostConnect: Called after a client has connected
|
||||
* ServerPeerActivate: Called after a client has activated
|
||||
* ServerChannelsInit: Called after channels are initialized
|
||||
* ServerChannelsFree: Called after channels are cleaned up
|
||||
* ServerSessionEnd: Called after the client connection disconnected
|
||||
|
||||
## Currently supported filter events
|
||||
|
||||
* KeyboardEvent: Keyboard event, e.g. all key press and release events
|
||||
* MouseEvent: Mouse event, e.g. mouse movement and button press/release events
|
||||
* ClientChannelData: Client static channel data
|
||||
* ServerChannelData: Server static channel data
|
||||
* DynamicChannelCreate: Dynamic channel create
|
||||
* ServerFetchTargetAddr: Fetch target address (e.g. RDP TargetInfo)
|
||||
* ServerPeerLogon: A peer is logging on
|
||||
|
||||
## Developing a new module
|
||||
* Create a new file that includes `freerdp/server/proxy/proxy_modules_api.h`.
|
||||
* Implement the `proxy_module_entry_point` function and register the callbacks you are interested in.
|
||||
* Each callback receives two parameters:
|
||||
* `connectionInfo* info` holds connection info of the raised event.
|
||||
* `void* param` holds the actual event data. It should be casted by the filter to the suitable struct from `filters_api.h`.
|
||||
* Each callback must return a `PF_FILTER_RESULT`:
|
||||
* `FILTER_IGNORE`: The event will not be proxied.
|
||||
* `FILTER_PASS`: The event will be proxied.
|
||||
* `FILTER_DROP`: The entire connection will be dropped.
|
||||
* Each callback must return a `BOOL`:
|
||||
* `FALSE`: The event will not be proxied.
|
||||
* `TRUE`: The event will be proxied.
|
||||
|
||||
A demo can be found in `filter_demo.c`.
|
||||
A demo can be found in `filter_demo.c`.
|
||||
|
@ -17,9 +17,11 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
set(PLUGIN_NAME "proxy-capture-plugin")
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
add_library(${PLUGIN_NAME} MODULE
|
||||
project(proxy-capture-plugin VERSION 1.0.0 LANGUAGES C)
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE
|
||||
cap_main.c
|
||||
cap_config.c
|
||||
cap_config.h
|
||||
@ -27,7 +29,9 @@ add_library(${PLUGIN_NAME} MODULE
|
||||
cap_protocol.h
|
||||
)
|
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1)
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}")
|
||||
target_link_libraries(${PROJECT_NAME} winpr)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES NO_SONAME 1)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION ${FREERDP_PROXY_PLUGINDIR})
|
||||
|
@ -75,7 +75,7 @@ BOOL capture_plugin_init_config(captureConfig* config)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
config->port = port;
|
||||
config->port = (UINT16)port;
|
||||
free(tmp);
|
||||
}
|
||||
else
|
||||
|
@ -17,40 +17,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define TAG MODULE_TAG("capture")
|
||||
|
||||
#define PLUGIN_NAME "capture"
|
||||
#define PLUGIN_DESC "stream egfx connections over tcp"
|
||||
|
||||
#include <errno.h>
|
||||
#include <winpr/image.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "modules_api.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_modules_api.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "cap_config.h"
|
||||
#include "cap_protocol.h"
|
||||
|
||||
#define TAG MODULE_TAG("capture")
|
||||
|
||||
#define PLUGIN_NAME "capture"
|
||||
#define PLUGIN_DESC "stream egfx connections over tcp"
|
||||
|
||||
#define BUFSIZE 8092
|
||||
|
||||
static proxyPluginsManager* g_plugins_manager = NULL;
|
||||
static captureConfig config = { 0 };
|
||||
|
||||
static SOCKET capture_plugin_init_socket(void)
|
||||
static SOCKET capture_plugin_init_socket(const captureConfig* cconfig)
|
||||
{
|
||||
int status;
|
||||
int sockfd;
|
||||
SOCKET sockfd;
|
||||
struct sockaddr_in addr = { 0 };
|
||||
|
||||
WINPR_ASSERT(cconfig);
|
||||
|
||||
sockfd = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (sockfd == -1)
|
||||
if (sockfd == (SOCKET)-1)
|
||||
return -1;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(config.port);
|
||||
inet_pton(AF_INET, config.host, &(addr.sin_addr));
|
||||
addr.sin_port = htons(cconfig->port);
|
||||
inet_pton(AF_INET, cconfig->host, &(addr.sin_addr));
|
||||
|
||||
status = _connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr));
|
||||
if (status < 0)
|
||||
@ -64,7 +65,6 @@ static SOCKET capture_plugin_init_socket(void)
|
||||
|
||||
static BOOL capture_plugin_send_data(SOCKET sockfd, const BYTE* buffer, size_t len)
|
||||
{
|
||||
size_t chunk_len;
|
||||
int nsent;
|
||||
|
||||
if (!buffer)
|
||||
@ -72,7 +72,7 @@ static BOOL capture_plugin_send_data(SOCKET sockfd, const BYTE* buffer, size_t l
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
chunk_len = len > BUFSIZE ? BUFSIZE : len;
|
||||
int chunk_len = len > BUFSIZE ? BUFSIZE : len;
|
||||
nsent = _send(sockfd, (const char*)buffer, chunk_len, 0);
|
||||
if (nsent == -1)
|
||||
return FALSE;
|
||||
@ -109,24 +109,32 @@ error:
|
||||
return result;
|
||||
}
|
||||
|
||||
static SOCKET capture_plugin_get_socket(proxyData* pdata)
|
||||
static SOCKET capture_plugin_get_socket(proxyPlugin* plugin, proxyData* pdata)
|
||||
{
|
||||
void* custom;
|
||||
|
||||
custom = g_plugins_manager->GetPluginData(PLUGIN_NAME, pdata);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(plugin->mgr);
|
||||
|
||||
custom = plugin->mgr->GetPluginData(plugin->mgr, PLUGIN_NAME, pdata);
|
||||
if (!custom)
|
||||
return -1;
|
||||
|
||||
return (SOCKET)custom;
|
||||
}
|
||||
|
||||
static BOOL capture_plugin_session_end(proxyData* pdata)
|
||||
static BOOL capture_plugin_session_end(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
SOCKET socket;
|
||||
BOOL ret;
|
||||
wStream* s;
|
||||
|
||||
socket = capture_plugin_get_socket(pdata);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(plugin->mgr);
|
||||
|
||||
socket = capture_plugin_get_socket(plugin, pdata);
|
||||
if (socket == INVALID_SOCKET)
|
||||
return FALSE;
|
||||
|
||||
@ -146,7 +154,11 @@ static BOOL capture_plugin_send_frame(pClientContext* pc, SOCKET socket, const B
|
||||
BOOL ret = FALSE;
|
||||
wStream* s = NULL;
|
||||
BYTE* bmp_header = NULL;
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
settings = pc->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
frame_size = settings->DesktopWidth * settings->DesktopHeight * (settings->ColorDepth / 8);
|
||||
bmp_header = winpr_bitmap_construct_header(settings->DesktopWidth, settings->DesktopHeight,
|
||||
@ -178,19 +190,24 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL capture_plugin_client_end_paint(proxyData* pdata)
|
||||
static BOOL capture_plugin_client_end_paint(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
pClientContext* pc = pdata->pc;
|
||||
rdpGdi* gdi = pc->context.gdi;
|
||||
SOCKET socket;
|
||||
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(plugin->mgr);
|
||||
|
||||
if (gdi->suppressOutput)
|
||||
return TRUE;
|
||||
|
||||
if (gdi->primary->hdc->hwnd->ninvalid < 1)
|
||||
return TRUE;
|
||||
|
||||
socket = capture_plugin_get_socket(pdata);
|
||||
socket = capture_plugin_get_socket(plugin, pdata);
|
||||
if (socket == INVALID_SOCKET)
|
||||
return FALSE;
|
||||
|
||||
@ -205,19 +222,28 @@ static BOOL capture_plugin_client_end_paint(proxyData* pdata)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL capture_plugin_client_post_connect(proxyData* pdata)
|
||||
static BOOL capture_plugin_client_post_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
captureConfig* cconfig;
|
||||
SOCKET socket;
|
||||
wStream* s;
|
||||
|
||||
socket = capture_plugin_init_socket();
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(plugin->mgr);
|
||||
|
||||
cconfig = plugin->custom;
|
||||
WINPR_ASSERT(cconfig);
|
||||
|
||||
socket = capture_plugin_init_socket(cconfig);
|
||||
if (socket == INVALID_SOCKET)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to establish a connection");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_plugins_manager->SetPluginData(PLUGIN_NAME, pdata, (void*)socket);
|
||||
plugin->mgr->SetPluginData(plugin->mgr, PLUGIN_NAME, pdata, (void*)socket);
|
||||
|
||||
s = capture_plugin_create_session_info_packet(pdata->pc);
|
||||
if (!s)
|
||||
@ -226,11 +252,24 @@ static BOOL capture_plugin_client_post_connect(proxyData* pdata)
|
||||
return capture_plugin_send_packet(socket, s);
|
||||
}
|
||||
|
||||
static BOOL capture_plugin_server_post_connect(proxyData* pdata)
|
||||
static BOOL capture_plugin_server_post_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
pServerContext* ps = pdata->ps;
|
||||
proxyConfig* config = pdata->config;
|
||||
rdpSettings* settings = ps->context.settings;
|
||||
pServerContext* ps;
|
||||
const proxyConfig* config;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
ps = pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
config = pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
settings = ps->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!config->GFX || !config->DecodeGFX)
|
||||
{
|
||||
@ -248,41 +287,51 @@ static BOOL capture_plugin_server_post_connect(proxyData* pdata)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL capture_plugin_unload(void)
|
||||
static BOOL capture_plugin_unload(proxyPlugin* plugin)
|
||||
{
|
||||
capture_plugin_config_free_internal(&config);
|
||||
if (plugin)
|
||||
{
|
||||
captureConfig* cconfig = plugin->custom;
|
||||
WINPR_ASSERT(cconfig);
|
||||
|
||||
capture_plugin_config_free_internal(cconfig);
|
||||
free(cconfig);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static proxyPlugin demo_plugin = {
|
||||
PLUGIN_NAME, /* name */
|
||||
PLUGIN_DESC, /* description */
|
||||
capture_plugin_unload, /* PluginUnload */
|
||||
NULL, /* ClientPreConnect */
|
||||
capture_plugin_client_post_connect, /* ClientPostConnect */
|
||||
NULL, /* ClientLoginFailure */
|
||||
capture_plugin_client_end_paint, /* ClientEndPaint */
|
||||
capture_plugin_server_post_connect, /* ServerPostConnect */
|
||||
NULL, /* ServerChannelsInit */
|
||||
NULL, /* ServerChannelsFree */
|
||||
capture_plugin_session_end, /* Session End */
|
||||
NULL, /* KeyboardEvent */
|
||||
NULL, /* MouseEvent */
|
||||
NULL, /* ClientChannelData */
|
||||
NULL, /* ServerChannelData */
|
||||
NULL /* ServerFetchTargetAddr */
|
||||
};
|
||||
|
||||
BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager)
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
g_plugins_manager = plugins_manager;
|
||||
#endif
|
||||
FREERDP_API BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager, void* userdata);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!capture_plugin_init_config(&config))
|
||||
BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager, void* userdata)
|
||||
{
|
||||
proxyPlugin plugin = { 0 };
|
||||
|
||||
plugin.name = PLUGIN_NAME; /* name */
|
||||
plugin.description = PLUGIN_DESC; /* description */
|
||||
plugin.PluginUnload = capture_plugin_unload; /* PluginUnload */
|
||||
plugin.ClientPostConnect = capture_plugin_client_post_connect; /* ClientPostConnect */
|
||||
plugin.ClientEndPaint = capture_plugin_client_end_paint; /* ClientEndPaint */
|
||||
plugin.ServerPostConnect = capture_plugin_server_post_connect; /* ServerPostConnect */
|
||||
plugin.ServerSessionEnd = capture_plugin_session_end; /* Session End */
|
||||
plugin.userdata = userdata; /* userdata */
|
||||
captureConfig* cconfig = calloc(1, sizeof(captureConfig));
|
||||
if (!cconfig)
|
||||
return FALSE;
|
||||
plugin.custom = cconfig;
|
||||
|
||||
if (!capture_plugin_init_config(cconfig))
|
||||
{
|
||||
WLog_ERR(TAG, "failed to load config");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "host: %s, port: %" PRIu16 "", config.host, config.port);
|
||||
return plugins_manager->RegisterPlugin(&demo_plugin);
|
||||
WLog_INFO(TAG, "host: %s, port: %" PRIu16 "", cconfig->host, cconfig->port);
|
||||
return plugins_manager->RegisterPlugin(plugins_manager, &plugin);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ wStream* capture_plugin_packet_new(UINT32 payload_size, UINT16 type)
|
||||
|
||||
wStream* capture_plugin_create_session_info_packet(pClientContext* pc)
|
||||
{
|
||||
UINT16 username_length;
|
||||
size_t username_length;
|
||||
wStream* s = NULL;
|
||||
rdpSettings* settings;
|
||||
|
||||
@ -46,7 +46,7 @@ wStream* capture_plugin_create_session_info_packet(pClientContext* pc)
|
||||
return NULL;
|
||||
|
||||
username_length = strlen(settings->Username);
|
||||
if (username_length == 0)
|
||||
if ((username_length == 0) || (username_length > UINT16_MAX))
|
||||
return NULL;
|
||||
|
||||
s = capture_plugin_packet_new(SESSION_INFO_PDU_BASE_SIZE + username_length,
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
/* protocol message sizes */
|
||||
#define HEADER_SIZE 6
|
||||
|
@ -17,14 +17,20 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
set(PLUGIN_NAME "proxy-demo-plugin")
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
add_library(${PLUGIN_NAME} MODULE
|
||||
project(proxy-demo-plugin VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE
|
||||
demo.cpp
|
||||
)
|
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_STANDARD 11)
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES NO_SONAME 1)
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${FREERDP_PROXY_PLUGINDIR}")
|
||||
target_link_libraries(${PROJECT_NAME} winpr)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES NO_SONAME 1)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION ${FREERDP_PROXY_PLUGINDIR})
|
||||
|
@ -19,59 +19,309 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "modules_api.h"
|
||||
#include <freerdp/server/proxy/proxy_modules_api.h>
|
||||
|
||||
#define TAG MODULE_TAG("demo")
|
||||
|
||||
static constexpr char plugin_name[] = "demo";
|
||||
static constexpr char plugin_desc[] = "this is a test plugin";
|
||||
|
||||
static proxyPluginsManager* g_plugins_manager = NULL;
|
||||
|
||||
static BOOL demo_filter_keyboard_event(proxyData* pdata, void* param)
|
||||
static BOOL demo_plugin_unload(proxyPlugin* plugin)
|
||||
{
|
||||
auto event_data = static_cast<proxyKeyboardEventInfo*>(param);
|
||||
if (event_data == NULL)
|
||||
WINPR_ASSERT(plugin);
|
||||
|
||||
std::cout << "C++ demo plugin: unloading..." << std::endl;
|
||||
|
||||
/* Here we have to free up our custom data storage. */
|
||||
if (plugin)
|
||||
free(plugin->custom);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_init_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_uninit_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_pre_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_post_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_post_disconnect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_x509_certificate(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_login_failure(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_client_end_paint(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_post_connect(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_peer_activate(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_channels_init(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_channels_free(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_session_end(proxyPlugin* plugin, proxyData* pdata, void* custom)
|
||||
{
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(custom);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_filter_keyboard_event(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
proxyPluginsManager* mgr;
|
||||
auto event_data = static_cast<const proxyKeyboardEventInfo*>(param);
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(event_data);
|
||||
|
||||
mgr = plugin->mgr;
|
||||
WINPR_ASSERT(mgr);
|
||||
|
||||
if (event_data == nullptr)
|
||||
return FALSE;
|
||||
|
||||
if (event_data->rdp_scan_code == RDP_SCANCODE_KEY_B)
|
||||
{
|
||||
/* user typed 'B', that means bye :) */
|
||||
std::cout << "C++ demo plugin: aborting connection" << std::endl;
|
||||
g_plugins_manager->AbortConnect(pdata);
|
||||
mgr->AbortConnect(mgr, pdata);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_plugin_unload()
|
||||
static BOOL demo_mouse_event(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
std::cout << "C++ demo plugin: unloading..." << std::endl;
|
||||
auto event_data = static_cast<const proxyMouseEventInfo*>(param);
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(event_data);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static proxyPlugin demo_plugin = {
|
||||
plugin_name, /* name */
|
||||
plugin_desc, /* description */
|
||||
demo_plugin_unload, /* PluginUnload */
|
||||
NULL, /* ClientPreConnect */
|
||||
NULL, /* ClientPostConnect */
|
||||
NULL, /* ClientLoginFailure */
|
||||
NULL, /* ClientEndPaint */
|
||||
NULL, /* ServerPostConnect */
|
||||
NULL, /* ServerChannelsInit */
|
||||
NULL, /* ServerChannelsFree */
|
||||
NULL, /* ServerSessionEnd */
|
||||
demo_filter_keyboard_event, /* KeyboardEvent */
|
||||
NULL, /* MouseEvent */
|
||||
NULL, /* ClientChannelData */
|
||||
NULL, /* ServerChannelData */
|
||||
NULL /* ServerFetchTargetAddr */
|
||||
};
|
||||
|
||||
BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager)
|
||||
static BOOL demo_client_channel_data(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
g_plugins_manager = plugins_manager;
|
||||
const proxyChannelDataEventInfo* channel = static_cast<const proxyChannelDataEventInfo*>(param);
|
||||
|
||||
return plugins_manager->RegisterPlugin(&demo_plugin);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(channel);
|
||||
|
||||
WLog_INFO(TAG, "%s: %s [0x%04" PRIx16 "] got %" PRIuz, __FUNCTION__, channel->channel_name,
|
||||
channel->channel_id, channel->data_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_channel_data(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
const proxyChannelDataEventInfo* channel = static_cast<const proxyChannelDataEventInfo*>(param);
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(channel);
|
||||
|
||||
WLog_WARN(TAG, "%s: %s [0x%04" PRIx16 "] got %" PRIuz, __FUNCTION__, channel->channel_name,
|
||||
channel->channel_id, channel->data_len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_dynamic_channel_create(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
const proxyChannelDataEventInfo* channel = static_cast<const proxyChannelDataEventInfo*>(param);
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(channel);
|
||||
|
||||
WLog_WARN(TAG, "%s: %s [0x%04" PRIx16 "]", __FUNCTION__, channel->channel_name,
|
||||
channel->channel_id);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_fetch_target_addr(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
auto event_data = static_cast<const proxyFetchTargetEventInfo*>(param);
|
||||
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(event_data);
|
||||
|
||||
WLog_INFO(TAG, "%s", __FUNCTION__);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL demo_server_peer_logon(proxyPlugin* plugin, proxyData* pdata, void* param)
|
||||
{
|
||||
auto info = static_cast<const proxyServerPeerLogon*>(param);
|
||||
WINPR_ASSERT(plugin);
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(info);
|
||||
WINPR_ASSERT(info->identity);
|
||||
|
||||
WLog_INFO(TAG, "%s: %d", __FUNCTION__, info->automatic);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
FREERDP_API BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager, void* userdata);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager, void* userdata)
|
||||
{
|
||||
struct demo_custom_data
|
||||
{
|
||||
proxyPluginsManager* mgr;
|
||||
int somesetting;
|
||||
};
|
||||
struct demo_custom_data* custom;
|
||||
proxyPlugin plugin;
|
||||
|
||||
plugin.name = plugin_name;
|
||||
plugin.description = plugin_desc;
|
||||
plugin.PluginUnload = demo_plugin_unload;
|
||||
plugin.ClientInitConnect = demo_client_init_connect;
|
||||
plugin.ClientUninitConnect = demo_client_uninit_connect;
|
||||
plugin.ClientPreConnect = demo_client_pre_connect;
|
||||
plugin.ClientPostConnect = demo_client_post_connect;
|
||||
plugin.ClientPostDisconnect = demo_client_post_disconnect;
|
||||
plugin.ClientX509Certificate = demo_client_x509_certificate;
|
||||
plugin.ClientLoginFailure = demo_client_login_failure;
|
||||
plugin.ClientEndPaint = demo_client_end_paint;
|
||||
plugin.ServerPostConnect = demo_server_post_connect;
|
||||
plugin.ServerPeerActivate = demo_server_peer_activate;
|
||||
plugin.ServerChannelsInit = demo_server_channels_init;
|
||||
plugin.ServerChannelsFree = demo_server_channels_free;
|
||||
plugin.ServerSessionEnd = demo_server_session_end;
|
||||
plugin.KeyboardEvent = demo_filter_keyboard_event;
|
||||
plugin.MouseEvent = demo_mouse_event;
|
||||
plugin.ClientChannelData = demo_client_channel_data;
|
||||
plugin.ServerChannelData = demo_server_channel_data;
|
||||
plugin.DynamicChannelCreate = demo_dynamic_channel_create;
|
||||
plugin.ServerFetchTargetAddr = demo_server_fetch_target_addr;
|
||||
plugin.ServerPeerLogon = demo_server_peer_logon;
|
||||
plugin.userdata = userdata;
|
||||
|
||||
custom = (struct demo_custom_data*)calloc(1, sizeof(struct demo_custom_data));
|
||||
if (!custom)
|
||||
return FALSE;
|
||||
|
||||
custom->mgr = plugins_manager;
|
||||
custom->somesetting = 42;
|
||||
|
||||
plugin.custom = custom;
|
||||
plugin.userdata = userdata;
|
||||
|
||||
return plugins_manager->RegisterPlugin(plugins_manager, &plugin);
|
||||
}
|
||||
|
@ -1,150 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
|
||||
*
|
||||
* 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_MODULES_API_H
|
||||
#define FREERDP_SERVER_PROXY_MODULES_API_H
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
#include "../pf_context.h"
|
||||
|
||||
#define MODULE_TAG(module) "proxy.modules." module
|
||||
|
||||
/* hook callback. should return TRUE on success or FALSE on error. */
|
||||
typedef BOOL (*proxyHookFn)(proxyData*);
|
||||
|
||||
/*
|
||||
* Filter callback:
|
||||
* It MUST return TRUE if the related event should be proxied,
|
||||
* or FALSE if it should be ignored.
|
||||
*/
|
||||
typedef BOOL (*proxyFilterFn)(proxyData*, void*);
|
||||
|
||||
/* describes a plugin: name, description and callbacks to execute. */
|
||||
typedef struct proxy_plugin
|
||||
{
|
||||
const char* name; /* unique module name */
|
||||
const char* description; /* module description */
|
||||
|
||||
BOOL (*PluginUnload)(void);
|
||||
|
||||
/* proxy hooks. a module can set these function pointers to register hooks */
|
||||
proxyHookFn ClientPreConnect;
|
||||
proxyHookFn ClientPostConnect;
|
||||
proxyHookFn ClientLoginFailure;
|
||||
proxyHookFn ClientEndPaint;
|
||||
proxyHookFn ServerPostConnect;
|
||||
proxyHookFn ServerChannelsInit;
|
||||
proxyHookFn ServerChannelsFree;
|
||||
proxyHookFn ServerSessionEnd;
|
||||
|
||||
/* proxy filters. a module can set these function pointers to register filters */
|
||||
proxyFilterFn KeyboardEvent;
|
||||
proxyFilterFn MouseEvent;
|
||||
proxyFilterFn ClientChannelData; /* passthrough channels data */
|
||||
proxyFilterFn ServerChannelData; /* passthrough channels data */
|
||||
proxyFilterFn ServerFetchTargetAddr;
|
||||
} proxyPlugin;
|
||||
|
||||
/*
|
||||
* Main API for use by external modules.
|
||||
* Supports:
|
||||
* - Registering a plugin.
|
||||
* - Setting/getting plugin's per-session specific data.
|
||||
* - Aborting a session.
|
||||
*/
|
||||
typedef struct proxy_plugins_manager
|
||||
{
|
||||
/* used for registering a fresh new proxy plugin. */
|
||||
BOOL (*RegisterPlugin)(proxyPlugin* plugin);
|
||||
|
||||
/* used for setting plugin's per-session info. */
|
||||
BOOL (*SetPluginData)(const char*, proxyData*, void*);
|
||||
|
||||
/* used for getting plugin's per-session info. */
|
||||
void* (*GetPluginData)(const char*, proxyData*);
|
||||
|
||||
/* used for aborting a session. */
|
||||
void (*AbortConnect)(proxyData*);
|
||||
} proxyPluginsManager;
|
||||
|
||||
/* filter events parameters */
|
||||
#define WINPR_PACK_PUSH
|
||||
#include <winpr/pack.h>
|
||||
typedef struct proxy_keyboard_event_info
|
||||
{
|
||||
UINT16 flags;
|
||||
UINT16 rdp_scan_code;
|
||||
} proxyKeyboardEventInfo;
|
||||
|
||||
typedef struct proxy_mouse_event_info
|
||||
{
|
||||
UINT16 flags;
|
||||
UINT16 x;
|
||||
UINT16 y;
|
||||
} proxyMouseEventInfo;
|
||||
|
||||
typedef struct channel_data_event_info
|
||||
{
|
||||
/* channel metadata */
|
||||
const char* channel_name;
|
||||
UINT16 channel_id;
|
||||
|
||||
/* actual data */
|
||||
const BYTE* data;
|
||||
size_t data_len;
|
||||
} proxyChannelDataEventInfo;
|
||||
|
||||
typedef enum proxy_fetch_target_method
|
||||
{
|
||||
PROXY_FETCH_TARGET_METHOD_DEFAULT,
|
||||
PROXY_FETCH_TARGET_METHOD_CONFIG,
|
||||
PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO,
|
||||
PROXY_FETCH_TARGET_USE_CUSTOM_ADDR
|
||||
} ProxyFetchTargetMethod;
|
||||
|
||||
typedef struct fetch_target_event_info
|
||||
{
|
||||
/* out values */
|
||||
char* target_address;
|
||||
UINT16 target_port;
|
||||
|
||||
/*
|
||||
* If this value is set to true by a plugin, target info will be fetched from config and proxy
|
||||
* will connect any client to the same remote server.
|
||||
*/
|
||||
ProxyFetchTargetMethod fetch_method;
|
||||
} proxyFetchTargetEventInfo;
|
||||
#define WINPR_PACK_POP
|
||||
#include <winpr/pack.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
FREERDP_API BOOL proxy_module_entry_point(proxyPluginsManager* plugins_manager);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_MODULES_API_H */
|
@ -23,6 +23,8 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/gdi/gfx.h>
|
||||
|
||||
#include <freerdp/client/rdpei.h>
|
||||
@ -31,21 +33,26 @@
|
||||
#include <freerdp/client/rdpgfx.h>
|
||||
#include <freerdp/client/disp.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_channels.h"
|
||||
#include "pf_client.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "pf_rail.h"
|
||||
#include "pf_rdpgfx.h"
|
||||
#include "pf_cliprdr.h"
|
||||
#include "pf_disp.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_modules.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!");
|
||||
@ -54,8 +61,17 @@ static void pf_channels_wait_for_server_dynvc(pServerContext* ps)
|
||||
void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs* e)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)data;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
LOG_INFO(TAG, pc, "Channel connected: %s", e->name);
|
||||
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)
|
||||
{
|
||||
@ -141,9 +157,19 @@ void pf_channels_on_client_channel_connect(void* data, ChannelConnectedEventArgs
|
||||
void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEventArgs* e)
|
||||
{
|
||||
rdpContext* context = (rdpContext*)data;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
LOG_INFO(TAG, pc, "Channel disconnected: %s", e->name);
|
||||
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)
|
||||
{
|
||||
@ -151,6 +177,9 @@ void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEve
|
||||
}
|
||||
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");
|
||||
|
||||
@ -159,6 +188,9 @@ void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEve
|
||||
}
|
||||
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");
|
||||
|
||||
@ -166,6 +198,9 @@ void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEve
|
||||
}
|
||||
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");
|
||||
|
||||
@ -173,6 +208,9 @@ void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEve
|
||||
}
|
||||
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");
|
||||
|
||||
@ -184,16 +222,28 @@ void pf_channels_on_client_channel_disconnect(void* data, ChannelDisconnectedEve
|
||||
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)
|
||||
BOOL pf_server_channels_init(pServerContext* ps, freerdp_peer* peer)
|
||||
{
|
||||
rdpContext* context = (rdpContext*)ps;
|
||||
rdpContext* client = (rdpContext*)ps->pdata->pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
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)
|
||||
{
|
||||
@ -230,38 +280,15 @@ BOOL pf_server_channels_init(pServerContext* ps)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
{
|
||||
/* open static channels for passthrough */
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
{
|
||||
char* channel_name = config->Passthrough[i];
|
||||
UINT64 channel_id;
|
||||
|
||||
/* only open channel if client joined with it */
|
||||
if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name))
|
||||
continue;
|
||||
|
||||
ps->vc_handles[i] = WTSVirtualChannelOpen(ps->vcm, WTS_CURRENT_SESSION, channel_name);
|
||||
if (!ps->vc_handles[i])
|
||||
{
|
||||
LOG_ERR(TAG, ps, "WTSVirtualChannelOpen failed for passthrough channel: %s",
|
||||
channel_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
channel_id = (UINT64)WTSChannelGetId(ps->context.peer, channel_name);
|
||||
HashTable_Insert(ps->vc_ids, channel_name, (void*)channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
return pf_modules_run_hook(HOOK_TYPE_SERVER_CHANNELS_INIT, ps->pdata);
|
||||
return pf_modules_run_hook(ps->pdata->module, HOOK_TYPE_SERVER_CHANNELS_INIT, ps->pdata, peer);
|
||||
}
|
||||
|
||||
void pf_server_channels_free(pServerContext* ps)
|
||||
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);
|
||||
@ -292,13 +319,5 @@ void pf_server_channels_free(pServerContext* ps)
|
||||
ps->rail = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
/* close passthrough channels */
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ps->pdata->config->PassthroughCount; i++)
|
||||
WTSVirtualChannelClose(ps->vc_handles[i]);
|
||||
}
|
||||
|
||||
pf_modules_run_hook(HOOK_TYPE_SERVER_CHANNELS_FREE, ps->pdata);
|
||||
pf_modules_run_hook(ps->pdata->module, HOOK_TYPE_SERVER_CHANNELS_FREE, ps->pdata, peer);
|
||||
}
|
||||
|
@ -25,12 +25,12 @@
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
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);
|
||||
void pf_server_channels_free(pServerContext* ps);
|
||||
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 */
|
||||
|
@ -27,22 +27,29 @@
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
#include <freerdp/channels/drdynvc.h>
|
||||
#include <freerdp/channels/encomsp.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include "pf_channels.h"
|
||||
#include "pf_gdi.h"
|
||||
#include "pf_graphics.h"
|
||||
#include "pf_client.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "pf_update.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_modules.h"
|
||||
#include "pf_input.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include "proxy_modules.h"
|
||||
#include "pf_utils.h"
|
||||
|
||||
#define TAG PROXY_TAG("client")
|
||||
|
||||
static pReceiveChannelData client_receive_channel_data_original = NULL;
|
||||
|
||||
static BOOL proxy_server_reactivate(rdpContext* ps, const rdpContext* pc)
|
||||
{
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
if (!pf_context_copy_settings(ps->settings, pc->settings))
|
||||
return FALSE;
|
||||
|
||||
@ -50,6 +57,7 @@ static BOOL proxy_server_reactivate(rdpContext* ps, const rdpContext* pc)
|
||||
* DesktopResize causes internal function rdp_server_reactivate to be called,
|
||||
* which causes the reactivation.
|
||||
*/
|
||||
WINPR_ASSERT(ps->update);
|
||||
if (!ps->update->DesktopResize(ps))
|
||||
return FALSE;
|
||||
|
||||
@ -59,13 +67,19 @@ static BOOL proxy_server_reactivate(rdpContext* ps, const rdpContext* pc)
|
||||
static void pf_client_on_error_info(void* ctx, ErrorInfoEventArgs* e)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)ctx;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
pServerContext* ps;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
WINPR_ASSERT(e);
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
if (e->code == ERRINFO_NONE)
|
||||
return;
|
||||
|
||||
LOG_WARN(TAG, pc, "received ErrorInfo PDU. code=0x%08" PRIu32 ", message: %s", e->code,
|
||||
freerdp_get_error_info_string(e->code));
|
||||
PROXY_LOG_WARN(TAG, pc, "received ErrorInfo PDU. code=0x%08" PRIu32 ", message: %s", e->code,
|
||||
freerdp_get_error_info_string(e->code));
|
||||
|
||||
/* forward error back to client */
|
||||
freerdp_set_error_info(ps->context.rdp, e->code);
|
||||
@ -75,10 +89,19 @@ static void pf_client_on_error_info(void* ctx, ErrorInfoEventArgs* e)
|
||||
static void pf_client_on_activated(void* ctx, ActivatedEventArgs* e)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)ctx;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
freerdp_peer* peer = ps->context.peer;
|
||||
pServerContext* ps;
|
||||
freerdp_peer* peer;
|
||||
|
||||
LOG_INFO(TAG, pc, "client activated, registering server input callbacks");
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
WINPR_ASSERT(e);
|
||||
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
peer = ps->context.peer;
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
PROXY_LOG_INFO(TAG, pc, "client activated, registering server input callbacks");
|
||||
|
||||
/* Register server input/update callbacks only after proxy client is fully activated */
|
||||
pf_server_register_input_callbacks(peer->context->input);
|
||||
@ -88,8 +111,15 @@ static void pf_client_on_activated(void* ctx, ActivatedEventArgs* e)
|
||||
static BOOL pf_client_load_rdpsnd(pClientContext* pc)
|
||||
{
|
||||
rdpContext* context = (rdpContext*)pc;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
proxyConfig* config = pc->pdata->config;
|
||||
pServerContext* ps;
|
||||
const proxyConfig* config;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
config = pc->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
/*
|
||||
* if AudioOutput is enabled in proxy and client connected with rdpsnd, use proxy as rdpsnd
|
||||
@ -113,48 +143,21 @@ static BOOL pf_client_load_rdpsnd(pClientContext* pc)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_client_passthrough_channels_init(pClientContext* pc)
|
||||
{
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
proxyConfig* config = pc->pdata->config;
|
||||
size_t i;
|
||||
|
||||
if (settings->ChannelCount + config->PassthroughCount >= settings->ChannelDefArraySize)
|
||||
{
|
||||
LOG_ERR(TAG, pc, "too many channels");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
{
|
||||
const char* channel_name = config->Passthrough[i];
|
||||
CHANNEL_DEF channel = { 0 };
|
||||
|
||||
/* only connect connect this channel if already joined in peer connection */
|
||||
if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name))
|
||||
{
|
||||
LOG_INFO(TAG, ps, "client did not connected with channel %s, skipping passthrough",
|
||||
channel_name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
channel.options = CHANNEL_OPTION_INITIALIZED; /* TODO: Export to config. */
|
||||
strncpy(channel.name, channel_name, CHANNEL_NAME_LEN);
|
||||
|
||||
settings->ChannelDefArray[settings->ChannelCount++] = channel;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_client_use_peer_load_balance_info(pClientContext* pc)
|
||||
{
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
pServerContext* ps;
|
||||
rdpSettings* settings;
|
||||
DWORD lb_info_len;
|
||||
const char* lb_info = freerdp_nego_get_routing_token(&ps->context, &lb_info_len);
|
||||
const char* lb_info;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
settings = pc->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
lb_info = freerdp_nego_get_routing_token(&ps->context, &lb_info_len);
|
||||
if (!lb_info)
|
||||
return TRUE;
|
||||
|
||||
@ -172,10 +175,22 @@ static BOOL pf_client_use_peer_load_balance_info(pClientContext* pc)
|
||||
|
||||
static BOOL pf_client_pre_connect(freerdp* instance)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)instance->context;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
rdpSettings* settings = instance->settings;
|
||||
pClientContext* pc;
|
||||
pServerContext* ps;
|
||||
const proxyConfig* config;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
config = ps->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
settings = instance->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
/*
|
||||
* as the client's settings are copied from the server's, GlyphSupportLevel might not be
|
||||
@ -187,19 +202,27 @@ static BOOL pf_client_pre_connect(freerdp* instance)
|
||||
settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE;
|
||||
ZeroMemory(settings->OrderSupport, 32);
|
||||
|
||||
settings->SupportDynamicChannels = TRUE;
|
||||
if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, DRDYNVC_SVC_CHANNEL_NAME))
|
||||
settings->SupportDynamicChannels = TRUE;
|
||||
|
||||
/* Multimon */
|
||||
settings->UseMultimon = TRUE;
|
||||
|
||||
/* Sound */
|
||||
settings->AudioPlayback = FALSE;
|
||||
settings->DeviceRedirection = TRUE;
|
||||
settings->AudioPlayback = config->AudioOutput;
|
||||
if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, "rdpdr"))
|
||||
settings->DeviceRedirection = TRUE;
|
||||
|
||||
/* Display control */
|
||||
settings->SupportDisplayControl = config->DisplayControl;
|
||||
settings->DynamicResolutionUpdate = config->DisplayControl;
|
||||
|
||||
if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, ENCOMSP_SVC_CHANNEL_NAME))
|
||||
settings->EncomspVirtualChannel = TRUE;
|
||||
|
||||
if (WTSVirtualChannelManagerIsChannelJoined(ps->vcm, CLIPRDR_SVC_CHANNEL_NAME))
|
||||
settings->RedirectClipboard = config->Clipboard;
|
||||
|
||||
settings->AutoReconnectionEnabled = TRUE;
|
||||
|
||||
/**
|
||||
@ -216,73 +239,211 @@ static BOOL pf_client_pre_connect(freerdp* instance)
|
||||
* Load all required plugins / channels / libraries specified by current
|
||||
* settings.
|
||||
*/
|
||||
LOG_INFO(TAG, pc, "Loading addins");
|
||||
PROXY_LOG_INFO(TAG, pc, "Loading addins");
|
||||
|
||||
if (!pf_client_use_peer_load_balance_info(pc))
|
||||
return FALSE;
|
||||
|
||||
if (!pf_client_passthrough_channels_init(pc))
|
||||
return FALSE;
|
||||
|
||||
if (!pf_client_load_rdpsnd(pc))
|
||||
{
|
||||
LOG_ERR(TAG, pc, "Failed to load rdpsnd client");
|
||||
PROXY_LOG_ERR(TAG, pc, "Failed to load rdpsnd client");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
|
||||
{
|
||||
LOG_ERR(TAG, pc, "Failed to load addins");
|
||||
PROXY_LOG_ERR(TAG, pc, "Failed to load addins");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_PRE_CONNECT, pc->pdata, pc);
|
||||
}
|
||||
|
||||
static BOOL pf_client_receive_channel_data_hook(freerdp* instance, UINT16 channelId,
|
||||
const BYTE* data, size_t size, UINT32 flags,
|
||||
size_t totalSize)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)instance->context;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
proxyData* pdata = ps->pdata;
|
||||
proxyConfig* config = pdata->config;
|
||||
size_t i;
|
||||
|
||||
const char* channel_name = freerdp_channels_get_name_by_id(instance, channelId);
|
||||
pClientContext* pc;
|
||||
pServerContext* ps;
|
||||
proxyData* pdata;
|
||||
const proxyConfig* config;
|
||||
int pass;
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(data || (size == 0));
|
||||
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
config = pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
pass = pf_utils_channel_is_passthrough(config, channel_name);
|
||||
|
||||
switch (pass)
|
||||
{
|
||||
if (strncmp(channel_name, config->Passthrough[i], CHANNEL_NAME_LEN) == 0)
|
||||
case 0:
|
||||
return TRUE; /* Silently drop */
|
||||
case 1:
|
||||
{
|
||||
proxyChannelDataEventInfo ev;
|
||||
UINT64 server_channel_id;
|
||||
UINT16 server_channel_id;
|
||||
|
||||
ev.channel_id = channelId;
|
||||
ev.channel_name = channel_name;
|
||||
ev.data = data;
|
||||
ev.data_len = size;
|
||||
ev.flags = flags;
|
||||
ev.total_size = totalSize;
|
||||
|
||||
if (!pf_modules_run_filter(FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA, pdata, &ev))
|
||||
return FALSE;
|
||||
if (!pf_modules_run_filter(pdata->module, FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA,
|
||||
pdata, &ev))
|
||||
return TRUE; /* Silently drop */
|
||||
|
||||
server_channel_id =
|
||||
(UINT64)HashTable_GetItemValue(ps->vc_ids, (const void*)channel_name);
|
||||
return ps->context.peer->SendChannelData(ps->context.peer, (UINT16)server_channel_id,
|
||||
data, size);
|
||||
/* Dynamic channels need special treatment
|
||||
*
|
||||
* We need to check every message with CHANNEL_FLAG_FIRST set if it
|
||||
* is a CREATE_REQUEST_PDU (0x01) and extract channelId and name
|
||||
* from it.
|
||||
*
|
||||
* To avoid issues with (misbehaving) clients assume all packets
|
||||
* that do not have at least a length of 1 byte and all incomplete
|
||||
* CREATE_REQUEST_PDU (0x01) packets as invalid.
|
||||
*/
|
||||
if ((flags & CHANNEL_FLAG_FIRST) &&
|
||||
(strncmp(channel_name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
|
||||
{
|
||||
BYTE cmd;
|
||||
if (size < 1)
|
||||
return FALSE;
|
||||
|
||||
cmd = data[0] >> 4;
|
||||
if (cmd == 0x01)
|
||||
{
|
||||
proxyChannelDataEventInfo dev;
|
||||
size_t len, nameLen;
|
||||
const char* name;
|
||||
UINT32 dynChannelId;
|
||||
BYTE cbId = data[0] & 0x03;
|
||||
switch (cbId)
|
||||
{
|
||||
case 0x00:
|
||||
if (size < 2)
|
||||
return FALSE;
|
||||
dynChannelId = data[1];
|
||||
name = (const char*)&data[2];
|
||||
nameLen = size - 2;
|
||||
break;
|
||||
case 0x01:
|
||||
if (size < 3)
|
||||
return FALSE;
|
||||
dynChannelId = data[2] << 8 | data[1];
|
||||
name = (const char*)&data[3];
|
||||
nameLen = size - 3;
|
||||
break;
|
||||
case 0x02:
|
||||
if (size < 5)
|
||||
return FALSE;
|
||||
dynChannelId = data[4] << 24 | data[3] << 16 | data[2] << 8 | data[1];
|
||||
name = (const char*)&data[5];
|
||||
nameLen = size - 5;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
len = strnlen(name, nameLen);
|
||||
if ((len == 0) || (len == nameLen))
|
||||
return FALSE;
|
||||
dev.channel_id = dynChannelId;
|
||||
dev.channel_name = name;
|
||||
dev.data = data;
|
||||
dev.data_len = size;
|
||||
dev.flags = flags;
|
||||
dev.total_size = totalSize;
|
||||
|
||||
if (!pf_modules_run_filter(pdata->module,
|
||||
FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE,
|
||||
pdata, &dev))
|
||||
return TRUE; /* Silently drop */
|
||||
}
|
||||
}
|
||||
server_channel_id = WTSChannelGetId(ps->context.peer, channel_name);
|
||||
|
||||
/* Ignore messages for channels that can not be mapped.
|
||||
* The client might not have enabled support for this specific channel,
|
||||
* so just drop the message. */
|
||||
if (server_channel_id == 0)
|
||||
return TRUE;
|
||||
return ps->context.peer->SendChannelPacket(ps->context.peer, server_channel_id,
|
||||
totalSize, flags, data, size);
|
||||
}
|
||||
default:
|
||||
WINPR_ASSERT(pc->client_receive_channel_data_original);
|
||||
return pc->client_receive_channel_data_original(instance, channelId, data, size, flags,
|
||||
totalSize);
|
||||
}
|
||||
|
||||
return client_receive_channel_data_original(instance, channelId, data, size, flags, totalSize);
|
||||
}
|
||||
|
||||
static BOOL pf_client_on_server_heartbeat(freerdp* instance, BYTE period, BYTE count1, BYTE count2)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)instance->context;
|
||||
pServerContext* ps = pc->pdata->ps;
|
||||
pClientContext* pc;
|
||||
pServerContext* ps;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
ps = pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
return freerdp_heartbeat_send_heartbeat_pdu(ps->context.peer, period, count1, count2);
|
||||
}
|
||||
|
||||
static BOOL pf_client_send_channel_data(pClientContext* pc, const proxyChannelDataEventInfo* ev)
|
||||
{
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(ev);
|
||||
|
||||
if (!pc->connected)
|
||||
{
|
||||
ArrayList_Append(pc->cached_server_channel_data, ev);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT16 channelId;
|
||||
WINPR_ASSERT(pc->context.instance);
|
||||
|
||||
channelId = freerdp_channels_get_id_by_name(pc->context.instance, ev->channel_name);
|
||||
/* Ignore unmappable channels */
|
||||
if ((channelId == 0) || (channelId == UINT16_MAX))
|
||||
return TRUE;
|
||||
WINPR_ASSERT(pc->context.instance->SendChannelPacket);
|
||||
return pc->context.instance->SendChannelPacket(
|
||||
pc->context.instance, channelId, ev->total_size, ev->flags, ev->data, ev->data_len);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL send_channel_data(void* data, size_t index, va_list ap)
|
||||
{
|
||||
pClientContext* pc = va_arg(ap, pClientContext*);
|
||||
proxyChannelDataEventInfo* ev = data;
|
||||
WINPR_ASSERT(ev);
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_UNUSED(index);
|
||||
|
||||
return pf_client_send_channel_data(pc, ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after a RDP connection was successfully established.
|
||||
* Settings might have changed during negotiation of client / server feature
|
||||
@ -299,16 +460,24 @@ static BOOL pf_client_post_connect(freerdp* instance)
|
||||
rdpUpdate* update;
|
||||
rdpContext* ps;
|
||||
pClientContext* pc;
|
||||
proxyConfig* config;
|
||||
const proxyConfig* config;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
context = instance->context;
|
||||
WINPR_ASSERT(context);
|
||||
settings = instance->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
update = instance->update;
|
||||
WINPR_ASSERT(update);
|
||||
pc = (pClientContext*)context;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
ps = (rdpContext*)pc->pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
config = pc->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!pf_modules_run_hook(HOOK_TYPE_CLIENT_POST_CONNECT, pc->pdata))
|
||||
if (!pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_POST_CONNECT, pc->pdata, pc))
|
||||
return FALSE;
|
||||
|
||||
if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
|
||||
@ -321,7 +490,7 @@ static BOOL pf_client_post_connect(freerdp* instance)
|
||||
{
|
||||
if (!pf_register_graphics(context->graphics))
|
||||
{
|
||||
LOG_ERR(TAG, pc, "failed to register graphics");
|
||||
PROXY_LOG_ERR(TAG, pc, "failed to register graphics");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -336,22 +505,19 @@ static BOOL pf_client_post_connect(freerdp* instance)
|
||||
pf_client_register_update_callbacks(update);
|
||||
|
||||
/* virtual channels receive data hook */
|
||||
client_receive_channel_data_original = instance->ReceiveChannelData;
|
||||
pc->client_receive_channel_data_original = instance->ReceiveChannelData;
|
||||
instance->ReceiveChannelData = pf_client_receive_channel_data_hook;
|
||||
|
||||
/* populate channel name -> channel ids map */
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
{
|
||||
char* channel_name = config->Passthrough[i];
|
||||
UINT64 channel_id = (UINT64)freerdp_channels_get_id_by_name(instance, channel_name);
|
||||
HashTable_Insert(pc->vc_ids, (void*)channel_name, (void*)channel_id);
|
||||
}
|
||||
}
|
||||
|
||||
instance->heartbeat->ServerHeartbeat = pf_client_on_server_heartbeat;
|
||||
|
||||
pc->connected = TRUE;
|
||||
|
||||
/* Send cached channel data */
|
||||
ArrayList_Lock(pc->cached_server_channel_data);
|
||||
ArrayList_ForEach(pc->cached_server_channel_data, send_channel_data, pc);
|
||||
ArrayList_Clear(pc->cached_server_channel_data);
|
||||
ArrayList_Unlock(pc->cached_server_channel_data);
|
||||
|
||||
/*
|
||||
* after the connection fully established and settings were negotiated with target server,
|
||||
* send a reactivation sequence to the client with the negotiated settings. This way,
|
||||
@ -365,7 +531,7 @@ static BOOL pf_client_post_connect(freerdp* instance)
|
||||
*/
|
||||
static void pf_client_post_disconnect(freerdp* instance)
|
||||
{
|
||||
pClientContext* context;
|
||||
pClientContext* pc;
|
||||
proxyData* pdata;
|
||||
|
||||
if (!instance)
|
||||
@ -374,8 +540,13 @@ static void pf_client_post_disconnect(freerdp* instance)
|
||||
if (!instance->context)
|
||||
return;
|
||||
|
||||
context = (pClientContext*)instance->context;
|
||||
pdata = context->pdata;
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
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);
|
||||
@ -385,7 +556,7 @@ static void pf_client_post_disconnect(freerdp* instance)
|
||||
gdi_free(instance);
|
||||
|
||||
/* Only close the connection if NLA fallback process is done */
|
||||
if (!context->allow_next_conn_failure)
|
||||
if (!pc->allow_next_conn_failure)
|
||||
proxy_data_abort_connect(pdata);
|
||||
}
|
||||
|
||||
@ -397,8 +568,15 @@ static void pf_client_post_disconnect(freerdp* instance)
|
||||
*/
|
||||
static BOOL pf_client_should_retry_without_nla(pClientContext* pc)
|
||||
{
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
proxyConfig* config = pc->pdata->config;
|
||||
rdpSettings* settings;
|
||||
const proxyConfig* config;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
settings = pc->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
config = pc->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!config->ClientAllowFallbackToTls || !settings->NlaSecurity)
|
||||
return FALSE;
|
||||
@ -408,26 +586,41 @@ static BOOL pf_client_should_retry_without_nla(pClientContext* pc)
|
||||
|
||||
static void pf_client_set_security_settings(pClientContext* pc)
|
||||
{
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
proxyConfig* config = pc->pdata->config;
|
||||
rdpSettings* settings;
|
||||
const proxyConfig* config;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->pdata);
|
||||
settings = pc->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
config = pc->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
settings->RdpSecurity = config->ClientRdpSecurity;
|
||||
settings->TlsSecurity = config->ClientTlsSecurity;
|
||||
settings->NlaSecurity = FALSE;
|
||||
settings->NlaSecurity = config->ClientNlaSecurity;
|
||||
|
||||
if (!config->ClientNlaSecurity)
|
||||
return;
|
||||
|
||||
if (!settings->Username || !settings->Password)
|
||||
return;
|
||||
|
||||
settings->NlaSecurity = TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_client_connect_without_nla(pClientContext* pc)
|
||||
{
|
||||
freerdp* instance = pc->context.instance;
|
||||
rdpSettings* settings = pc->context.settings;
|
||||
freerdp* instance;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(pc);
|
||||
instance = pc->context.instance;
|
||||
WINPR_ASSERT(instance);
|
||||
settings = pc->context.settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
/* If already disabled abort early. */
|
||||
if (!settings->NlaSecurity)
|
||||
return FALSE;
|
||||
|
||||
/* disable NLA */
|
||||
settings->NlaSecurity = FALSE;
|
||||
@ -439,32 +632,38 @@ static BOOL pf_client_connect_without_nla(pClientContext* pc)
|
||||
|
||||
static BOOL pf_client_connect(freerdp* instance)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)instance->context;
|
||||
rdpSettings* settings = instance->settings;
|
||||
pClientContext* pc;
|
||||
rdpSettings* settings;
|
||||
BOOL rc = FALSE;
|
||||
BOOL retry = FALSE;
|
||||
|
||||
LOG_INFO(TAG, pc, "connecting using client info: Username: %s, Domain: %s", settings->Username,
|
||||
settings->Domain);
|
||||
WINPR_ASSERT(instance);
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
settings = instance->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
PROXY_LOG_INFO(TAG, pc, "connecting using client info: Username: %s, Domain: %s",
|
||||
settings->Username, settings->Domain);
|
||||
|
||||
pf_client_set_security_settings(pc);
|
||||
if (pf_client_should_retry_without_nla(pc))
|
||||
retry = pc->allow_next_conn_failure = TRUE;
|
||||
|
||||
LOG_INFO(TAG, pc, "connecting using security settings: rdp=%d, tls=%d, nla=%d",
|
||||
settings->RdpSecurity, settings->TlsSecurity, settings->NlaSecurity);
|
||||
PROXY_LOG_INFO(TAG, pc, "connecting using security settings: rdp=%d, tls=%d, nla=%d",
|
||||
settings->RdpSecurity, settings->TlsSecurity, settings->NlaSecurity);
|
||||
|
||||
if (!freerdp_connect(instance))
|
||||
{
|
||||
if (!retry)
|
||||
goto out;
|
||||
|
||||
LOG_ERR(TAG, pc, "failed to connect with NLA. retrying to connect without NLA");
|
||||
pf_modules_run_hook(HOOK_TYPE_CLIENT_LOGIN_FAILURE, pc->pdata);
|
||||
PROXY_LOG_ERR(TAG, pc, "failed to connect with NLA. retrying to connect without NLA");
|
||||
pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_LOGIN_FAILURE, pc->pdata, pc);
|
||||
|
||||
if (!pf_client_connect_without_nla(pc))
|
||||
{
|
||||
LOG_ERR(TAG, pc, "pf_client_connect_without_nla failed!");
|
||||
PROXY_LOG_ERR(TAG, pc, "pf_client_connect_without_nla failed!");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -483,12 +682,17 @@ out:
|
||||
static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
|
||||
{
|
||||
freerdp* instance = (freerdp*)arg;
|
||||
pClientContext* pc = (pClientContext*)instance->context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
DWORD nCount;
|
||||
pClientContext* pc;
|
||||
proxyData* pdata;
|
||||
DWORD nCount = 0;
|
||||
DWORD status;
|
||||
HANDLE handles[65];
|
||||
HANDLE handles[65] = { 0 };
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
/*
|
||||
* during redirection, freerdp's abort event might be overriden (reset) by the library, after
|
||||
* the server set it in order to shutdown the connection. it means that the server might signal
|
||||
@ -496,9 +700,9 @@ static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
|
||||
* continue its work instead of exiting. That's why the client must wait on `pdata->abort_event`
|
||||
* too, which will never be modified by the library.
|
||||
*/
|
||||
handles[64] = pdata->abort_event;
|
||||
handles[nCount++] = pdata->abort_event;
|
||||
|
||||
if (!pf_modules_run_hook(HOOK_TYPE_CLIENT_PRE_CONNECT, pdata))
|
||||
if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_CLIENT_INIT_CONNECT, pdata, pc))
|
||||
{
|
||||
proxy_data_abort_connect(pdata);
|
||||
return FALSE;
|
||||
@ -512,15 +716,16 @@ static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
|
||||
|
||||
while (!freerdp_shall_disconnect(instance))
|
||||
{
|
||||
nCount = freerdp_get_event_handles(instance->context, &handles[0], 64);
|
||||
UINT32 tmp = freerdp_get_event_handles(instance->context, &handles[nCount],
|
||||
ARRAYSIZE(handles) - nCount);
|
||||
|
||||
if (nCount == 0)
|
||||
if (tmp == 0)
|
||||
{
|
||||
LOG_ERR(TAG, pc, "freerdp_get_event_handles failed!");
|
||||
PROXY_LOG_ERR(TAG, pc, "freerdp_get_event_handles failed!");
|
||||
break;
|
||||
}
|
||||
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
status = WaitForMultipleObjects(nCount + tmp, handles, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
@ -529,6 +734,10 @@ static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
|
||||
break;
|
||||
}
|
||||
|
||||
/* abort_event triggered */
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (freerdp_shall_disconnect(instance))
|
||||
break;
|
||||
|
||||
@ -545,6 +754,9 @@ static DWORD WINAPI pf_client_thread_proc(LPVOID arg)
|
||||
}
|
||||
|
||||
freerdp_disconnect(instance);
|
||||
|
||||
pf_modules_run_hook(pdata->module, HOOK_TYPE_CLIENT_UNINIT_CONNECT, pdata, pc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -560,91 +772,126 @@ static int pf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback set in the rdp_freerdp structure, and used to make a certificate validation
|
||||
* when the connection requires it.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param host The host currently connecting to
|
||||
* @param port The port currently connecting to
|
||||
* @param common_name The common name of the certificate, should match host or an alias of it
|
||||
* @param subject The subject of the certificate
|
||||
* @param issuer The certificate issuer name
|
||||
* @param fingerprint The fingerprint of the certificate
|
||||
* @param flags See VERIFY_CERT_FLAG_* for possible values.
|
||||
*
|
||||
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
|
||||
*/
|
||||
static DWORD pf_client_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port,
|
||||
const char* common_name, const char* subject,
|
||||
const char* issuer, const char* fingerprint,
|
||||
DWORD flags)
|
||||
{
|
||||
/* TODO: Add trust level to proxy configurable settings */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback set in the rdp_freerdp structure, and used to make a certificate validation
|
||||
* when a stored certificate does not match the remote counterpart.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param host The host currently connecting to
|
||||
* @param port The port currently connecting to
|
||||
* @param common_name The common name of the certificate, should match host or an alias of it
|
||||
* @param subject The subject of the certificate
|
||||
* @param issuer The certificate issuer name
|
||||
* @param fingerprint The fingerprint of the certificate
|
||||
* @param old_subject The subject of the previous certificate
|
||||
* @param old_issuer The previous certificate issuer name
|
||||
* @param old_fingerprint The fingerprint of the previous certificate
|
||||
* @param flags See VERIFY_CERT_FLAG_* for possible values.
|
||||
*
|
||||
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
|
||||
*/
|
||||
static DWORD pf_client_verify_changed_certificate_ex(
|
||||
freerdp* instance, const char* host, UINT16 port, const char* common_name, const char* subject,
|
||||
const char* issuer, const char* fingerprint, const char* old_subject, const char* old_issuer,
|
||||
const char* old_fingerprint, DWORD flags)
|
||||
{
|
||||
/* TODO: Add trust level to proxy configurable settings */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pf_client_context_free(freerdp* instance, rdpContext* context)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
WINPR_UNUSED(instance);
|
||||
|
||||
if (!pc)
|
||||
return;
|
||||
|
||||
HashTable_Free(pc->vc_ids);
|
||||
pc->sendChannelData = NULL;
|
||||
ArrayList_Free(pc->cached_server_channel_data);
|
||||
Stream_Free(pc->remote_pem, TRUE);
|
||||
free(pc->remote_hostname);
|
||||
}
|
||||
|
||||
static int pf_client_verify_X509_certificate(freerdp* instance, const BYTE* data, size_t length,
|
||||
const char* hostname, UINT16 port, DWORD flags)
|
||||
{
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(data);
|
||||
WINPR_ASSERT(length > 0);
|
||||
WINPR_ASSERT(hostname);
|
||||
|
||||
pc = (pClientContext*)instance->context;
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
if (!Stream_EnsureCapacity(pc->remote_pem, length))
|
||||
return 0;
|
||||
Stream_SetPosition(pc->remote_pem, 0);
|
||||
|
||||
free(pc->remote_hostname);
|
||||
pc->remote_hostname = NULL;
|
||||
|
||||
if (length > 0)
|
||||
Stream_Write(pc->remote_pem, data, length);
|
||||
|
||||
if (hostname)
|
||||
pc->remote_hostname = _strdup(hostname);
|
||||
pc->remote_port = port;
|
||||
pc->remote_flags = flags;
|
||||
|
||||
Stream_SealLength(pc->remote_pem);
|
||||
if (!pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_VERIFY_X509, pc->pdata, pc))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void* channel_data_copy(const void* obj)
|
||||
{
|
||||
const proxyChannelDataEventInfo* src = obj;
|
||||
proxyChannelDataEventInfo* dst;
|
||||
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
dst = calloc(1, sizeof(proxyChannelDataEventInfo));
|
||||
WINPR_ASSERT(dst);
|
||||
|
||||
*dst = *src;
|
||||
if (src->channel_name)
|
||||
{
|
||||
dst->channel_name = _strdup(src->channel_name);
|
||||
WINPR_ASSERT(dst->channel_name);
|
||||
}
|
||||
dst->data = malloc(src->data_len);
|
||||
WINPR_ASSERT(dst->data);
|
||||
memcpy((void*)dst->data, src->data, src->data_len);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void channel_data_free(void* obj)
|
||||
{
|
||||
proxyChannelDataEventInfo* dst = obj;
|
||||
if (dst)
|
||||
{
|
||||
free((void*)dst->data);
|
||||
free((void*)dst->channel_name);
|
||||
free(dst);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL pf_client_client_new(freerdp* instance, rdpContext* context)
|
||||
{
|
||||
wObject* obj;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
|
||||
if (!instance || !context)
|
||||
return FALSE;
|
||||
|
||||
instance->PreConnect = pf_client_pre_connect;
|
||||
instance->PostConnect = pf_client_post_connect;
|
||||
instance->PostDisconnect = pf_client_post_disconnect;
|
||||
instance->VerifyCertificateEx = pf_client_verify_certificate_ex;
|
||||
instance->VerifyChangedCertificateEx = pf_client_verify_changed_certificate_ex;
|
||||
instance->LogonErrorInfo = pf_logon_error_info;
|
||||
instance->ContextFree = pf_client_context_free;
|
||||
instance->VerifyX509Certificate = pf_client_verify_X509_certificate;
|
||||
|
||||
pc->remote_pem = Stream_New(NULL, 4096);
|
||||
if (!pc->remote_pem)
|
||||
return FALSE;
|
||||
|
||||
pc->sendChannelData = pf_client_send_channel_data;
|
||||
pc->cached_server_channel_data = ArrayList_New(TRUE);
|
||||
if (!pc->cached_server_channel_data)
|
||||
return FALSE;
|
||||
obj = ArrayList_Object(pc->cached_server_channel_data);
|
||||
WINPR_ASSERT(obj);
|
||||
obj->fnObjectNew = channel_data_copy;
|
||||
obj->fnObjectFree = channel_data_free;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int pf_client_client_stop(rdpContext* context)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
proxyData* pdata;
|
||||
|
||||
LOG_DBG(TAG, pc, "aborting client connection");
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
PROXY_LOG_DBG(TAG, pc, "aborting client connection");
|
||||
proxy_data_abort_connect(pdata);
|
||||
freerdp_abort_connect(context->instance);
|
||||
|
||||
@ -654,9 +901,9 @@ static int pf_client_client_stop(rdpContext* context)
|
||||
* Wait for client thread to finish. No need to call CloseHandle() here, as
|
||||
* it is the responsibility of `proxy_data_free`.
|
||||
*/
|
||||
LOG_DBG(TAG, pc, "waiting for client thread to finish");
|
||||
PROXY_LOG_DBG(TAG, pc, "waiting for client thread to finish");
|
||||
WaitForSingleObject(pdata->client_thread, INFINITE);
|
||||
LOG_DBG(TAG, pc, "thread finished");
|
||||
PROXY_LOG_DBG(TAG, pc, "thread finished");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -664,12 +911,15 @@ static int pf_client_client_stop(rdpContext* context)
|
||||
|
||||
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
WINPR_ASSERT(pEntryPoints);
|
||||
|
||||
ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
|
||||
pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
|
||||
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
|
||||
pEntryPoints->ContextSize = sizeof(pClientContext);
|
||||
/* Client init and finish */
|
||||
pEntryPoints->ClientNew = pf_client_client_new;
|
||||
pEntryPoints->ClientFree = pf_client_context_free;
|
||||
pEntryPoints->ClientStop = pf_client_client_stop;
|
||||
return 0;
|
||||
}
|
||||
@ -681,6 +931,7 @@ DWORD WINAPI pf_client_start(LPVOID arg)
|
||||
{
|
||||
rdpContext* context = (rdpContext*)arg;
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
if (freerdp_client_start(context) != 0)
|
||||
return 1;
|
||||
|
||||
|
@ -18,8 +18,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_cliprdr.h"
|
||||
#include "pf_log.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
|
||||
#define TAG PROXY_TAG("cliprdr")
|
||||
#define TEXT_FORMATS_COUNT 2
|
||||
@ -30,6 +33,8 @@ static CLIPRDR_FORMAT g_text_formats[] = { { CF_TEXT, "\0" }, { CF_UNICODETEXT,
|
||||
BOOL pf_server_cliprdr_init(pServerContext* ps)
|
||||
{
|
||||
CliprdrServerContext* cliprdr;
|
||||
|
||||
WINPR_ASSERT(ps);
|
||||
cliprdr = ps->cliprdr = cliprdr_server_context_new(ps->vcm);
|
||||
|
||||
if (!cliprdr)
|
||||
@ -66,6 +71,7 @@ static INLINE BOOL pf_cliprdr_is_text_format(UINT32 format)
|
||||
|
||||
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;
|
||||
@ -77,10 +83,14 @@ static INLINE void pf_cliprdr_create_text_only_format_list(CLIPRDR_FORMAT_LIST*
|
||||
* 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(proxyConfig* config,
|
||||
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 */
|
||||
@ -126,6 +136,8 @@ static BOOL pf_cliprdr_is_copy_paste_valid(proxyConfig* config,
|
||||
*/
|
||||
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;
|
||||
@ -136,8 +148,20 @@ static INLINE void pf_cliprdr_create_failed_format_data_response(CLIPRDR_FORMAT_
|
||||
static UINT pf_cliprdr_ClientCapabilities(CliprdrServerContext* context,
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -145,8 +169,20 @@ static UINT pf_cliprdr_ClientCapabilities(CliprdrServerContext* context,
|
||||
static UINT pf_cliprdr_TempDirectory(CliprdrServerContext* context,
|
||||
const CLIPRDR_TEMP_DIRECTORY* tempDirectory)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -154,13 +190,25 @@ static UINT pf_cliprdr_TempDirectory(CliprdrServerContext* context,
|
||||
static UINT pf_cliprdr_ClientFormatList(CliprdrServerContext* context,
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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;
|
||||
CLIPRDR_FORMAT_LIST list = { 0 };
|
||||
pf_cliprdr_create_text_only_format_list(&list);
|
||||
return client->ClientFormatList(client, &list);
|
||||
}
|
||||
@ -173,8 +221,20 @@ static UINT
|
||||
pf_cliprdr_ClientFormatListResponse(CliprdrServerContext* context,
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -182,8 +242,20 @@ pf_cliprdr_ClientFormatListResponse(CliprdrServerContext* context,
|
||||
static UINT pf_cliprdr_ClientLockClipboardData(CliprdrServerContext* context,
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -192,8 +264,20 @@ static UINT
|
||||
pf_cliprdr_ClientUnlockClipboardData(CliprdrServerContext* context,
|
||||
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -201,18 +285,36 @@ pf_cliprdr_ClientUnlockClipboardData(CliprdrServerContext* context,
|
||||
static UINT pf_cliprdr_ClientFormatDataRequest(CliprdrServerContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -220,8 +322,21 @@ static UINT
|
||||
pf_cliprdr_ClientFormatDataResponse(CliprdrServerContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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))
|
||||
@ -242,8 +357,21 @@ static UINT
|
||||
pf_cliprdr_ClientFileContentsRequest(CliprdrServerContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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)
|
||||
@ -256,8 +384,21 @@ static UINT
|
||||
pf_cliprdr_ClientFileContentsResponse(CliprdrServerContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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)
|
||||
@ -271,8 +412,21 @@ pf_cliprdr_ClientFileContentsResponse(CliprdrServerContext* context,
|
||||
static UINT pf_cliprdr_ServerCapabilities(CliprdrClientContext* context,
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -280,8 +434,21 @@ static UINT pf_cliprdr_ServerCapabilities(CliprdrClientContext* context,
|
||||
static UINT pf_cliprdr_MonitorReady(CliprdrClientContext* context,
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -289,8 +456,21 @@ static UINT pf_cliprdr_MonitorReady(CliprdrClientContext* context,
|
||||
static UINT pf_cliprdr_ServerFormatList(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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)
|
||||
@ -307,8 +487,21 @@ static UINT
|
||||
pf_cliprdr_ServerFormatListResponse(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -316,8 +509,21 @@ pf_cliprdr_ServerFormatListResponse(CliprdrClientContext* context,
|
||||
static UINT pf_cliprdr_ServerLockClipboardData(CliprdrClientContext* context,
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -326,8 +532,21 @@ static UINT
|
||||
pf_cliprdr_ServerUnlockClipboardData(CliprdrClientContext* context,
|
||||
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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);
|
||||
}
|
||||
@ -335,19 +554,37 @@ pf_cliprdr_ServerUnlockClipboardData(CliprdrClientContext* context,
|
||||
static UINT pf_cliprdr_ServerFormatDataRequest(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
CliprdrClientContext* client = pdata->pc->cliprdr;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -355,8 +592,21 @@ static UINT
|
||||
pf_cliprdr_ServerFormatDataResponse(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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))
|
||||
@ -377,8 +627,21 @@ static UINT
|
||||
pf_cliprdr_ServerFileContentsRequest(CliprdrClientContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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)
|
||||
@ -391,8 +654,21 @@ static UINT
|
||||
pf_cliprdr_ServerFileContentsResponse(CliprdrClientContext* context,
|
||||
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
CliprdrServerContext* server = pdata->ps->cliprdr;
|
||||
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)
|
||||
@ -404,6 +680,10 @@ pf_cliprdr_ServerFileContentsResponse(CliprdrClientContext* context,
|
||||
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;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/server/cliprdr.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
BOOL pf_server_cliprdr_init(pServerContext* ps);
|
||||
void pf_cliprdr_register_callbacks(CliprdrClientContext* cliprdr_client,
|
||||
|
@ -24,15 +24,18 @@
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_server.h"
|
||||
#include "pf_config.h"
|
||||
#include "pf_modules.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#define TAG PROXY_TAG("config")
|
||||
|
||||
#define CONFIG_PRINT_SECTION(section) WLog_INFO(TAG, "\t%s:", section)
|
||||
#define CONFIG_PRINT_STR(config, key) WLog_INFO(TAG, "\t\t%s: %s", #key, config->key)
|
||||
#define CONFIG_PRINT_STR_CONTENT(config, key) \
|
||||
WLog_INFO(TAG, "\t\t%s: %s", #key, config->key ? "set" : NULL)
|
||||
#define CONFIG_PRINT_BOOL(config, key) \
|
||||
WLog_INFO(TAG, "\t\t%s: %s", #key, config->key ? "TRUE" : "FALSE")
|
||||
#define CONFIG_PRINT_UINT16(config, key) WLog_INFO(TAG, "\t\t%s: %" PRIu16 "", #key, config->key)
|
||||
@ -52,12 +55,22 @@ static char** pf_config_parse_comma_separated_list(const char* list, size_t* cou
|
||||
return CommandLineParseCommaSeparatedValues(list, count);
|
||||
}
|
||||
|
||||
BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key, UINT16* result)
|
||||
static BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key,
|
||||
UINT16* result, BOOL required)
|
||||
{
|
||||
int val;
|
||||
const char* strval;
|
||||
|
||||
WINPR_ASSERT(result);
|
||||
|
||||
strval = IniFile_GetKeyValueString(ini, section, key);
|
||||
if (!strval && required)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: key '%s.%s' does not exist.", __FUNCTION__, section, key);
|
||||
return FALSE;
|
||||
}
|
||||
val = IniFile_GetKeyValueInt(ini, section, key);
|
||||
if ((val < 0) || (val > UINT16_MAX))
|
||||
if ((val <= 0) || (val > UINT16_MAX))
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: invalid value %d for key '%s.%s'.", __FUNCTION__, val, section, key);
|
||||
return FALSE;
|
||||
@ -67,9 +80,20 @@ BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key, U
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key, UINT32* result)
|
||||
static BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key,
|
||||
UINT32* result, BOOL required)
|
||||
{
|
||||
int val;
|
||||
const char* strval;
|
||||
|
||||
WINPR_ASSERT(result);
|
||||
|
||||
strval = IniFile_GetKeyValueString(ini, section, key);
|
||||
if (!strval && required)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: key '%s.%s' does not exist.", __FUNCTION__, section, key);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
val = IniFile_GetKeyValueInt(ini, section, key);
|
||||
if ((val < 0) || (val > INT32_MAX))
|
||||
@ -82,7 +106,7 @@ BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key, U
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key)
|
||||
static BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key, BOOL fallback)
|
||||
{
|
||||
int num_value;
|
||||
const char* str_value;
|
||||
@ -90,23 +114,26 @@ BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key)
|
||||
str_value = IniFile_GetKeyValueString(ini, section, key);
|
||||
if (!str_value)
|
||||
{
|
||||
WLog_WARN(TAG, "[%s]: key '%s.%s' not found, value defaults to false.", __FUNCTION__,
|
||||
section, key);
|
||||
return FALSE;
|
||||
WLog_WARN(TAG, "[%s]: key '%s.%s' not found, value defaults to %s.", __FUNCTION__, section,
|
||||
key, fallback ? "true" : "false");
|
||||
return fallback;
|
||||
}
|
||||
|
||||
if (strcmp(str_value, "TRUE") == 0 || strcmp(str_value, "true") == 0)
|
||||
if (_stricmp(str_value, "TRUE") == 0)
|
||||
return TRUE;
|
||||
if (_stricmp(str_value, "FALSE") == 0)
|
||||
return FALSE;
|
||||
|
||||
num_value = IniFile_GetKeyValueInt(ini, section, key);
|
||||
|
||||
if (num_value == 1)
|
||||
if (num_value != 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key)
|
||||
static const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key,
|
||||
BOOL required)
|
||||
{
|
||||
const char* value;
|
||||
|
||||
@ -114,7 +141,8 @@ const char* pf_config_get_str(wIniFile* ini, const char* section, const char* ke
|
||||
|
||||
if (!value)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: key '%s.%s' not found.", __FUNCTION__, section, key);
|
||||
if (required)
|
||||
WLog_ERR(TAG, "[%s]: key '%s.%s' not found.", __FUNCTION__, section, key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -125,19 +153,20 @@ static BOOL pf_config_load_server(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
const char* host;
|
||||
|
||||
if (!pf_config_get_uint16(ini, "Server", "Port", &config->Port))
|
||||
return FALSE;
|
||||
|
||||
host = pf_config_get_str(ini, "Server", "Host");
|
||||
WINPR_ASSERT(config);
|
||||
host = pf_config_get_str(ini, "Server", "Host", FALSE);
|
||||
|
||||
if (!host)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
||||
config->Host = _strdup(host);
|
||||
|
||||
if (!config->Host)
|
||||
return FALSE;
|
||||
|
||||
if (!pf_config_get_uint16(ini, "Server", "Port", &config->Port, TRUE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -145,10 +174,13 @@ static BOOL pf_config_load_target(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
const char* target_host;
|
||||
|
||||
if (!pf_config_get_uint16(ini, "Target", "Port", &config->TargetPort))
|
||||
WINPR_ASSERT(config);
|
||||
config->FixedTarget = pf_config_get_bool(ini, "Target", "FixedTarget", FALSE);
|
||||
|
||||
if (!pf_config_get_uint16(ini, "Target", "Port", &config->TargetPort, config->FixedTarget))
|
||||
return FALSE;
|
||||
|
||||
target_host = pf_config_get_str(ini, "Target", "Host");
|
||||
target_host = pf_config_get_str(ini, "Target", "Host", config->FixedTarget);
|
||||
|
||||
if (!target_host)
|
||||
return FALSE;
|
||||
@ -157,19 +189,22 @@ static BOOL pf_config_load_target(wIniFile* ini, proxyConfig* config)
|
||||
if (!config->TargetHost)
|
||||
return FALSE;
|
||||
|
||||
config->FixedTarget = pf_config_get_bool(ini, "Target", "FixedTarget");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
config->GFX = pf_config_get_bool(ini, "Channels", "GFX");
|
||||
config->DisplayControl = pf_config_get_bool(ini, "Channels", "DisplayControl");
|
||||
config->Clipboard = pf_config_get_bool(ini, "Channels", "Clipboard");
|
||||
config->AudioOutput = pf_config_get_bool(ini, "Channels", "AudioOutput");
|
||||
config->RemoteApp = pf_config_get_bool(ini, "Channels", "RemoteApp");
|
||||
WINPR_ASSERT(config);
|
||||
config->GFX = pf_config_get_bool(ini, "Channels", "GFX", TRUE);
|
||||
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->RemoteApp = pf_config_get_bool(ini, "Channels", "RemoteApp", FALSE);
|
||||
config->PassthroughIsBlacklist =
|
||||
pf_config_get_bool(ini, "Channels", "PassthroughIsBlacklist", FALSE);
|
||||
|
||||
config->Passthrough = pf_config_parse_comma_separated_list(
|
||||
pf_config_get_str(ini, "Channels", "Passthrough"), &config->PassthroughCount);
|
||||
pf_config_get_str(ini, "Channels", "Passthrough", FALSE), &config->PassthroughCount);
|
||||
|
||||
{
|
||||
/* validate channel name length */
|
||||
@ -177,7 +212,8 @@ static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config)
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
{
|
||||
if (strlen(config->Passthrough[i]) > CHANNEL_NAME_LEN)
|
||||
const char* name = config->Passthrough[i];
|
||||
if (strlen(name) > CHANNEL_NAME_LEN)
|
||||
{
|
||||
WLog_ERR(TAG, "passthrough channel: %s: name too long!", config->Passthrough[i]);
|
||||
return FALSE;
|
||||
@ -190,29 +226,33 @@ static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config)
|
||||
|
||||
static BOOL pf_config_load_input(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
config->Keyboard = pf_config_get_bool(ini, "Input", "Keyboard");
|
||||
config->Mouse = pf_config_get_bool(ini, "Input", "Mouse");
|
||||
WINPR_ASSERT(config);
|
||||
config->Keyboard = pf_config_get_bool(ini, "Input", "Keyboard", TRUE);
|
||||
config->Mouse = pf_config_get_bool(ini, "Input", "Mouse", TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_config_load_security(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
config->ServerTlsSecurity = pf_config_get_bool(ini, "Security", "ServerTlsSecurity");
|
||||
config->ServerRdpSecurity = pf_config_get_bool(ini, "Security", "ServerRdpSecurity");
|
||||
WINPR_ASSERT(config);
|
||||
config->ServerTlsSecurity = pf_config_get_bool(ini, "Security", "ServerTlsSecurity", TRUE);
|
||||
config->ServerNlaSecurity = pf_config_get_bool(ini, "Security", "ServerNlaSecurity", FALSE);
|
||||
config->ServerRdpSecurity = pf_config_get_bool(ini, "Security", "ServerRdpSecurity", TRUE);
|
||||
|
||||
config->ClientTlsSecurity = pf_config_get_bool(ini, "Security", "ClientTlsSecurity");
|
||||
config->ClientNlaSecurity = pf_config_get_bool(ini, "Security", "ClientNlaSecurity");
|
||||
config->ClientRdpSecurity = pf_config_get_bool(ini, "Security", "ClientRdpSecurity");
|
||||
config->ClientTlsSecurity = pf_config_get_bool(ini, "Security", "ClientTlsSecurity", TRUE);
|
||||
config->ClientNlaSecurity = pf_config_get_bool(ini, "Security", "ClientNlaSecurity", TRUE);
|
||||
config->ClientRdpSecurity = pf_config_get_bool(ini, "Security", "ClientRdpSecurity", TRUE);
|
||||
config->ClientAllowFallbackToTls =
|
||||
pf_config_get_bool(ini, "Security", "ClientAllowFallbackToTls");
|
||||
pf_config_get_bool(ini, "Security", "ClientAllowFallbackToTls", TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_config_load_clipboard(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
config->TextOnly = pf_config_get_bool(ini, "Clipboard", "TextOnly");
|
||||
WINPR_ASSERT(config);
|
||||
config->TextOnly = pf_config_get_bool(ini, "Clipboard", "TextOnly", FALSE);
|
||||
|
||||
if (!pf_config_get_uint32(ini, "Clipboard", "MaxTextLength", &config->MaxTextLength))
|
||||
if (!pf_config_get_uint32(ini, "Clipboard", "MaxTextLength", &config->MaxTextLength, FALSE))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -226,6 +266,7 @@ static BOOL pf_config_load_modules(wIniFile* ini, proxyConfig* config)
|
||||
modules_to_load = IniFile_GetKeyValueString(ini, "Plugins", "Modules");
|
||||
required_modules = IniFile_GetKeyValueString(ini, "Plugins", "Required");
|
||||
|
||||
WINPR_ASSERT(config);
|
||||
config->Modules = pf_config_parse_comma_separated_list(modules_to_load, &config->ModulesCount);
|
||||
|
||||
config->RequiredPlugins =
|
||||
@ -235,11 +276,190 @@ static BOOL pf_config_load_modules(wIniFile* ini, proxyConfig* config)
|
||||
|
||||
static BOOL pf_config_load_gfx_settings(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
config->DecodeGFX = pf_config_get_bool(ini, "GFXSettings", "DecodeGFX");
|
||||
WINPR_ASSERT(config);
|
||||
config->DecodeGFX = pf_config_get_bool(ini, "GFXSettings", "DecodeGFX", FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
proxyConfig* pf_server_config_load(const char* path)
|
||||
static BOOL pf_config_load_certificates(wIniFile* ini, proxyConfig* config)
|
||||
{
|
||||
const char* tmp1;
|
||||
const char* tmp2;
|
||||
|
||||
WINPR_ASSERT(ini);
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
tmp1 = pf_config_get_str(ini, "Certificates", "CertificateFile", FALSE);
|
||||
if (tmp1)
|
||||
{
|
||||
if (!winpr_PathFileExists(tmp1))
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/CertificateFile file %s does not exist", tmp1);
|
||||
return FALSE;
|
||||
}
|
||||
config->CertificateFile = _strdup(tmp1);
|
||||
}
|
||||
tmp2 = pf_config_get_str(ini, "Certificates", "CertificateContent", FALSE);
|
||||
if (tmp2)
|
||||
{
|
||||
if (strlen(tmp2) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/CertificateContent has invalid empty value");
|
||||
return FALSE;
|
||||
}
|
||||
config->CertificateContent = _strdup(tmp2);
|
||||
}
|
||||
if (tmp1 && tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/CertificateFile and Certificates/CertificateContent are "
|
||||
"mutually exclusive options");
|
||||
return FALSE;
|
||||
}
|
||||
else if (!tmp1 && !tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/CertificateFile or Certificates/CertificateContent are "
|
||||
"required settings");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tmp1 = pf_config_get_str(ini, "Certificates", "PrivateKeyFile", FALSE);
|
||||
if (tmp1)
|
||||
{
|
||||
if (!winpr_PathFileExists(tmp1))
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/PrivateKeyFile file %s does not exist", tmp1);
|
||||
return FALSE;
|
||||
}
|
||||
config->PrivateKeyFile = _strdup(tmp1);
|
||||
}
|
||||
tmp2 = pf_config_get_str(ini, "Certificates", "PrivateKeyContent", FALSE);
|
||||
if (tmp2)
|
||||
{
|
||||
if (strlen(tmp2) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/PrivateKeyContent has invalid empty value");
|
||||
return FALSE;
|
||||
}
|
||||
config->PrivateKeyContent = _strdup(tmp2);
|
||||
}
|
||||
|
||||
if (tmp1 && tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/PrivateKeyFile and Certificates/PrivateKeyContent are "
|
||||
"mutually exclusive options");
|
||||
return FALSE;
|
||||
}
|
||||
else if (!tmp1 && !tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/PrivateKeyFile or Certificates/PrivateKeyContent are "
|
||||
"are required settings");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tmp1 = pf_config_get_str(ini, "Certificates", "RdpKeyFile", FALSE);
|
||||
if (tmp1)
|
||||
{
|
||||
if (!winpr_PathFileExists(tmp1))
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/RdpKeyFile file %s does not exist", tmp1);
|
||||
return FALSE;
|
||||
}
|
||||
config->RdpKeyFile = _strdup(tmp1);
|
||||
}
|
||||
tmp2 = pf_config_get_str(ini, "Certificates", "RdpKeyContent", FALSE);
|
||||
if (tmp2)
|
||||
{
|
||||
if (strlen(tmp2) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/RdpKeyContent has invalid empty value");
|
||||
return FALSE;
|
||||
}
|
||||
config->RdpKeyContent = _strdup(tmp2);
|
||||
}
|
||||
if (tmp1 && tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/RdpKeyFile and Certificates/RdpKeyContent are mutually "
|
||||
"exclusive options");
|
||||
return FALSE;
|
||||
}
|
||||
else if (!tmp1 && !tmp2)
|
||||
{
|
||||
WLog_ERR(TAG, "Certificates/RdpKeyFile or Certificates/RdpKeyContent are "
|
||||
"required settings");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
proxyConfig* server_config_load_ini(wIniFile* ini)
|
||||
{
|
||||
proxyConfig* config = NULL;
|
||||
|
||||
WINPR_ASSERT(ini);
|
||||
|
||||
config = calloc(1, sizeof(proxyConfig));
|
||||
if (config)
|
||||
{
|
||||
if (!pf_config_load_server(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_target(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_channels(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_input(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_security(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_modules(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_clipboard(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_gfx_settings(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_certificates(ini, config))
|
||||
goto out;
|
||||
}
|
||||
return config;
|
||||
out:
|
||||
pf_server_config_free(config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
proxyConfig* pf_server_config_load_buffer(const char* buffer)
|
||||
{
|
||||
proxyConfig* config = NULL;
|
||||
wIniFile* ini;
|
||||
|
||||
ini = IniFile_New();
|
||||
|
||||
if (!ini)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: IniFile_New() failed!", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IniFile_ReadBuffer(ini, buffer) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s] failed to parse ini: '%s'", __FUNCTION__, buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
config = server_config_load_ini(ini);
|
||||
out:
|
||||
IniFile_Free(ini);
|
||||
return config;
|
||||
}
|
||||
|
||||
proxyConfig* pf_server_config_load_file(const char* path)
|
||||
{
|
||||
proxyConfig* config = NULL;
|
||||
wIniFile* ini = IniFile_New();
|
||||
@ -247,7 +467,7 @@ proxyConfig* pf_server_config_load(const char* path)
|
||||
if (!ini)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: IniFile_New() failed!", __FUNCTION__);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (IniFile_ReadFile(ini, path) < 0)
|
||||
@ -256,51 +476,26 @@ proxyConfig* pf_server_config_load(const char* path)
|
||||
goto out;
|
||||
}
|
||||
|
||||
config = calloc(1, sizeof(proxyConfig));
|
||||
|
||||
if (!pf_config_load_server(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_target(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_channels(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_input(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_security(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_modules(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_clipboard(ini, config))
|
||||
goto out;
|
||||
|
||||
if (!pf_config_load_gfx_settings(ini, config))
|
||||
goto out;
|
||||
|
||||
IniFile_Free(ini);
|
||||
return config;
|
||||
|
||||
config = server_config_load_ini(ini);
|
||||
out:
|
||||
IniFile_Free(ini);
|
||||
pf_server_config_free(config);
|
||||
return NULL;
|
||||
return config;
|
||||
}
|
||||
|
||||
static void pf_server_config_print_list(char** list, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
WINPR_ASSERT(list);
|
||||
for (i = 0; i < count; i++)
|
||||
WLog_INFO(TAG, "\t\t- %s", list[i]);
|
||||
}
|
||||
|
||||
void pf_server_config_print(proxyConfig* config)
|
||||
void pf_server_config_print(const proxyConfig* config)
|
||||
{
|
||||
size_t x;
|
||||
|
||||
WINPR_ASSERT(config);
|
||||
WLog_INFO(TAG, "Proxy configuration:");
|
||||
|
||||
CONFIG_PRINT_SECTION("Server");
|
||||
@ -334,6 +529,7 @@ void pf_server_config_print(proxyConfig* config)
|
||||
CONFIG_PRINT_BOOL(config, Clipboard);
|
||||
CONFIG_PRINT_BOOL(config, AudioOutput);
|
||||
CONFIG_PRINT_BOOL(config, RemoteApp);
|
||||
CONFIG_PRINT_BOOL(config, PassthroughIsBlacklist);
|
||||
|
||||
if (config->PassthroughCount)
|
||||
{
|
||||
@ -348,6 +544,24 @@ void pf_server_config_print(proxyConfig* config)
|
||||
|
||||
CONFIG_PRINT_SECTION("GFXSettings");
|
||||
CONFIG_PRINT_BOOL(config, DecodeGFX);
|
||||
|
||||
/* modules */
|
||||
CONFIG_PRINT_SECTION("Plugins/Modules");
|
||||
for (x = 0; x < config->ModulesCount; x++)
|
||||
CONFIG_PRINT_STR(config, Modules[x]);
|
||||
|
||||
/* Required plugins */
|
||||
CONFIG_PRINT_SECTION("Plugins/Required");
|
||||
for (x = 0; x < config->RequiredPluginsCount; x++)
|
||||
CONFIG_PRINT_STR(config, RequiredPlugins[x]);
|
||||
|
||||
CONFIG_PRINT_SECTION("Certificates");
|
||||
CONFIG_PRINT_STR(config, CertificateFile);
|
||||
CONFIG_PRINT_STR_CONTENT(config, CertificateContent);
|
||||
CONFIG_PRINT_STR(config, PrivateKeyFile);
|
||||
CONFIG_PRINT_STR_CONTENT(config, PrivateKeyContent);
|
||||
CONFIG_PRINT_STR(config, RdpKeyFile);
|
||||
CONFIG_PRINT_STR_CONTENT(config, RdpKeyContent);
|
||||
}
|
||||
|
||||
void pf_server_config_free(proxyConfig* config)
|
||||
@ -360,5 +574,113 @@ void pf_server_config_free(proxyConfig* config)
|
||||
free(config->Modules);
|
||||
free(config->TargetHost);
|
||||
free(config->Host);
|
||||
free(config->CertificateFile);
|
||||
free(config->CertificateContent);
|
||||
free(config->PrivateKeyFile);
|
||||
free(config->PrivateKeyContent);
|
||||
free(config->RdpKeyFile);
|
||||
free(config->RdpKeyContent);
|
||||
free(config);
|
||||
}
|
||||
|
||||
size_t pf_config_required_plugins_count(const proxyConfig* config)
|
||||
{
|
||||
WINPR_ASSERT(config);
|
||||
return config->RequiredPluginsCount;
|
||||
}
|
||||
|
||||
const char* pf_config_required_plugin(const proxyConfig* config, size_t index)
|
||||
{
|
||||
WINPR_ASSERT(config);
|
||||
if (index >= config->RequiredPluginsCount)
|
||||
return NULL;
|
||||
|
||||
return config->RequiredPlugins[index];
|
||||
}
|
||||
|
||||
size_t pf_config_modules_count(const proxyConfig* config)
|
||||
{
|
||||
WINPR_ASSERT(config);
|
||||
return config->ModulesCount;
|
||||
}
|
||||
|
||||
const char** pf_config_modules(const proxyConfig* config)
|
||||
{
|
||||
WINPR_ASSERT(config);
|
||||
return config->Modules;
|
||||
}
|
||||
|
||||
static BOOL pf_config_copy_string(char** dst, const char* src)
|
||||
{
|
||||
*dst = NULL;
|
||||
if (src)
|
||||
*dst = _strdup(src);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_config_copy_string_list(char*** dst, size_t* size, char** src, size_t srcSize)
|
||||
{
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(size);
|
||||
WINPR_ASSERT(src || (srcSize == 0));
|
||||
|
||||
*dst = NULL;
|
||||
*size = 0;
|
||||
if (srcSize == 0)
|
||||
return TRUE;
|
||||
{
|
||||
char* csv = CommandLineToCommaSeparatedValues(srcSize, src);
|
||||
*dst = CommandLineParseCommaSeparatedValues(csv, size);
|
||||
free(csv);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL pf_config_clone(proxyConfig** dst, const proxyConfig* config)
|
||||
{
|
||||
proxyConfig* tmp = calloc(1, sizeof(proxyConfig));
|
||||
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
|
||||
*tmp = *config;
|
||||
|
||||
if (!pf_config_copy_string(&tmp->Host, config->Host))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string(&tmp->TargetHost, config->TargetHost))
|
||||
goto fail;
|
||||
|
||||
if (!pf_config_copy_string_list(&tmp->Passthrough, &tmp->PassthroughCount, config->Passthrough,
|
||||
config->PassthroughCount))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string_list(&tmp->Modules, &tmp->ModulesCount, config->Modules,
|
||||
config->ModulesCount))
|
||||
goto fail;
|
||||
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))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string(&tmp->PrivateKeyFile, config->PrivateKeyFile))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string(&tmp->PrivateKeyContent, config->PrivateKeyContent))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string(&tmp->RdpKeyFile, config->RdpKeyFile))
|
||||
goto fail;
|
||||
if (!pf_config_copy_string(&tmp->RdpKeyContent, config->RdpKeyContent))
|
||||
goto fail;
|
||||
|
||||
*dst = tmp;
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
pf_server_config_free(tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
|
||||
*
|
||||
* 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_PFCONFIG_H
|
||||
#define FREERDP_SERVER_PROXY_PFCONFIG_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <winpr/ini.h>
|
||||
#include <winpr/path.h>
|
||||
|
||||
typedef struct proxy_config proxyConfig;
|
||||
|
||||
struct proxy_config
|
||||
{
|
||||
/* server */
|
||||
char* Host;
|
||||
UINT16 Port;
|
||||
|
||||
/* target */
|
||||
BOOL FixedTarget;
|
||||
char* TargetHost;
|
||||
UINT16 TargetPort;
|
||||
|
||||
/* input */
|
||||
BOOL Keyboard;
|
||||
BOOL Mouse;
|
||||
|
||||
/* server security */
|
||||
BOOL ServerTlsSecurity;
|
||||
BOOL ServerRdpSecurity;
|
||||
|
||||
/* client security */
|
||||
BOOL ClientNlaSecurity;
|
||||
BOOL ClientTlsSecurity;
|
||||
BOOL ClientRdpSecurity;
|
||||
BOOL ClientAllowFallbackToTls;
|
||||
|
||||
/* channels */
|
||||
BOOL GFX;
|
||||
BOOL DisplayControl;
|
||||
BOOL Clipboard;
|
||||
BOOL AudioOutput;
|
||||
BOOL RemoteApp;
|
||||
char** Passthrough;
|
||||
size_t PassthroughCount;
|
||||
|
||||
/* clipboard specific settings */
|
||||
BOOL TextOnly;
|
||||
UINT32 MaxTextLength;
|
||||
|
||||
/* gfx settings */
|
||||
BOOL DecodeGFX;
|
||||
|
||||
/* modules */
|
||||
char** Modules; /* module file names to load */
|
||||
size_t ModulesCount;
|
||||
|
||||
char** RequiredPlugins; /* required plugin names */
|
||||
size_t RequiredPluginsCount;
|
||||
};
|
||||
|
||||
typedef struct proxy_config proxyConfig;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
FREERDP_API BOOL pf_config_get_uint16(wIniFile* ini, const char* section, const char* key,
|
||||
UINT16* result);
|
||||
FREERDP_API BOOL pf_config_get_uint32(wIniFile* ini, const char* section, const char* key,
|
||||
UINT32* result);
|
||||
FREERDP_API BOOL pf_config_get_bool(wIniFile* ini, const char* section, const char* key);
|
||||
FREERDP_API const char* pf_config_get_str(wIniFile* ini, const char* section, const char* key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
proxyConfig* pf_server_config_load(const char* path);
|
||||
void pf_server_config_print(proxyConfig* config);
|
||||
void pf_server_config_free(proxyConfig* config);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFCONFIG_H */
|
@ -22,30 +22,18 @@
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_server.h>
|
||||
|
||||
#include "pf_client.h"
|
||||
#include "pf_context.h"
|
||||
|
||||
static wHashTable* create_channel_ids_map()
|
||||
{
|
||||
wHashTable* table = HashTable_New(TRUE);
|
||||
if (!table)
|
||||
return NULL;
|
||||
|
||||
if (!HashTable_SetupForStringData(table, FALSE))
|
||||
goto fail;
|
||||
|
||||
return table;
|
||||
fail:
|
||||
HashTable_Free(table);
|
||||
return NULL;
|
||||
}
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
/* Proxy context initialization callback */
|
||||
static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
|
||||
{
|
||||
pServerContext* context = (pServerContext*)ctx;
|
||||
proxyServer* server = (proxyServer*)client->ContextExtra;
|
||||
proxyConfig* config = server->config;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
context->dynvcReady = NULL;
|
||||
|
||||
@ -57,14 +45,6 @@ static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
|
||||
if (!(context->dynvcReady = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
goto error;
|
||||
|
||||
context->vc_handles = (HANDLE*)calloc(config->PassthroughCount, sizeof(HANDLE));
|
||||
if (!context->vc_handles)
|
||||
goto error;
|
||||
|
||||
context->vc_ids = create_channel_ids_map();
|
||||
if (!context->vc_ids)
|
||||
goto error;
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
@ -77,10 +57,6 @@ error:
|
||||
context->dynvcReady = NULL;
|
||||
}
|
||||
|
||||
free(context->vc_handles);
|
||||
context->vc_handles = NULL;
|
||||
HashTable_Free(context->vc_ids);
|
||||
context->vc_ids = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -99,13 +75,12 @@ static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx)
|
||||
CloseHandle(context->dynvcReady);
|
||||
context->dynvcReady = NULL;
|
||||
}
|
||||
|
||||
HashTable_Free(context->vc_ids);
|
||||
free(context->vc_handles);
|
||||
}
|
||||
|
||||
BOOL pf_context_init_server_context(freerdp_peer* client)
|
||||
{
|
||||
WINPR_ASSERT(client);
|
||||
|
||||
client->ContextSize = sizeof(pServerContext);
|
||||
client->ContextNew = client_to_proxy_context_new;
|
||||
client->ContextFree = client_to_proxy_context_free;
|
||||
@ -113,10 +88,33 @@ BOOL pf_context_init_server_context(freerdp_peer* client)
|
||||
return freerdp_peer_context_new(client);
|
||||
}
|
||||
|
||||
static BOOL pf_context_revert_str_settings(rdpSettings* dst, const rdpSettings* before, size_t nr,
|
||||
const size_t* ids)
|
||||
{
|
||||
size_t x;
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(before);
|
||||
WINPR_ASSERT(ids || (nr == 0));
|
||||
|
||||
for (x = 0; x < nr; x++)
|
||||
{
|
||||
size_t id = ids[x];
|
||||
const char* what = freerdp_settings_get_string(before, id);
|
||||
if (!freerdp_settings_set_string(dst, id, what))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
rdpSettings* before_copy;
|
||||
const size_t to_revert[] = { FreeRDP_ConfigPath, FreeRDP_PrivateKeyContent,
|
||||
FreeRDP_RdpKeyContent, FreeRDP_RdpKeyFile,
|
||||
FreeRDP_PrivateKeyFile, FreeRDP_CertificateFile,
|
||||
FreeRDP_CertificateName, FreeRDP_CertificateContent };
|
||||
|
||||
if (!dst || !src)
|
||||
return FALSE;
|
||||
@ -125,12 +123,6 @@ BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
|
||||
if (!before_copy)
|
||||
return FALSE;
|
||||
|
||||
#define REVERT_STR_VALUE(name) \
|
||||
free(dst->name); \
|
||||
dst->name = NULL; \
|
||||
if (before_copy->name && !(dst->name = _strdup(before_copy->name))) \
|
||||
goto out_fail
|
||||
|
||||
if (!freerdp_settings_copy(dst, src))
|
||||
{
|
||||
freerdp_settings_free(before_copy);
|
||||
@ -141,14 +133,8 @@ BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
|
||||
dst->ServerMode = before_copy->ServerMode;
|
||||
|
||||
/* revert some values that must not be changed */
|
||||
REVERT_STR_VALUE(ConfigPath);
|
||||
REVERT_STR_VALUE(PrivateKeyContent);
|
||||
REVERT_STR_VALUE(RdpKeyContent);
|
||||
REVERT_STR_VALUE(RdpKeyFile);
|
||||
REVERT_STR_VALUE(PrivateKeyFile);
|
||||
REVERT_STR_VALUE(CertificateFile);
|
||||
REVERT_STR_VALUE(CertificateName);
|
||||
REVERT_STR_VALUE(CertificateContent);
|
||||
if (!pf_context_revert_str_settings(dst, before_copy, ARRAYSIZE(to_revert), to_revert))
|
||||
return FALSE;
|
||||
|
||||
if (!dst->ServerMode)
|
||||
{
|
||||
@ -160,13 +146,13 @@ BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
|
||||
* it must be freed before setting it to NULL to avoid a memory leak!
|
||||
*/
|
||||
|
||||
free(dst->RdpServerRsaKey->Modulus);
|
||||
free(dst->RdpServerRsaKey->PrivateExponent);
|
||||
free(dst->RdpServerRsaKey);
|
||||
dst->RdpServerRsaKey = NULL;
|
||||
if (!freerdp_settings_set_pointer_len(dst, FreeRDP_RdpServerRsaKey, NULL,
|
||||
sizeof(rdpRsaKey)))
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
/* We handle certificate management for this client ourselfes. */
|
||||
rc = freerdp_settings_set_bool(dst, FreeRDP_ExternalCertificateManagement, TRUE);
|
||||
|
||||
out_fail:
|
||||
freerdp_settings_free(before_copy);
|
||||
@ -178,6 +164,9 @@ pClientContext* pf_context_create_client_context(rdpSettings* clientSettings)
|
||||
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
|
||||
pClientContext* pc;
|
||||
rdpContext* context;
|
||||
|
||||
WINPR_ASSERT(clientSettings);
|
||||
|
||||
RdpClientEntry(&clientEntryPoints);
|
||||
context = freerdp_client_context_new(&clientEntryPoints);
|
||||
|
||||
@ -189,10 +178,6 @@ pClientContext* pf_context_create_client_context(rdpSettings* clientSettings)
|
||||
if (!pf_context_copy_settings(context->settings, clientSettings))
|
||||
goto error;
|
||||
|
||||
pc->vc_ids = create_channel_ids_map();
|
||||
if (!pc->vc_ids)
|
||||
goto error;
|
||||
|
||||
return pc;
|
||||
error:
|
||||
freerdp_client_context_free(context);
|
||||
@ -240,6 +225,8 @@ error:
|
||||
/* updates circular pointers between proxyData and pClientContext instances */
|
||||
void proxy_data_set_client_context(proxyData* pdata, pClientContext* context)
|
||||
{
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(context);
|
||||
pdata->pc = context;
|
||||
context->pdata = pdata;
|
||||
}
|
||||
@ -247,29 +234,25 @@ void proxy_data_set_client_context(proxyData* pdata, pClientContext* context)
|
||||
/* updates circular pointers between proxyData and pServerContext instances */
|
||||
void proxy_data_set_server_context(proxyData* pdata, pServerContext* context)
|
||||
{
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(context);
|
||||
pdata->ps = context;
|
||||
context->pdata = pdata;
|
||||
}
|
||||
|
||||
void proxy_data_free(proxyData* pdata)
|
||||
{
|
||||
if (!pdata)
|
||||
return;
|
||||
|
||||
if (pdata->abort_event)
|
||||
{
|
||||
CloseHandle(pdata->abort_event);
|
||||
pdata->abort_event = NULL;
|
||||
}
|
||||
|
||||
if (pdata->client_thread)
|
||||
{
|
||||
CloseHandle(pdata->client_thread);
|
||||
pdata->client_thread = NULL;
|
||||
}
|
||||
|
||||
if (pdata->gfx_server_ready)
|
||||
{
|
||||
CloseHandle(pdata->gfx_server_ready);
|
||||
pdata->gfx_server_ready = NULL;
|
||||
}
|
||||
|
||||
if (pdata->modules_info)
|
||||
HashTable_Free(pdata->modules_info);
|
||||
@ -279,10 +262,14 @@ void proxy_data_free(proxyData* pdata)
|
||||
|
||||
void proxy_data_abort_connect(proxyData* pdata)
|
||||
{
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(pdata->abort_event);
|
||||
SetEvent(pdata->abort_event);
|
||||
}
|
||||
|
||||
BOOL proxy_data_shall_disconnect(proxyData* pdata)
|
||||
{
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(pdata->abort_event);
|
||||
return WaitForSingleObject(pdata->abort_event, 0) == WAIT_OBJECT_0;
|
||||
}
|
||||
|
@ -17,16 +17,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <freerdp/server/disp.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_disp.h"
|
||||
#include "pf_log.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)
|
||||
@ -41,8 +43,20 @@ BOOL pf_server_disp_init(pServerContext* ps)
|
||||
static UINT pf_disp_monitor_layout(DispServerContext* context,
|
||||
const DISPLAY_CONTROL_MONITOR_LAYOUT_PDU* pdu)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
DispClientContext* client = (DispClientContext*)pdata->pc->disp;
|
||||
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);
|
||||
}
|
||||
@ -50,9 +64,21 @@ static UINT pf_disp_monitor_layout(DispServerContext* context,
|
||||
static UINT pf_disp_on_caps_control(DispClientContext* context, UINT32 MaxNumMonitors,
|
||||
UINT32 MaxMonitorAreaFactorA, UINT32 MaxMonitorAreaFactorB)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
DispServerContext* server = (DispServerContext*)pdata->ps->disp;
|
||||
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;
|
||||
@ -64,6 +90,10 @@ static UINT pf_disp_on_caps_control(DispClientContext* context, UINT32 MaxNumMon
|
||||
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 */
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <freerdp/client/disp.h>
|
||||
#include <freerdp/server/disp.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
BOOL pf_server_disp_init(pServerContext* ps);
|
||||
void pf_disp_register_callbacks(DispClientContext* client, DispServerContext* server,
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
@ -30,39 +32,55 @@
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include "pf_gdi.h"
|
||||
#include "pf_log.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@ -70,42 +88,63 @@ static BOOL pf_gdi_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opa
|
||||
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;
|
||||
}
|
||||
@ -113,19 +152,30 @@ static BOOL pf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
|
||||
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 = update->primary;
|
||||
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;
|
||||
|
@ -24,13 +24,15 @@
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_graphics.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_gdi.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
#include <freerdp/gdi/dc.h>
|
||||
#include <freerdp/gdi/shape.h>
|
||||
@ -44,105 +46,139 @@
|
||||
/* 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 = NULL;
|
||||
rdpPointer pointer = { 0 };
|
||||
|
||||
if (!(pointer = (rdpPointer*)calloc(1, sizeof(rdpPointer))))
|
||||
return FALSE;
|
||||
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);
|
||||
free(pointer);
|
||||
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;
|
||||
rdpGlyph glyph;
|
||||
rdpBitmap bitmap = { 0 };
|
||||
rdpGlyph glyph = { 0 };
|
||||
|
||||
if (!graphics || !graphics->Bitmap_Prototype || !graphics->Glyph_Prototype)
|
||||
return FALSE;
|
||||
@ -155,6 +191,7 @@ BOOL pf_register_graphics(rdpGraphics* graphics)
|
||||
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;
|
||||
|
@ -19,23 +19,46 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include "pf_input.h"
|
||||
#include "pf_context.h"
|
||||
#include "pf_modules.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
#include "proxy_modules.h"
|
||||
|
||||
static BOOL pf_server_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
ps = (pServerContext*)input->context;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
pc = ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
return freerdp_input_send_synchronize_event(pc->context.input, flags);
|
||||
}
|
||||
|
||||
static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
const proxyConfig* config;
|
||||
proxyKeyboardEventInfo event;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
ps = (pServerContext*)input->context;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
pc = ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
config = ps->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!config->Keyboard)
|
||||
return TRUE;
|
||||
@ -43,7 +66,7 @@ static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
event.flags = flags;
|
||||
event.rdp_scan_code = code;
|
||||
|
||||
if (pf_modules_run_filter(FILTER_TYPE_KEYBOARD, pc->pdata, &event))
|
||||
if (pf_modules_run_filter(pc->pdata->module, FILTER_TYPE_KEYBOARD, pc->pdata, &event))
|
||||
return freerdp_input_send_keyboard_event(pc->context.input, flags, code);
|
||||
|
||||
return TRUE;
|
||||
@ -51,9 +74,20 @@ static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
|
||||
static BOOL pf_server_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
const proxyConfig* config;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
ps = (pServerContext*)input->context;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
pc = ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
config = ps->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!config->Keyboard)
|
||||
return TRUE;
|
||||
@ -63,10 +97,21 @@ static BOOL pf_server_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT
|
||||
|
||||
static BOOL pf_server_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
proxyMouseEventInfo event;
|
||||
const proxyConfig* config;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
ps = (pServerContext*)input->context;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
pc = ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
config = ps->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!config->Mouse)
|
||||
return TRUE;
|
||||
@ -75,7 +120,7 @@ static BOOL pf_server_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
|
||||
event.x = x;
|
||||
event.y = y;
|
||||
|
||||
if (pf_modules_run_filter(FILTER_TYPE_MOUSE, pc->pdata, &event))
|
||||
if (pf_modules_run_filter(pc->pdata->module, FILTER_TYPE_MOUSE, pc->pdata, &event))
|
||||
return freerdp_input_send_mouse_event(pc->context.input, flags, x, y);
|
||||
|
||||
return TRUE;
|
||||
@ -83,9 +128,20 @@ static BOOL pf_server_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
|
||||
|
||||
static BOOL pf_server_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
const proxyConfig* config;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
WINPR_ASSERT(input);
|
||||
ps = (pServerContext*)input->context;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
pc = ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
|
||||
config = ps->pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
if (!config->Mouse)
|
||||
return TRUE;
|
||||
@ -95,6 +151,8 @@ static BOOL pf_server_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16
|
||||
|
||||
void pf_server_register_input_callbacks(rdpInput* input)
|
||||
{
|
||||
WINPR_ASSERT(input);
|
||||
|
||||
input->SynchronizeEvent = pf_server_synchronize_event;
|
||||
input->KeyboardEvent = pf_server_keyboard_event;
|
||||
input->UnicodeKeyboardEvent = pf_server_unicode_keyboard_event;
|
||||
|
@ -22,22 +22,27 @@
|
||||
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/library.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/build-config.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_modules.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
#include <freerdp/server/proxy/proxy_modules_api.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "proxy_modules.h"
|
||||
|
||||
#define TAG PROXY_TAG("modules")
|
||||
|
||||
#define MODULE_ENTRY_POINT "proxy_module_entry_point"
|
||||
|
||||
static wArrayList* plugins_list = NULL; /* list of all loaded plugins */
|
||||
static wArrayList* handles_list = NULL; /* list of module handles to free at shutdown */
|
||||
|
||||
typedef BOOL (*moduleEntryPoint)(proxyPluginsManager* plugins_manager);
|
||||
struct proxy_module
|
||||
{
|
||||
proxyPluginsManager mgr;
|
||||
wArrayList* plugins;
|
||||
wArrayList* handles;
|
||||
};
|
||||
|
||||
static const char* FILTER_TYPE_STRINGS[] = { "KEYBOARD_EVENT", "MOUSE_EVENT", "CLIENT_CHANNEL_DATA",
|
||||
"SERVER_CHANNEL_DATA", "SERVER_FETCH_TARGET_ADDR" };
|
||||
@ -68,45 +73,67 @@ static BOOL pf_modules_proxy_ArrayList_ForEachFkt(void* data, size_t index, va_l
|
||||
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||
PF_HOOK_TYPE type;
|
||||
proxyData* pdata;
|
||||
void* custom;
|
||||
BOOL ok = FALSE;
|
||||
|
||||
WINPR_UNUSED(index);
|
||||
|
||||
type = va_arg(ap, PF_HOOK_TYPE);
|
||||
pdata = va_arg(ap, proxyData*);
|
||||
custom = va_arg(ap, void*);
|
||||
|
||||
WLog_VRB(TAG, "running hook %s.%s", plugin->name, pf_modules_get_hook_type_string(type));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case HOOK_TYPE_CLIENT_INIT_CONNECT:
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientInitConnect, plugin, pdata, custom);
|
||||
break;
|
||||
case HOOK_TYPE_CLIENT_UNINIT_CONNECT:
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientUninitConnect, plugin, pdata, custom);
|
||||
break;
|
||||
case HOOK_TYPE_CLIENT_PRE_CONNECT:
|
||||
IFCALLRET(plugin->ClientPreConnect, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientPreConnect, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_CLIENT_POST_CONNECT:
|
||||
IFCALLRET(plugin->ClientPostConnect, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientPostConnect, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_CLIENT_POST_DISCONNECT:
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientPostDisconnect, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_CLIENT_VERIFY_X509:
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientX509Certificate, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_CLIENT_LOGIN_FAILURE:
|
||||
IFCALLRET(plugin->ClientLoginFailure, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientLoginFailure, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_CLIENT_END_PAINT:
|
||||
IFCALLRET(plugin->ClientEndPaint, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ClientEndPaint, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_SERVER_POST_CONNECT:
|
||||
IFCALLRET(plugin->ServerPostConnect, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ServerPostConnect, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_SERVER_ACTIVATE:
|
||||
ok = IFCALLRESULT(TRUE, plugin->ServerPeerActivate, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_SERVER_CHANNELS_INIT:
|
||||
IFCALLRET(plugin->ServerChannelsInit, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ServerChannelsInit, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_SERVER_CHANNELS_FREE:
|
||||
IFCALLRET(plugin->ServerChannelsFree, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ServerChannelsFree, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_TYPE_SERVER_SESSION_END:
|
||||
IFCALLRET(plugin->ServerSessionEnd, ok, pdata);
|
||||
ok = IFCALLRESULT(TRUE, plugin->ServerSessionEnd, plugin, pdata, custom);
|
||||
break;
|
||||
|
||||
case HOOK_LAST:
|
||||
@ -129,9 +156,12 @@ static BOOL pf_modules_proxy_ArrayList_ForEachFkt(void* data, size_t index, va_l
|
||||
* @type: hook type to run.
|
||||
* @server: pointer of server's rdpContext struct of the current session.
|
||||
*/
|
||||
BOOL pf_modules_run_hook(PF_HOOK_TYPE type, proxyData* pdata)
|
||||
BOOL pf_modules_run_hook(proxyModule* module, PF_HOOK_TYPE type, proxyData* pdata, void* custom)
|
||||
{
|
||||
return ArrayList_ForEach(plugins_list, pf_modules_proxy_ArrayList_ForEachFkt, type, pdata);
|
||||
WINPR_ASSERT(module);
|
||||
WINPR_ASSERT(module->plugins);
|
||||
return ArrayList_ForEach(module->plugins, pf_modules_proxy_ArrayList_ForEachFkt, type, pdata,
|
||||
custom);
|
||||
}
|
||||
|
||||
static BOOL pf_modules_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||
@ -153,23 +183,31 @@ static BOOL pf_modules_ArrayList_ForEachFkt(void* data, size_t index, va_list ap
|
||||
switch (type)
|
||||
{
|
||||
case FILTER_TYPE_KEYBOARD:
|
||||
IFCALLRET(plugin->KeyboardEvent, result, pdata, param);
|
||||
result = IFCALLRESULT(TRUE, plugin->KeyboardEvent, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_MOUSE:
|
||||
IFCALLRET(plugin->MouseEvent, result, pdata, param);
|
||||
result = IFCALLRESULT(TRUE, plugin->MouseEvent, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA:
|
||||
IFCALLRET(plugin->ClientChannelData, result, pdata, param);
|
||||
result = IFCALLRESULT(TRUE, plugin->ClientChannelData, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA:
|
||||
IFCALLRET(plugin->ServerChannelData, result, pdata, param);
|
||||
result = IFCALLRESULT(TRUE, plugin->ServerChannelData, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE:
|
||||
result = IFCALLRESULT(TRUE, plugin->DynamicChannelCreate, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_SERVER_FETCH_TARGET_ADDR:
|
||||
IFCALLRET(plugin->ServerFetchTargetAddr, result, pdata, param);
|
||||
result = IFCALLRESULT(TRUE, plugin->ServerFetchTargetAddr, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_SERVER_PEER_LOGON:
|
||||
result = IFCALLRESULT(TRUE, plugin->ServerPeerLogon, plugin, pdata, param);
|
||||
break;
|
||||
|
||||
case FILTER_LAST:
|
||||
@ -192,10 +230,12 @@ static BOOL pf_modules_ArrayList_ForEachFkt(void* data, size_t index, va_list ap
|
||||
* @type: filter type to run.
|
||||
* @server: pointer of server's rdpContext struct of the current session.
|
||||
*/
|
||||
BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param)
|
||||
BOOL pf_modules_run_filter(proxyModule* module, PF_FILTER_TYPE type, proxyData* pdata, void* param)
|
||||
{
|
||||
WINPR_ASSERT(module);
|
||||
WINPR_ASSERT(module->plugins);
|
||||
|
||||
return ArrayList_ForEach(plugins_list, pf_modules_ArrayList_ForEachFkt, type, pdata, param);
|
||||
return ArrayList_ForEach(module->plugins, pf_modules_ArrayList_ForEachFkt, type, pdata, param);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -204,7 +244,8 @@ BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param)
|
||||
* @context: current session server's rdpContext instance.
|
||||
* @info: pointer to per-session data.
|
||||
*/
|
||||
static BOOL pf_modules_set_plugin_data(const char* plugin_name, proxyData* pdata, void* data)
|
||||
static BOOL pf_modules_set_plugin_data(proxyPluginsManager* mgr, const char* plugin_name,
|
||||
proxyData* pdata, void* data)
|
||||
{
|
||||
union {
|
||||
const char* ccp;
|
||||
@ -233,7 +274,8 @@ static BOOL pf_modules_set_plugin_data(const char* plugin_name, proxyData* pdata
|
||||
* if there's no data related to `plugin_name` in `context` (current session), a NULL will be
|
||||
* returned.
|
||||
*/
|
||||
static void* pf_modules_get_plugin_data(const char* plugin_name, proxyData* pdata)
|
||||
static void* pf_modules_get_plugin_data(proxyPluginsManager* mgr, const char* plugin_name,
|
||||
proxyData* pdata)
|
||||
{
|
||||
union {
|
||||
const char* ccp;
|
||||
@ -246,7 +288,7 @@ static void* pf_modules_get_plugin_data(const char* plugin_name, proxyData* pdat
|
||||
return HashTable_GetItemValue(pdata->modules_info, ccharconv.cp);
|
||||
}
|
||||
|
||||
static void pf_modules_abort_connect(proxyData* pdata)
|
||||
static void pf_modules_abort_connect(proxyPluginsManager* mgr, proxyData* pdata)
|
||||
{
|
||||
WINPR_ASSERT(pdata);
|
||||
WLog_DBG(TAG, "%s is called!", __FUNCTION__);
|
||||
@ -268,17 +310,24 @@ static BOOL pf_modules_register_ArrayList_ForEachFkt(void* data, size_t index, v
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_modules_register_plugin(proxyPlugin* plugin_to_register)
|
||||
static BOOL pf_modules_register_plugin(proxyPluginsManager* mgr,
|
||||
const proxyPlugin* plugin_to_register)
|
||||
{
|
||||
proxyPlugin internal = { 0 };
|
||||
proxyModule* module = (proxyModule*)mgr;
|
||||
WINPR_ASSERT(module);
|
||||
|
||||
if (!plugin_to_register)
|
||||
return FALSE;
|
||||
|
||||
internal = *plugin_to_register;
|
||||
internal.mgr = mgr;
|
||||
|
||||
/* make sure there's no other loaded plugin with the same name of `plugin_to_register`. */
|
||||
if (!ArrayList_ForEach(plugins_list, pf_modules_register_ArrayList_ForEachFkt,
|
||||
plugin_to_register))
|
||||
if (!ArrayList_ForEach(module->plugins, pf_modules_register_ArrayList_ForEachFkt, &internal))
|
||||
return FALSE;
|
||||
|
||||
if (!ArrayList_Append(plugins_list, plugin_to_register))
|
||||
if (!ArrayList_Append(module->plugins, &internal))
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: failed adding plugin to list: %s", __FUNCTION__,
|
||||
plugin_to_register->name);
|
||||
@ -301,12 +350,12 @@ static BOOL pf_modules_load_ArrayList_ForEachFkt(void* data, size_t index, va_li
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL pf_modules_is_plugin_loaded(const char* plugin_name)
|
||||
BOOL pf_modules_is_plugin_loaded(proxyModule* module, const char* plugin_name)
|
||||
{
|
||||
if (plugins_list == NULL)
|
||||
WINPR_ASSERT(module);
|
||||
if (ArrayList_Count(module->plugins) < 1)
|
||||
return FALSE;
|
||||
|
||||
return ArrayList_ForEach(plugins_list, pf_modules_load_ArrayList_ForEachFkt, plugin_name);
|
||||
return ArrayList_ForEach(module->plugins, pf_modules_load_ArrayList_ForEachFkt, plugin_name);
|
||||
}
|
||||
|
||||
static BOOL pf_modules_print_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||
@ -321,31 +370,28 @@ static BOOL pf_modules_print_ArrayList_ForEachFkt(void* data, size_t index, va_l
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void pf_modules_list_loaded_plugins(void)
|
||||
void pf_modules_list_loaded_plugins(proxyModule* module)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
if (plugins_list == NULL)
|
||||
return;
|
||||
WINPR_ASSERT(module);
|
||||
WINPR_ASSERT(module->plugins);
|
||||
|
||||
count = (size_t)ArrayList_Count(plugins_list);
|
||||
count = ArrayList_Count(module->plugins);
|
||||
|
||||
if (count > 0)
|
||||
WLog_INFO(TAG, "Loaded plugins:");
|
||||
|
||||
ArrayList_ForEach(plugins_list, pf_modules_print_ArrayList_ForEachFkt);
|
||||
ArrayList_ForEach(module->plugins, pf_modules_print_ArrayList_ForEachFkt);
|
||||
}
|
||||
|
||||
static proxyPluginsManager plugins_manager = { pf_modules_register_plugin,
|
||||
pf_modules_set_plugin_data,
|
||||
pf_modules_get_plugin_data,
|
||||
pf_modules_abort_connect };
|
||||
|
||||
static BOOL pf_modules_load_module(const char* module_path)
|
||||
static BOOL pf_modules_load_module(const char* module_path, proxyModule* module, void* userdata)
|
||||
{
|
||||
HMODULE handle = NULL;
|
||||
moduleEntryPoint pEntryPoint;
|
||||
handle = LoadLibraryA(module_path);
|
||||
proxyModuleEntryPoint pEntryPoint;
|
||||
WINPR_ASSERT(module);
|
||||
|
||||
handle = LoadLibraryX(module_path);
|
||||
|
||||
if (handle == NULL)
|
||||
{
|
||||
@ -353,118 +399,142 @@ static BOOL pf_modules_load_module(const char* module_path)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(pEntryPoint = (moduleEntryPoint)GetProcAddress(handle, MODULE_ENTRY_POINT)))
|
||||
pEntryPoint = (proxyModuleEntryPoint)GetProcAddress(handle, MODULE_ENTRY_POINT);
|
||||
if (!pEntryPoint)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: GetProcAddress failed while loading %s", __FUNCTION__, module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!pEntryPoint(&plugins_manager))
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: module %s entry point failed!", __FUNCTION__, module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* save module handle for freeing the module later */
|
||||
if (!ArrayList_Append(handles_list, handle))
|
||||
if (!ArrayList_Append(module->handles, handle))
|
||||
{
|
||||
WLog_ERR(TAG, "ArrayList_Append failed!");
|
||||
return FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return pf_modules_add(module, pEntryPoint, userdata);
|
||||
|
||||
error:
|
||||
FreeLibrary(handle);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL pf_modules_init(const char* root_dir, const char** modules, size_t count)
|
||||
static void free_handle(void* obj)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!PathFileExistsA(root_dir))
|
||||
{
|
||||
if (!CreateDirectoryA(root_dir, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "error occurred while creating modules directory: %s", root_dir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "modules root directory: %s", root_dir);
|
||||
|
||||
plugins_list = ArrayList_New(FALSE);
|
||||
|
||||
if (plugins_list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s]: ArrayList_New failed!", __FUNCTION__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
handles_list = ArrayList_New(FALSE);
|
||||
if (handles_list == NULL)
|
||||
{
|
||||
|
||||
WLog_ERR(TAG, "[%s]: ArrayList_New failed!", __FUNCTION__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
char* fullpath = GetCombinedPath(root_dir, modules[i]);
|
||||
pf_modules_load_module(fullpath);
|
||||
free(fullpath);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
ArrayList_Free(plugins_list);
|
||||
plugins_list = NULL;
|
||||
ArrayList_Free(handles_list);
|
||||
handles_list = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL pf_modules_free_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||
{
|
||||
proxyPlugin* plugin = (proxyPlugin*)data;
|
||||
|
||||
WINPR_UNUSED(index);
|
||||
WINPR_UNUSED(ap);
|
||||
|
||||
if (!IFCALLRESULT(TRUE, plugin->PluginUnload))
|
||||
WLog_WARN(TAG, "PluginUnload failed for plugin '%s'", plugin->name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_modules_free_handles_ArrayList_ForEachFkt(void* data, size_t index, va_list ap)
|
||||
{
|
||||
HANDLE handle = (HANDLE)data;
|
||||
|
||||
WINPR_UNUSED(index);
|
||||
WINPR_UNUSED(ap);
|
||||
HANDLE handle = (HANDLE)obj;
|
||||
if (handle)
|
||||
FreeLibrary(handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void pf_modules_free(void)
|
||||
static void free_plugin(void* obj)
|
||||
{
|
||||
if (plugins_list)
|
||||
proxyPlugin* plugin = (proxyPlugin*)obj;
|
||||
WINPR_ASSERT(plugin);
|
||||
|
||||
if (!IFCALLRESULT(TRUE, plugin->PluginUnload, plugin))
|
||||
WLog_WARN(TAG, "PluginUnload failed for plugin '%s'", plugin->name);
|
||||
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void* new_plugin(const void* obj)
|
||||
{
|
||||
const proxyPlugin* src = obj;
|
||||
proxyPlugin* proxy = calloc(1, sizeof(proxyPlugin));
|
||||
if (!proxy)
|
||||
return NULL;
|
||||
*proxy = *src;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
proxyModule* pf_modules_new(const char* root_dir, const char** modules, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
wObject* obj;
|
||||
char* path = NULL;
|
||||
proxyModule* module = calloc(1, sizeof(proxyModule));
|
||||
if (!module)
|
||||
return NULL;
|
||||
|
||||
module->mgr.RegisterPlugin = pf_modules_register_plugin;
|
||||
module->mgr.SetPluginData = pf_modules_set_plugin_data;
|
||||
module->mgr.GetPluginData = pf_modules_get_plugin_data;
|
||||
module->mgr.AbortConnect = pf_modules_abort_connect;
|
||||
module->plugins = ArrayList_New(FALSE);
|
||||
|
||||
if (module->plugins == NULL)
|
||||
{
|
||||
ArrayList_ForEach(plugins_list, pf_modules_free_ArrayList_ForEachFkt);
|
||||
ArrayList_Free(plugins_list);
|
||||
plugins_list = NULL;
|
||||
WLog_ERR(TAG, "[%s]: ArrayList_New failed!", __FUNCTION__);
|
||||
goto error;
|
||||
}
|
||||
obj = ArrayList_Object(module->plugins);
|
||||
WINPR_ASSERT(obj);
|
||||
|
||||
obj->fnObjectFree = free_plugin;
|
||||
obj->fnObjectNew = new_plugin;
|
||||
|
||||
module->handles = ArrayList_New(FALSE);
|
||||
if (module->handles == NULL)
|
||||
{
|
||||
|
||||
WLog_ERR(TAG, "[%s]: ArrayList_New failed!", __FUNCTION__);
|
||||
goto error;
|
||||
}
|
||||
ArrayList_Object(module->handles)->fnObjectFree = free_handle;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
WINPR_ASSERT(root_dir);
|
||||
if (!winpr_PathFileExists(root_dir))
|
||||
path = GetCombinedPath(FREERDP_INSTALL_PREFIX, root_dir);
|
||||
else
|
||||
path = _strdup(root_dir);
|
||||
|
||||
if (!winpr_PathFileExists(path))
|
||||
{
|
||||
if (!winpr_PathMakePath(path, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "error occurred while creating modules directory: %s", root_dir);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (winpr_PathFileExists(path))
|
||||
WLog_DBG(TAG, "modules root directory: %s", path);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
char name[8192] = { 0 };
|
||||
char* fullpath;
|
||||
_snprintf(name, sizeof(name), "proxy-%s-plugin%s", modules[i],
|
||||
FREERDP_SHARED_LIBRARY_SUFFIX);
|
||||
fullpath = GetCombinedPath(path, name);
|
||||
pf_modules_load_module(fullpath, module, NULL);
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
|
||||
if (handles_list)
|
||||
{
|
||||
ArrayList_ForEach(handles_list, pf_modules_free_handles_ArrayList_ForEachFkt);
|
||||
ArrayList_Free(handles_list);
|
||||
handles_list = NULL;
|
||||
}
|
||||
free(path);
|
||||
return module;
|
||||
|
||||
error:
|
||||
free(path);
|
||||
pf_modules_free(module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pf_modules_free(proxyModule* module)
|
||||
{
|
||||
if (!module)
|
||||
return;
|
||||
|
||||
ArrayList_Free(module->plugins);
|
||||
ArrayList_Free(module->handles);
|
||||
free(module);
|
||||
}
|
||||
|
||||
BOOL pf_modules_add(proxyModule* module, proxyModuleEntryPoint ep, void* userdata)
|
||||
{
|
||||
WINPR_ASSERT(module);
|
||||
WINPR_ASSERT(ep);
|
||||
|
||||
return ep(&module->mgr, userdata);
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
|
||||
*
|
||||
* 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_MODULES_H
|
||||
#define FREERDP_SERVER_PROXY_MODULES_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "modules/modules_api.h"
|
||||
|
||||
enum _PF_FILTER_TYPE
|
||||
{
|
||||
FILTER_TYPE_KEYBOARD,
|
||||
FILTER_TYPE_MOUSE,
|
||||
FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA,
|
||||
|
||||
FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA,
|
||||
FILTER_TYPE_SERVER_FETCH_TARGET_ADDR,
|
||||
|
||||
FILTER_LAST
|
||||
};
|
||||
typedef enum _PF_FILTER_TYPE PF_FILTER_TYPE;
|
||||
|
||||
enum _PF_HOOK_TYPE
|
||||
{
|
||||
HOOK_TYPE_CLIENT_PRE_CONNECT,
|
||||
HOOK_TYPE_CLIENT_POST_CONNECT,
|
||||
HOOK_TYPE_CLIENT_LOGIN_FAILURE,
|
||||
HOOK_TYPE_CLIENT_END_PAINT,
|
||||
|
||||
HOOK_TYPE_SERVER_POST_CONNECT,
|
||||
HOOK_TYPE_SERVER_CHANNELS_INIT,
|
||||
HOOK_TYPE_SERVER_CHANNELS_FREE,
|
||||
HOOK_TYPE_SERVER_SESSION_END,
|
||||
|
||||
HOOK_LAST
|
||||
};
|
||||
typedef enum _PF_HOOK_TYPE PF_HOOK_TYPE;
|
||||
|
||||
BOOL pf_modules_init(const char* root_dir, const char** modules, size_t count);
|
||||
BOOL pf_modules_is_plugin_loaded(const char* plugin_name);
|
||||
void pf_modules_list_loaded_plugins(void);
|
||||
|
||||
BOOL pf_modules_run_filter(PF_FILTER_TYPE type, proxyData* pdata, void* param);
|
||||
BOOL pf_modules_run_hook(PF_HOOK_TYPE type, proxyData* pdata);
|
||||
|
||||
void pf_modules_free(void);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_MODULES_H */
|
@ -19,18 +19,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/client/rail.h>
|
||||
#include <freerdp/server/rail.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_rail.h"
|
||||
#include "pf_context.h"
|
||||
#include "pf_log.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
#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)
|
||||
@ -53,6 +58,9 @@ BOOL pf_rail_context_init(pServerContext* ps)
|
||||
|
||||
static UINT pf_rail_client_on_open(RailClientContext* context, BOOL* sendHandshake)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(sendHandshake);
|
||||
|
||||
if (NULL != sendHandshake)
|
||||
*sendHandshake = FALSE;
|
||||
|
||||
@ -63,8 +71,20 @@ static UINT pf_rail_client_on_open(RailClientContext* context, BOOL* sendHandsha
|
||||
static UINT pf_rail_server_handshake(RailClientContext* client,
|
||||
const RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -72,16 +92,40 @@ static UINT pf_rail_server_handshake(RailClientContext* client,
|
||||
static UINT pf_rail_server_handshake_ex(RailClientContext* client,
|
||||
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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 = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -89,8 +133,20 @@ static UINT pf_rail_server_sysparam(RailClientContext* client, const RAIL_SYSPAR
|
||||
static UINT pf_rail_server_local_move_size(RailClientContext* client,
|
||||
const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -98,8 +154,20 @@ static UINT pf_rail_server_local_move_size(RailClientContext* client,
|
||||
static UINT pf_rail_server_min_max_info(RailClientContext* client,
|
||||
const RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -107,8 +175,20 @@ static UINT pf_rail_server_min_max_info(RailClientContext* client,
|
||||
static UINT pf_rail_server_taskbar_info(RailClientContext* client,
|
||||
const RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -116,8 +196,20 @@ static UINT pf_rail_server_taskbar_info(RailClientContext* client,
|
||||
static UINT pf_rail_server_langbar_info(RailClientContext* client,
|
||||
const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -125,8 +217,20 @@ static UINT pf_rail_server_langbar_info(RailClientContext* client,
|
||||
static UINT pf_rail_server_exec_result(RailClientContext* client,
|
||||
const RAIL_EXEC_RESULT_ORDER* execResult)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -134,16 +238,40 @@ static UINT pf_rail_server_exec_result(RailClientContext* client,
|
||||
static UINT pf_rail_server_z_order_sync(RailClientContext* client,
|
||||
const RAIL_ZORDER_SYNC* zOrderSync)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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 = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -152,8 +280,20 @@ static UINT
|
||||
pf_rail_server_power_display_request(RailClientContext* client,
|
||||
const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -161,8 +301,20 @@ pf_rail_server_power_display_request(RailClientContext* client,
|
||||
static UINT pf_rail_server_get_appid_resp(RailClientContext* client,
|
||||
const RAIL_GET_APPID_RESP_ORDER* getAppidResp)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -170,8 +322,20 @@ static UINT pf_rail_server_get_appid_resp(RailClientContext* client,
|
||||
static UINT pf_rail_server_get_appid_resp_ex(RailClientContext* client,
|
||||
const RAIL_GET_APPID_RESP_EX* getAppidRespEx)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)client->custom;
|
||||
RailServerContext* server = (RailServerContext*)pdata->ps->rail;
|
||||
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);
|
||||
}
|
||||
@ -181,8 +345,20 @@ static UINT pf_rail_server_get_appid_resp_ex(RailClientContext* client,
|
||||
static UINT pf_rail_client_handshake(RailServerContext* server,
|
||||
const RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -190,40 +366,100 @@ static UINT pf_rail_client_handshake(RailServerContext* server,
|
||||
static UINT pf_rail_client_client_status(RailServerContext* server,
|
||||
const RAIL_CLIENT_STATUS_ORDER* clientStatus)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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 = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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 = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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 = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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 = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -231,8 +467,20 @@ static UINT pf_rail_client_sysmenu(RailServerContext* server, const RAIL_SYSMENU
|
||||
static UINT pf_rail_client_syscommand(RailServerContext* server,
|
||||
const RAIL_SYSCOMMAND_ORDER* syscommand)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -240,8 +488,20 @@ static UINT pf_rail_client_syscommand(RailServerContext* server,
|
||||
static UINT pf_rail_client_notify_event(RailServerContext* server,
|
||||
const RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -249,8 +509,20 @@ static UINT pf_rail_client_notify_event(RailServerContext* server,
|
||||
static UINT pf_rail_client_window_move(RailServerContext* server,
|
||||
const RAIL_WINDOW_MOVE_ORDER* windowMove)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -258,8 +530,20 @@ static UINT pf_rail_client_window_move(RailServerContext* server,
|
||||
static UINT pf_rail_client_snap_arrange(RailServerContext* server,
|
||||
const RAIL_SNAP_ARRANGE* snapArrange)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -267,8 +551,20 @@ static UINT pf_rail_client_snap_arrange(RailServerContext* server,
|
||||
static UINT pf_rail_client_get_appid_req(RailServerContext* server,
|
||||
const RAIL_GET_APPID_REQ_ORDER* getAppidReq)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -276,8 +572,20 @@ static UINT pf_rail_client_get_appid_req(RailServerContext* server,
|
||||
static UINT pf_rail_client_langbar_info(RailServerContext* server,
|
||||
const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -285,8 +593,20 @@ static UINT pf_rail_client_langbar_info(RailServerContext* server,
|
||||
static UINT pf_rail_client_language_ime_info(RailServerContext* server,
|
||||
const RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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);
|
||||
}
|
||||
@ -294,20 +614,49 @@ static UINT pf_rail_client_language_ime_info(RailServerContext* server,
|
||||
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 = (proxyData*)server->custom;
|
||||
RailClientContext* client = (RailClientContext*)pdata->pc->rail;
|
||||
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;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <freerdp/client/rail.h>
|
||||
#include <freerdp/server/rail.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
BOOL pf_rail_context_init(pServerContext* ps);
|
||||
void pf_rail_pipeline_init(RailClientContext* client, RailServerContext* server, proxyData* pdata);
|
||||
|
@ -21,18 +21,22 @@
|
||||
|
||||
#include <freerdp/client/rdpgfx.h>
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include "pf_rdpgfx.h"
|
||||
#include "pf_context.h"
|
||||
#include "pf_log.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
#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)
|
||||
@ -48,10 +52,26 @@ static UINT pf_rdpgfx_reset_graphics(RdpgfxClientContext* context,
|
||||
const RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -60,6 +80,9 @@ static UINT pf_rdpgfx_reset_graphics(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -67,10 +90,26 @@ static UINT pf_rdpgfx_start_frame(RdpgfxClientContext* context,
|
||||
const RDPGFX_START_FRAME_PDU* startFrame)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -79,16 +118,35 @@ static UINT pf_rdpgfx_start_frame(RdpgfxClientContext* context,
|
||||
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 = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -97,6 +155,9 @@ static UINT pf_rdpgfx_end_frame(RdpgfxClientContext* context, const RDPGFX_END_F
|
||||
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);
|
||||
}
|
||||
|
||||
@ -104,10 +165,26 @@ static UINT pf_rdpgfx_surface_command(RdpgfxClientContext* context,
|
||||
const RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -116,6 +193,9 @@ static UINT pf_rdpgfx_surface_command(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -124,10 +204,26 @@ pf_rdpgfx_delete_encoding_context(RdpgfxClientContext* context,
|
||||
const RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -136,6 +232,9 @@ pf_rdpgfx_delete_encoding_context(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -143,10 +242,26 @@ static UINT pf_rdpgfx_create_surface(RdpgfxClientContext* context,
|
||||
const RDPGFX_CREATE_SURFACE_PDU* createSurface)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -155,6 +270,9 @@ static UINT pf_rdpgfx_create_surface(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -162,10 +280,26 @@ static UINT pf_rdpgfx_delete_surface(RdpgfxClientContext* context,
|
||||
const RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -174,6 +308,9 @@ static UINT pf_rdpgfx_delete_surface(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -181,10 +318,26 @@ static UINT pf_rdpgfx_solid_fill(RdpgfxClientContext* context,
|
||||
const RDPGFX_SOLID_FILL_PDU* solidFill)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -193,6 +346,9 @@ static UINT pf_rdpgfx_solid_fill(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -200,10 +356,26 @@ static UINT pf_rdpgfx_surface_to_surface(RdpgfxClientContext* context,
|
||||
const RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -212,6 +384,9 @@ static UINT pf_rdpgfx_surface_to_surface(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -219,10 +394,26 @@ static UINT pf_rdpgfx_surface_to_cache(RdpgfxClientContext* context,
|
||||
const RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -231,6 +422,9 @@ static UINT pf_rdpgfx_surface_to_cache(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -238,10 +432,26 @@ static UINT pf_rdpgfx_cache_to_surface(RdpgfxClientContext* context,
|
||||
const RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -250,14 +460,30 @@ static UINT pf_rdpgfx_cache_to_surface(RdpgfxClientContext* context,
|
||||
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 = (proxyData*)context->custom;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
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);
|
||||
}
|
||||
@ -266,10 +492,26 @@ static UINT pf_rdpgfx_evict_cache_entry(RdpgfxClientContext* context,
|
||||
const RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -278,6 +520,9 @@ static UINT pf_rdpgfx_evict_cache_entry(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -285,10 +530,26 @@ static UINT pf_rdpgfx_map_surface_to_output(RdpgfxClientContext* context,
|
||||
const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -297,6 +558,9 @@ static UINT pf_rdpgfx_map_surface_to_output(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -304,10 +568,26 @@ static UINT pf_rdpgfx_map_surface_to_window(RdpgfxClientContext* context,
|
||||
const RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -316,6 +596,9 @@ static UINT pf_rdpgfx_map_surface_to_window(RdpgfxClientContext* context,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -324,10 +607,26 @@ static UINT pf_rdpgfx_map_surface_to_scaled_window(
|
||||
const RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* surfaceToScaledWindow)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -336,6 +635,9 @@ static UINT pf_rdpgfx_map_surface_to_scaled_window(
|
||||
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);
|
||||
}
|
||||
|
||||
@ -344,10 +646,26 @@ static UINT pf_rdpgfx_map_surface_to_scaled_output(
|
||||
const RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToScaledOutput)
|
||||
{
|
||||
UINT error;
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
proxyConfig* config = pdata->config;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
RdpgfxClientContext* gfx_decoder = pdata->pc->gfx_decoder;
|
||||
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)))
|
||||
@ -356,13 +674,25 @@ static UINT pf_rdpgfx_map_surface_to_scaled_output(
|
||||
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 = (proxyData*)context->custom;
|
||||
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)
|
||||
@ -379,9 +709,23 @@ static UINT pf_rdpgfx_on_open(RdpgfxClientContext* context, BOOL* do_caps_advert
|
||||
static UINT pf_rdpgfx_caps_confirm(RdpgfxClientContext* context,
|
||||
const RDPGFX_CAPS_CONFIRM_PDU* capsConfirm)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
RdpgfxServerContext* server = (RdpgfxServerContext*)pdata->ps->gfx;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -389,14 +733,22 @@ static UINT pf_rdpgfx_caps_confirm(RdpgfxClientContext* context,
|
||||
static UINT pf_rdpgfx_caps_advertise(RdpgfxServerContext* context,
|
||||
const RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
RdpgfxClientContext* client = (RdpgfxClientContext*)pdata->pc->gfx_proxy;
|
||||
UINT16 index;
|
||||
UINT16 proxySupportedCapsSetCount = 0;
|
||||
RDPGFX_CAPS_ADVERTISE_PDU supportedCapsAdvertise;
|
||||
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];
|
||||
@ -417,15 +769,30 @@ static UINT pf_rdpgfx_caps_advertise(RdpgfxServerContext* context,
|
||||
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 = (proxyData*)context->custom;
|
||||
RdpgfxClientContext* client = (RdpgfxClientContext*)pdata->pc->gfx_proxy;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -433,17 +800,39 @@ static UINT
|
||||
pf_rdpgfx_qoe_frame_acknowledge(RdpgfxServerContext* context,
|
||||
const RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* qoeFrameAcknowledge)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)context->custom;
|
||||
RdpgfxClientContext* client = (RdpgfxClientContext*)pdata->pc->gfx_proxy;
|
||||
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 = (proxyData*)context->custom;
|
||||
RdpgfxClientContext* client = (RdpgfxClientContext*)pdata->pc->gfx_proxy;
|
||||
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)
|
||||
@ -452,13 +841,22 @@ static UINT pf_rdpgfx_cache_import_offer(RdpgfxServerContext* context,
|
||||
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 = pdata->pc;
|
||||
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);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include <freerdp/gdi/gfx.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
BOOL pf_server_rdpgfx_init(pServerContext* ps);
|
||||
void pf_rdpgfx_pipeline_init(RdpgfxClientContext* gfx, RdpgfxServerContext* server,
|
||||
|
@ -18,13 +18,15 @@
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#include <freerdp/server/server-common.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
#include "pf_rdpsnd.h"
|
||||
#include "pf_log.h"
|
||||
|
||||
#define TAG PROXY_TAG("rdpsnd")
|
||||
|
||||
@ -33,10 +35,13 @@ 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];
|
||||
@ -54,12 +59,16 @@ static void rdpsnd_activated(RdpsndServerContext* context)
|
||||
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)
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <freerdp/client/rdpsnd.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
BOOL pf_server_rdpsnd_init(pServerContext* ps);
|
||||
void pf_server_rdpsnd_free(pServerContext* ps);
|
||||
|
@ -30,23 +30,25 @@
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/build-config.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_server.h>
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_server.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_config.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include "pf_client.h"
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "pf_update.h"
|
||||
#include "pf_rdpgfx.h"
|
||||
#include "pf_disp.h"
|
||||
#include "pf_rail.h"
|
||||
#include "pf_channels.h"
|
||||
#include "pf_modules.h"
|
||||
#include "proxy_modules.h"
|
||||
#include "pf_utils.h"
|
||||
|
||||
#define TAG PROXY_TAG("server")
|
||||
|
||||
static psPeerReceiveChannelData server_receive_channel_data_original = NULL;
|
||||
|
||||
static BOOL pf_server_parse_target_from_routing_token(rdpContext* context, char** target,
|
||||
DWORD* port)
|
||||
{
|
||||
@ -64,7 +66,7 @@ static BOOL pf_server_parse_target_from_routing_token(rdpContext* context, char*
|
||||
|
||||
if ((routing_token_length <= prefix_len) || (routing_token_length >= TARGET_MAX))
|
||||
{
|
||||
LOG_ERR(TAG, ps, "invalid routing token length: %" PRIu32 "", routing_token_length);
|
||||
PROXY_LOG_ERR(TAG, ps, "invalid routing token length: %" PRIu32 "", routing_token_length);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -97,15 +99,20 @@ static BOOL pf_server_parse_target_from_routing_token(rdpContext* context, char*
|
||||
}
|
||||
|
||||
static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings,
|
||||
proxyConfig* config)
|
||||
const proxyConfig* config)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)context;
|
||||
proxyFetchTargetEventInfo ev = { 0 };
|
||||
|
||||
WINPR_ASSERT(settings);
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
|
||||
ev.fetch_method = config->FixedTarget ? PROXY_FETCH_TARGET_METHOD_CONFIG
|
||||
: PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO;
|
||||
|
||||
if (!pf_modules_run_filter(FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, ps->pdata, &ev))
|
||||
if (!pf_modules_run_filter(ps->pdata->module, FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, ps->pdata,
|
||||
&ev))
|
||||
return FALSE;
|
||||
|
||||
switch (ev.fetch_method)
|
||||
@ -117,12 +124,13 @@ static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings
|
||||
|
||||
case PROXY_FETCH_TARGET_METHOD_CONFIG:
|
||||
{
|
||||
WINPR_ASSERT(config);
|
||||
settings->ServerPort = config->TargetPort > 0 ? 3389 : settings->ServerPort;
|
||||
settings->ServerHostname = _strdup(config->TargetHost);
|
||||
|
||||
if (!settings->ServerHostname)
|
||||
{
|
||||
LOG_ERR(TAG, ps, "strdup failed!");
|
||||
PROXY_LOG_ERR(TAG, ps, "strdup failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -139,7 +147,7 @@ static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings
|
||||
settings->ServerHostname = _strdup(ev.target_address);
|
||||
if (!settings->ServerHostname)
|
||||
{
|
||||
LOG_ERR(TAG, ps, "strdup failed!");
|
||||
PROXY_LOG_ERR(TAG, ps, "strdup failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -173,15 +181,20 @@ static BOOL pf_server_post_connect(freerdp_peer* peer)
|
||||
size_t accepted_channels_count;
|
||||
size_t i;
|
||||
|
||||
ps = (pServerContext*)peer->context;
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
LOG_INFO(TAG, ps, "Accepted client: %s", peer->settings->ClientHostname);
|
||||
ps = (pServerContext*)peer->context;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
PROXY_LOG_INFO(TAG, ps, "Accepted client: %s", peer->settings->ClientHostname);
|
||||
accepted_channels = WTSGetAcceptedChannelNames(peer, &accepted_channels_count);
|
||||
if (accepted_channels)
|
||||
{
|
||||
for (i = 0; i < accepted_channels_count; i++)
|
||||
LOG_INFO(TAG, ps, "Accepted channel: %s", accepted_channels[i]);
|
||||
PROXY_LOG_INFO(TAG, ps, "Accepted channel: %s", accepted_channels[i]);
|
||||
|
||||
free(accepted_channels);
|
||||
}
|
||||
@ -189,7 +202,7 @@ static BOOL pf_server_post_connect(freerdp_peer* peer)
|
||||
pc = pf_context_create_client_context(peer->settings);
|
||||
if (pc == NULL)
|
||||
{
|
||||
LOG_ERR(TAG, ps, "failed to create client context!");
|
||||
PROXY_LOG_ERR(TAG, ps, "failed to create client context!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -200,26 +213,26 @@ static BOOL pf_server_post_connect(freerdp_peer* peer)
|
||||
|
||||
if (!pf_server_get_target_info(peer->context, client_settings, pdata->config))
|
||||
{
|
||||
LOG_INFO(TAG, ps, "pf_server_get_target_info failed!");
|
||||
PROXY_LOG_INFO(TAG, ps, "pf_server_get_target_info failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LOG_INFO(TAG, ps, "remote target is %s:%" PRIu16 "", client_settings->ServerHostname,
|
||||
client_settings->ServerPort);
|
||||
PROXY_LOG_INFO(TAG, ps, "remote target is %s:%" PRIu16 "", client_settings->ServerHostname,
|
||||
client_settings->ServerPort);
|
||||
|
||||
if (!pf_server_channels_init(ps))
|
||||
if (!pf_server_channels_init(ps, peer))
|
||||
{
|
||||
LOG_INFO(TAG, ps, "failed to initialize server's channels!");
|
||||
PROXY_LOG_INFO(TAG, ps, "failed to initialize server's channels!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pf_modules_run_hook(HOOK_TYPE_SERVER_POST_CONNECT, pdata))
|
||||
if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_POST_CONNECT, pdata, peer))
|
||||
return FALSE;
|
||||
|
||||
/* Start a proxy's client in it's own thread */
|
||||
if (!(pdata->client_thread = CreateThread(NULL, 0, pf_client_start, pc, 0, NULL)))
|
||||
{
|
||||
LOG_ERR(TAG, ps, "failed to create client thread");
|
||||
PROXY_LOG_ERR(TAG, ps, "failed to create client thread");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -228,12 +241,51 @@ static BOOL pf_server_post_connect(freerdp_peer* peer)
|
||||
|
||||
static BOOL pf_server_activate(freerdp_peer* peer)
|
||||
{
|
||||
pServerContext* ps;
|
||||
proxyData* pdata;
|
||||
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
ps = (pServerContext*)peer->context;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
WINPR_ASSERT(peer->settings);
|
||||
peer->settings->CompressionLevel = PACKET_COMPR_TYPE_RDP8;
|
||||
if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_ACTIVATE, pdata, peer))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_server_logon(freerdp_peer* peer, const SEC_WINNT_AUTH_IDENTITY* identity,
|
||||
BOOL automatic)
|
||||
{
|
||||
pServerContext* ps;
|
||||
proxyData* pdata;
|
||||
proxyServerPeerLogon info = { 0 };
|
||||
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
ps = (pServerContext*)peer->context;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
WINPR_ASSERT(peer->settings);
|
||||
WINPR_ASSERT(identity);
|
||||
|
||||
info.identity = identity;
|
||||
info.automatic = automatic;
|
||||
if (!pf_modules_run_filter(pdata->module, FILTER_TYPE_SERVER_PEER_LOGON, pdata, &info))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_server_adjust_monitor_layout(freerdp_peer* peer)
|
||||
{
|
||||
WINPR_ASSERT(peer);
|
||||
/* proxy as is, there's no need to do anything here */
|
||||
return TRUE;
|
||||
}
|
||||
@ -242,13 +294,24 @@ static BOOL pf_server_receive_channel_data_hook(freerdp_peer* peer, UINT16 chann
|
||||
const BYTE* data, size_t size, UINT32 flags,
|
||||
size_t totalSize)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)peer->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
proxyData* pdata = ps->pdata;
|
||||
proxyConfig* config = pdata->config;
|
||||
size_t i;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
proxyData* pdata;
|
||||
const proxyConfig* config;
|
||||
int pass;
|
||||
const char* channel_name = WTSChannelGetName(peer, channelId);
|
||||
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
ps = (pServerContext*)peer->context;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
pc = pdata->pc;
|
||||
config = pdata->config;
|
||||
WINPR_ASSERT(config);
|
||||
/*
|
||||
* client side is not initialized yet, call original callback.
|
||||
* this is probably a drdynvc message between peer and proxy server,
|
||||
@ -257,40 +320,52 @@ static BOOL pf_server_receive_channel_data_hook(freerdp_peer* peer, UINT16 chann
|
||||
if (!pc)
|
||||
goto original_cb;
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
pass = pf_utils_channel_is_passthrough(config, channel_name);
|
||||
switch (pass)
|
||||
{
|
||||
if (strncmp(channel_name, config->Passthrough[i], CHANNEL_NAME_LEN) == 0)
|
||||
case 0:
|
||||
return TRUE;
|
||||
case 1:
|
||||
{
|
||||
proxyChannelDataEventInfo ev;
|
||||
UINT64 client_channel_id;
|
||||
|
||||
ev.channel_id = channelId;
|
||||
ev.channel_name = channel_name;
|
||||
ev.data = data;
|
||||
ev.data_len = size;
|
||||
ev.flags = flags;
|
||||
ev.total_size = totalSize;
|
||||
|
||||
if (!pf_modules_run_filter(FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA, pdata, &ev))
|
||||
return FALSE;
|
||||
if (!pf_modules_run_filter(pdata->module, FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA,
|
||||
pdata, &ev))
|
||||
return TRUE; /* Silently ignore */
|
||||
|
||||
client_channel_id = (UINT64)HashTable_GetItemValue(pc->vc_ids, channel_name);
|
||||
|
||||
return pc->context.instance->SendChannelData(pc->context.instance,
|
||||
(UINT16)client_channel_id, data, size);
|
||||
return IFCALLRESULT(TRUE, pc->sendChannelData, pc, &ev);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
original_cb:
|
||||
return server_receive_channel_data_original(peer, channelId, data, size, flags, totalSize);
|
||||
WINPR_ASSERT(pdata->server_receive_channel_data_original);
|
||||
return pdata->server_receive_channel_data_original(peer, channelId, data, size, flags,
|
||||
totalSize);
|
||||
}
|
||||
|
||||
static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)peer->context;
|
||||
rdpSettings* settings = peer->settings;
|
||||
pServerContext* ps;
|
||||
rdpSettings* settings;
|
||||
proxyData* pdata;
|
||||
proxyConfig* config;
|
||||
const proxyConfig* config;
|
||||
proxyServer* server;
|
||||
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
settings = peer->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
ps = (pServerContext*)peer->context;
|
||||
if (!ps)
|
||||
return FALSE;
|
||||
|
||||
@ -301,6 +376,7 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
proxy_data_set_server_context(pdata, ps);
|
||||
server = (proxyServer*)peer->ContextExtra;
|
||||
|
||||
pdata->module = server->module;
|
||||
config = pdata->config = server->config;
|
||||
|
||||
/* currently not supporting GDI orders */
|
||||
@ -309,9 +385,18 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
|
||||
settings->SupportMonitorLayoutPdu = TRUE;
|
||||
settings->SupportGraphicsPipeline = config->GFX;
|
||||
settings->CertificateFile = _strdup("server.crt");
|
||||
settings->PrivateKeyFile = _strdup("server.key");
|
||||
settings->RdpKeyFile = _strdup("server.key");
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_CertificateFile, config->CertificateFile) ||
|
||||
!freerdp_settings_set_string(settings, FreeRDP_CertificateContent,
|
||||
config->CertificateContent) ||
|
||||
!freerdp_settings_set_string(settings, FreeRDP_PrivateKeyFile, config->PrivateKeyFile) ||
|
||||
!freerdp_settings_set_string(settings, FreeRDP_PrivateKeyContent,
|
||||
config->PrivateKeyContent) ||
|
||||
!freerdp_settings_set_string(settings, FreeRDP_RdpKeyFile, config->RdpKeyFile) ||
|
||||
!freerdp_settings_set_string(settings, FreeRDP_RdpKeyContent, config->RdpKeyContent))
|
||||
{
|
||||
WLog_ERR(TAG, "Memory allocation failed (strdup)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (config->RemoteApp)
|
||||
{
|
||||
@ -324,15 +409,9 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
settings->RemoteAppLanguageBarSupported = TRUE;
|
||||
}
|
||||
|
||||
if (!settings->CertificateFile || !settings->PrivateKeyFile || !settings->RdpKeyFile)
|
||||
{
|
||||
WLog_ERR(TAG, "Memory allocation failed (strdup)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
settings->RdpSecurity = config->ServerRdpSecurity;
|
||||
settings->TlsSecurity = config->ServerTlsSecurity;
|
||||
settings->NlaSecurity = FALSE; /* currently NLA is not supported in proxy server */
|
||||
settings->NlaSecurity = config->ServerNlaSecurity;
|
||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
settings->ColorDepth = 32;
|
||||
settings->SuppressOutput = TRUE;
|
||||
@ -341,11 +420,12 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
|
||||
peer->PostConnect = pf_server_post_connect;
|
||||
peer->Activate = pf_server_activate;
|
||||
peer->Logon = pf_server_logon;
|
||||
peer->AdjustMonitorsLayout = pf_server_adjust_monitor_layout;
|
||||
peer->settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */
|
||||
|
||||
/* virtual channels receive data hook */
|
||||
server_receive_channel_data_original = peer->ReceiveChannelData;
|
||||
pdata->server_receive_channel_data_original = peer->ReceiveChannelData;
|
||||
peer->ReceiveChannelData = pf_server_receive_channel_data_hook;
|
||||
|
||||
if (!ArrayList_Append(server->clients, pdata))
|
||||
@ -362,7 +442,7 @@ static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
|
||||
*/
|
||||
static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
{
|
||||
HANDLE eventHandles[32];
|
||||
HANDLE eventHandles[32] = { 0 };
|
||||
HANDLE ChannelEvent;
|
||||
DWORD eventCount;
|
||||
DWORD tmp;
|
||||
@ -371,7 +451,12 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
rdpContext* pc;
|
||||
proxyData* pdata;
|
||||
freerdp_peer* client = (freerdp_peer*)arg;
|
||||
proxyServer* server = (proxyServer*)client->ContextExtra;
|
||||
proxyServer* server;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
|
||||
server = (proxyServer*)client->ContextExtra;
|
||||
WINPR_ASSERT(server);
|
||||
|
||||
if (!pf_context_init_server_context(client))
|
||||
goto out_free_peer;
|
||||
@ -380,11 +465,16 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
goto out_free_peer;
|
||||
|
||||
ps = (pServerContext*)client->context;
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(ps);
|
||||
|
||||
pdata = ps->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
|
||||
WINPR_ASSERT(client->Initialize);
|
||||
client->Initialize(client);
|
||||
LOG_INFO(TAG, ps, "new connection: proxy address: %s, client address: %s", pdata->config->Host,
|
||||
client->hostname);
|
||||
|
||||
PROXY_LOG_INFO(TAG, ps, "new connection: proxy address: %s, client address: %s",
|
||||
pdata->config->Host, client->hostname);
|
||||
/* Main client event handling loop */
|
||||
ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm);
|
||||
|
||||
@ -392,6 +482,7 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
{
|
||||
eventCount = 0;
|
||||
{
|
||||
WINPR_ASSERT(client->GetEventHandles);
|
||||
tmp = client->GetEventHandles(client, &eventHandles[eventCount], 32 - eventCount);
|
||||
|
||||
if (tmp == 0)
|
||||
@ -413,6 +504,7 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
break;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(client->CheckFileDescriptor);
|
||||
if (client->CheckFileDescriptor(client) != TRUE)
|
||||
break;
|
||||
|
||||
@ -461,19 +553,26 @@ static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
|
||||
|
||||
fail:
|
||||
|
||||
PROXY_LOG_INFO(TAG, ps, "starting shutdown of connection");
|
||||
PROXY_LOG_INFO(TAG, ps, "stopping proxy's client");
|
||||
|
||||
pc = (rdpContext*)pdata->pc;
|
||||
LOG_INFO(TAG, ps, "starting shutdown of connection");
|
||||
LOG_INFO(TAG, ps, "stopping proxy's client");
|
||||
freerdp_client_stop(pc);
|
||||
pf_modules_run_hook(HOOK_TYPE_SERVER_SESSION_END, pdata);
|
||||
LOG_INFO(TAG, ps, "freeing server's channels");
|
||||
pf_server_channels_free(ps);
|
||||
LOG_INFO(TAG, ps, "freeing proxy data");
|
||||
|
||||
pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_END, pdata, client);
|
||||
PROXY_LOG_INFO(TAG, ps, "freeing server's channels");
|
||||
pf_server_channels_free(ps, client);
|
||||
PROXY_LOG_INFO(TAG, ps, "freeing proxy data");
|
||||
ArrayList_Remove(server->clients, pdata);
|
||||
proxy_data_free(pdata);
|
||||
freerdp_client_context_free(pc);
|
||||
|
||||
WINPR_ASSERT(client->Close);
|
||||
client->Close(client);
|
||||
|
||||
WINPR_ASSERT(client->Disconnect);
|
||||
client->Disconnect(client);
|
||||
|
||||
out_free_peer:
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
@ -482,10 +581,11 @@ out_free_peer:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* client)
|
||||
static BOOL pf_server_start_peer(freerdp_peer* client)
|
||||
{
|
||||
HANDLE hThread;
|
||||
client->ContextExtra = listener->info;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
|
||||
if (!(hThread = CreateThread(NULL, 0, pf_server_handle_peer, (void*)client, 0, NULL)))
|
||||
return FALSE;
|
||||
@ -494,57 +594,31 @@ static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* cl
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DWORD WINAPI pf_server_mainloop(LPVOID arg)
|
||||
static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* client)
|
||||
{
|
||||
HANDLE eventHandles[32];
|
||||
DWORD eventCount;
|
||||
DWORD status;
|
||||
proxyServer* server = (proxyServer*)arg;
|
||||
freerdp_listener* listener = server->listener;
|
||||
WINPR_ASSERT(listener);
|
||||
WINPR_ASSERT(client);
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventCount = listener->GetEventHandles(listener, eventHandles, 32);
|
||||
client->ContextExtra = listener->info;
|
||||
|
||||
if (0 == eventCount)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to get FreeRDP event handles");
|
||||
break;
|
||||
}
|
||||
|
||||
eventHandles[eventCount++] = server->stopEvent;
|
||||
status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (WAIT_FAILED == status)
|
||||
{
|
||||
WLog_ERR(TAG, "select failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (listener->CheckFileDescriptor(listener) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
listener->Close(listener);
|
||||
ExitThread(0);
|
||||
return 0;
|
||||
return pf_server_start_peer(client);
|
||||
}
|
||||
|
||||
BOOL pf_server_start(proxyServer* server)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
|
||||
WINPR_ASSERT(server);
|
||||
|
||||
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
goto error;
|
||||
|
||||
WINPR_ASSERT(server->config);
|
||||
WINPR_ASSERT(server->listener);
|
||||
WINPR_ASSERT(server->listener->Open);
|
||||
if (!server->listener->Open(server->listener, server->config->Host, server->config->Port))
|
||||
{
|
||||
switch (errno)
|
||||
@ -563,10 +637,45 @@ BOOL pf_server_start(proxyServer* server)
|
||||
goto error;
|
||||
}
|
||||
|
||||
server->thread = CreateThread(NULL, 0, pf_server_mainloop, (void*)server, 0, NULL);
|
||||
if (!server->thread)
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
WSACleanup();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL pf_server_start_from_socket(proxyServer* server, int socket)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
|
||||
WINPR_ASSERT(server);
|
||||
|
||||
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
goto error;
|
||||
|
||||
WINPR_ASSERT(server->listener);
|
||||
WINPR_ASSERT(server->listener->OpenFromSocket);
|
||||
if (!server->listener->OpenFromSocket(server->listener, socket))
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EADDRINUSE:
|
||||
WLog_ERR(TAG, "failed to start listener: address already in use!");
|
||||
break;
|
||||
case EACCES:
|
||||
WLog_ERR(TAG, "failed to start listener: insufficent permissions!");
|
||||
break;
|
||||
default:
|
||||
WLog_ERR(TAG, "failed to start listener: errno=%d", errno);
|
||||
break;
|
||||
}
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
@ -574,25 +683,85 @@ error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
WINPR_ASSERT(server);
|
||||
|
||||
if (!client)
|
||||
goto fail;
|
||||
|
||||
if (getpeername(peer_fd, (struct sockaddr*)&peer_addr, &len) != 0)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_peer_set_local_and_hostname(client, &peer_addr))
|
||||
goto fail;
|
||||
|
||||
client->ContextExtra = server;
|
||||
|
||||
if (!pf_server_start_peer(client))
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
WLog_ERR(TAG, "PeerAccepted callback failed");
|
||||
freerdp_peer_free(client);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void pf_server_clients_list_client_free(void* obj)
|
||||
{
|
||||
proxyData* pdata = (proxyData*)obj;
|
||||
proxy_data_abort_connect(pdata);
|
||||
}
|
||||
|
||||
proxyServer* pf_server_new(proxyConfig* config)
|
||||
static BOOL are_all_required_modules_loaded(proxyModule* module, const proxyConfig* config)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < pf_config_required_plugins_count(config); i++)
|
||||
{
|
||||
const char* plugin_name = pf_config_required_plugin(config, i);
|
||||
|
||||
if (!pf_modules_is_plugin_loaded(module, plugin_name))
|
||||
{
|
||||
WLog_ERR(TAG, "Required plugin '%s' is not loaded. stopping.", plugin_name);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
proxyServer* pf_server_new(const proxyConfig* config)
|
||||
{
|
||||
wObject* obj;
|
||||
proxyServer* server;
|
||||
|
||||
if (!config)
|
||||
return NULL;
|
||||
WINPR_ASSERT(config);
|
||||
|
||||
server = calloc(1, sizeof(proxyServer));
|
||||
if (!server)
|
||||
return NULL;
|
||||
|
||||
server->config = config;
|
||||
if (!pf_config_clone(&server->config, config))
|
||||
goto out;
|
||||
|
||||
server->module = pf_modules_new(FREERDP_PROXY_PLUGINDIR, pf_config_modules(config),
|
||||
pf_config_modules_count(config));
|
||||
if (!server->module)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to initialize proxy modules!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pf_modules_list_loaded_plugins(server->module);
|
||||
if (!are_all_required_modules_loaded(server->module, server->config))
|
||||
goto out;
|
||||
|
||||
server->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!server->stopEvent)
|
||||
@ -622,6 +791,58 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL pf_server_run(proxyServer* server)
|
||||
{
|
||||
BOOL rc = TRUE;
|
||||
HANDLE eventHandles[32] = { 0 };
|
||||
DWORD eventCount;
|
||||
DWORD status;
|
||||
freerdp_listener* listener;
|
||||
|
||||
WINPR_ASSERT(server);
|
||||
|
||||
listener = server->listener;
|
||||
WINPR_ASSERT(listener);
|
||||
|
||||
while (1)
|
||||
{
|
||||
WINPR_ASSERT(listener->GetEventHandles);
|
||||
eventCount = listener->GetEventHandles(listener, eventHandles, 32);
|
||||
|
||||
if (0 == eventCount)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to get FreeRDP event handles");
|
||||
break;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(server->stopEvent);
|
||||
eventHandles[eventCount++] = server->stopEvent;
|
||||
status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (WAIT_FAILED == status)
|
||||
{
|
||||
WLog_ERR(TAG, "select failed");
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(listener->CheckFileDescriptor);
|
||||
if (listener->CheckFileDescriptor(listener) != TRUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WINPR_ASSERT(listener->Close);
|
||||
listener->Close(listener);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void pf_server_stop(proxyServer* server)
|
||||
{
|
||||
HANDLE waitHandle = INVALID_HANDLE_VALUE;
|
||||
@ -639,7 +860,6 @@ void pf_server_stop(proxyServer* server)
|
||||
|
||||
/* signal main thread to stop and wait for the thread to exit */
|
||||
SetEvent(server->stopEvent);
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
}
|
||||
|
||||
void pf_server_free(proxyServer* server)
|
||||
@ -654,8 +874,15 @@ void pf_server_free(proxyServer* server)
|
||||
if (server->stopEvent)
|
||||
CloseHandle(server->stopEvent);
|
||||
|
||||
if (server->thread)
|
||||
CloseHandle(server->thread);
|
||||
|
||||
pf_server_config_free(server->config);
|
||||
pf_modules_free(server->module);
|
||||
free(server);
|
||||
}
|
||||
|
||||
BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep, void* userdata)
|
||||
{
|
||||
WINPR_ASSERT(server);
|
||||
WINPR_ASSERT(ep);
|
||||
|
||||
return pf_modules_add(server->module, ep, userdata);
|
||||
}
|
||||
|
@ -19,29 +19,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_SERVER_PROXY_SERVER_H
|
||||
#define FREERDP_SERVER_PROXY_SERVER_H
|
||||
#ifndef _FREERDP_SERVER_PROXY_SERVER_H
|
||||
#define _FREERDP_SERVER_PROXY_SERVER_H
|
||||
|
||||
#include <winpr/collections.h>
|
||||
#include <freerdp/listener.h>
|
||||
|
||||
#include "pf_config.h"
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
#include "proxy_modules.h"
|
||||
|
||||
typedef struct proxy_server
|
||||
struct proxy_server
|
||||
{
|
||||
proxyModule* module;
|
||||
proxyConfig* config;
|
||||
|
||||
freerdp_listener* listener;
|
||||
wArrayList* clients; /* maintain a list of active sessions, for stats */
|
||||
wCountdownEvent* waitGroup; /* wait group used for gracefull shutdown */
|
||||
HANDLE thread; /* main server thread - freerdp listener thread */
|
||||
HANDLE stopEvent; /* an event used to signal the main thread to stop */
|
||||
} proxyServer;
|
||||
};
|
||||
|
||||
proxyServer* pf_server_new(proxyConfig* config);
|
||||
void pf_server_free(proxyServer* server);
|
||||
|
||||
BOOL pf_server_start(proxyServer* server);
|
||||
void pf_server_stop(proxyServer* server);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_SERVER_H */
|
||||
#endif /* _FREERDP_SERVER_PROXY_SERVER_H */
|
||||
|
@ -21,27 +21,41 @@
|
||||
|
||||
#include <freerdp/display.h>
|
||||
#include <freerdp/session.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/image.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include "pf_modules.h"
|
||||
#include <freerdp/server/proxy/proxy_log.h>
|
||||
|
||||
#include "pf_update.h"
|
||||
#include "pf_context.h"
|
||||
#include "pf_log.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
#include "proxy_modules.h"
|
||||
|
||||
#define TAG PROXY_TAG("update")
|
||||
|
||||
static BOOL pf_server_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)context;
|
||||
rdpContext* pc = (rdpContext*)ps->pdata->pc;
|
||||
rdpContext* pc;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
pc = (rdpContext*)ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->update);
|
||||
WINPR_ASSERT(pc->update->RefreshRect);
|
||||
return pc->update->RefreshRect(pc, count, areas);
|
||||
}
|
||||
|
||||
static BOOL pf_server_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
|
||||
{
|
||||
pServerContext* ps = (pServerContext*)context;
|
||||
rdpContext* pc = (rdpContext*)ps->pdata->pc;
|
||||
rdpContext* pc;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->pdata);
|
||||
pc = (rdpContext*)ps->pdata->pc;
|
||||
WINPR_ASSERT(pc);
|
||||
WINPR_ASSERT(pc->update);
|
||||
WINPR_ASSERT(pc->update->SuppressOutput);
|
||||
return pc->update->SuppressOutput(pc, allow, area);
|
||||
}
|
||||
|
||||
@ -54,8 +68,15 @@ static BOOL pf_server_suppress_output(rdpContext* context, BYTE allow, const REC
|
||||
static BOOL pf_client_begin_paint(rdpContext* context)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->BeginPaint);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->BeginPaint(ps);
|
||||
}
|
||||
@ -68,8 +89,15 @@ static BOOL pf_client_begin_paint(rdpContext* context)
|
||||
static BOOL pf_client_end_paint(rdpContext* context)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->EndPaint);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
|
||||
@ -77,7 +105,7 @@ static BOOL pf_client_end_paint(rdpContext* context)
|
||||
if (!ps->update->EndPaint(ps))
|
||||
return FALSE;
|
||||
|
||||
if (!pf_modules_run_hook(HOOK_TYPE_CLIENT_END_PAINT, pdata))
|
||||
if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_CLIENT_END_PAINT, pdata, context))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -86,8 +114,15 @@ static BOOL pf_client_end_paint(rdpContext* context)
|
||||
static BOOL pf_client_bitmap_update(rdpContext* context, const BITMAP_UPDATE* bitmap)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->BitmapUpdate);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->BitmapUpdate(ps, bitmap);
|
||||
}
|
||||
@ -95,8 +130,17 @@ static BOOL pf_client_bitmap_update(rdpContext* context, const BITMAP_UPDATE* bi
|
||||
static BOOL pf_client_desktop_resize(rdpContext* context)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->DesktopResize);
|
||||
WINPR_ASSERT(context->settings);
|
||||
WINPR_ASSERT(ps->settings);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
ps->settings->DesktopWidth = context->settings->DesktopWidth;
|
||||
ps->settings->DesktopHeight = context->settings->DesktopHeight;
|
||||
@ -107,8 +151,13 @@ static BOOL pf_client_remote_monitors(rdpContext* context, UINT32 count,
|
||||
const MONITOR_DEF* monitors)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return freerdp_display_send_monitor_layout(ps, count, monitors);
|
||||
}
|
||||
@ -117,8 +166,16 @@ static BOOL pf_client_send_pointer_system(rdpContext* context,
|
||||
const POINTER_SYSTEM_UPDATE* pointer_system)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerSystem);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerSystem(ps, pointer_system);
|
||||
}
|
||||
@ -127,8 +184,16 @@ static BOOL pf_client_send_pointer_position(rdpContext* context,
|
||||
const POINTER_POSITION_UPDATE* pointerPosition)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerPosition);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerPosition(ps, pointerPosition);
|
||||
}
|
||||
@ -137,8 +202,16 @@ static BOOL pf_client_send_pointer_color(rdpContext* context,
|
||||
const POINTER_COLOR_UPDATE* pointer_color)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerColor);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerColor(ps, pointer_color);
|
||||
}
|
||||
@ -147,8 +220,16 @@ static BOOL pf_client_send_pointer_large(rdpContext* context,
|
||||
const POINTER_LARGE_UPDATE* pointer_large)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerLarge);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerLarge(ps, pointer_large);
|
||||
}
|
||||
@ -156,8 +237,16 @@ static BOOL pf_client_send_pointer_large(rdpContext* context,
|
||||
static BOOL pf_client_send_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerNew);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerNew(ps, pointer_new);
|
||||
}
|
||||
@ -166,18 +255,33 @@ static BOOL pf_client_send_pointer_cached(rdpContext* context,
|
||||
const POINTER_CACHED_UPDATE* pointer_cached)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->pointer);
|
||||
WINPR_ASSERT(ps->update->pointer->PointerCached);
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerCached(ps, pointer_cached);
|
||||
}
|
||||
|
||||
static BOOL pf_client_save_session_info(rdpContext* context, UINT32 type, void* data)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
logon_info* logonInfo = NULL;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->SaveSessionInfo);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
|
||||
@ -187,8 +291,8 @@ static BOOL pf_client_save_session_info(rdpContext* context, UINT32 type, void*
|
||||
case INFO_TYPE_LOGON_LONG:
|
||||
{
|
||||
logonInfo = (logon_info*)data;
|
||||
LOG_INFO(TAG, pc, "client logon info: Username: %s, Domain: %s", logonInfo->username,
|
||||
logonInfo->domain);
|
||||
PROXY_LOG_INFO(TAG, pc, "client logon info: Username: %s, Domain: %s",
|
||||
logonInfo->username, logonInfo->domain);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -202,7 +306,16 @@ static BOOL pf_client_save_session_info(rdpContext* context, UINT32 type, void*
|
||||
static BOOL pf_client_server_status_info(rdpContext* context, UINT32 status)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->ServerStatusInfo);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->ServerStatusInfo(ps, status);
|
||||
}
|
||||
@ -210,7 +323,16 @@ static BOOL pf_client_server_status_info(rdpContext* context, UINT32 status)
|
||||
static BOOL pf_client_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->SetKeyboardIndicators);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->SetKeyboardIndicators(ps, led_flags);
|
||||
}
|
||||
@ -219,7 +341,16 @@ static BOOL pf_client_set_keyboard_ime_status(rdpContext* context, UINT16 imeId,
|
||||
UINT32 imeConvMode)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->SetKeyboardImeStatus);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->SetKeyboardImeStatus(ps, imeId, imeState, imeConvMode);
|
||||
}
|
||||
@ -227,9 +358,19 @@ static BOOL pf_client_set_keyboard_ime_status(rdpContext* context, UINT16 imeId,
|
||||
static BOOL pf_client_window_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->WindowCreate);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->WindowCreate(ps, orderInfo, windowState);
|
||||
@ -240,9 +381,19 @@ static BOOL pf_client_window_create(rdpContext* context, const WINDOW_ORDER_INFO
|
||||
static BOOL pf_client_window_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_STATE_ORDER* windowState)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->WindowUpdate);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->WindowUpdate(ps, orderInfo, windowState);
|
||||
@ -253,9 +404,19 @@ static BOOL pf_client_window_update(rdpContext* context, const WINDOW_ORDER_INFO
|
||||
static BOOL pf_client_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_ICON_ORDER* windowIcon)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->WindowIcon);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->WindowIcon(ps, orderInfo, windowIcon);
|
||||
@ -266,9 +427,19 @@ static BOOL pf_client_window_icon(rdpContext* context, const WINDOW_ORDER_INFO*
|
||||
static BOOL pf_client_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const WINDOW_CACHED_ICON_ORDER* windowCachedIcon)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->WindowCachedIcon);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->WindowCachedIcon(ps, orderInfo, windowCachedIcon);
|
||||
@ -278,9 +449,19 @@ static BOOL pf_client_window_cached_icon(rdpContext* context, const WINDOW_ORDER
|
||||
|
||||
static BOOL pf_client_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->WindowDelete);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->WindowDelete(ps, orderInfo);
|
||||
@ -291,9 +472,19 @@ static BOOL pf_client_window_delete(rdpContext* context, const WINDOW_ORDER_INFO
|
||||
static BOOL pf_client_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->NotifyIconCreate);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->NotifyIconCreate(ps, orderInfo, notifyIconState);
|
||||
@ -304,9 +495,19 @@ static BOOL pf_client_notify_icon_create(rdpContext* context, const WINDOW_ORDER
|
||||
static BOOL pf_client_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const NOTIFY_ICON_STATE_ORDER* notifyIconState)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->NotifyIconUpdate);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->NotifyIconUpdate(ps, orderInfo, notifyIconState);
|
||||
@ -316,9 +517,20 @@ static BOOL pf_client_notify_icon_update(rdpContext* context, const WINDOW_ORDER
|
||||
|
||||
static BOOL pf_client_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->NotifyIconDelete);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->NotifyIconDelete(ps, orderInfo);
|
||||
@ -329,9 +541,19 @@ static BOOL pf_client_notify_icon_delete(rdpContext* context, const WINDOW_ORDER
|
||||
static BOOL pf_client_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
|
||||
const MONITORED_DESKTOP_ORDER* monitoredDesktop)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->MonitoredDesktop);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->MonitoredDesktop(ps, orderInfo, monitoredDesktop);
|
||||
@ -341,9 +563,19 @@ static BOOL pf_client_monitored_desktop(rdpContext* context, const WINDOW_ORDER_
|
||||
|
||||
static BOOL pf_client_non_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
rdpContext* ps = (rdpContext*)pc->pdata->ps;
|
||||
BOOL rc;
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata;
|
||||
rdpContext* ps;
|
||||
WINPR_ASSERT(pc);
|
||||
pdata = pc->pdata;
|
||||
WINPR_ASSERT(pdata);
|
||||
ps = (rdpContext*)pdata->ps;
|
||||
WINPR_ASSERT(ps);
|
||||
WINPR_ASSERT(ps->update);
|
||||
WINPR_ASSERT(ps->update->window);
|
||||
WINPR_ASSERT(ps->update->window->NonMonitoredDesktop);
|
||||
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
EnterCriticalSection(&ps->update->mux);
|
||||
rc = ps->update->window->NonMonitoredDesktop(ps, orderInfo);
|
||||
@ -353,12 +585,14 @@ static BOOL pf_client_non_monitored_desktop(rdpContext* context, const WINDOW_OR
|
||||
|
||||
void pf_server_register_update_callbacks(rdpUpdate* update)
|
||||
{
|
||||
WINPR_ASSERT(update);
|
||||
update->RefreshRect = pf_server_refresh_rect;
|
||||
update->SuppressOutput = pf_server_suppress_output;
|
||||
}
|
||||
|
||||
void pf_client_register_update_callbacks(rdpUpdate* update)
|
||||
{
|
||||
WINPR_ASSERT(update);
|
||||
update->BeginPaint = pf_client_begin_paint;
|
||||
update->EndPaint = pf_client_end_paint;
|
||||
update->BitmapUpdate = pf_client_bitmap_update;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
#include <freerdp/gdi/bitmap.h>
|
||||
|
||||
#include "pf_context.h"
|
||||
#include <freerdp/server/proxy/proxy_context.h>
|
||||
|
||||
void pf_server_register_update_callbacks(rdpUpdate* update);
|
||||
void pf_client_register_update_callbacks(rdpUpdate* update);
|
||||
|
55
server/proxy/pf_utils.c
Normal file
55
server/proxy/pf_utils.c
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
* * 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 <winpr/assert.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wtsapi.h>
|
||||
|
||||
#include "pf_utils.h"
|
||||
|
||||
int pf_utils_channel_is_passthrough(const proxyConfig* config, const char* name)
|
||||
{
|
||||
size_t i;
|
||||
BOOL found = FALSE;
|
||||
|
||||
WINPR_ASSERT(config);
|
||||
WINPR_ASSERT(name);
|
||||
|
||||
for (i = 0; i < config->PassthroughCount; i++)
|
||||
{
|
||||
const char* channel_name = config->Passthrough[i];
|
||||
if (strncmp(name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (config->PassthroughIsBlacklist)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->PassthroughIsBlacklist)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
37
server/proxy/pf_utils.h
Normal file
37
server/proxy/pf_utils.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2021 Armin Novak <armin.novak@thincast.com>
|
||||
* * 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_SERVER_PROXY_PFUTILS_H
|
||||
#define FREERDP_SERVER_PROXY_PFUTILS_H
|
||||
|
||||
#include <freerdp/server/proxy/proxy_config.h>
|
||||
|
||||
/**
|
||||
* @brief pf_utils_channel_is_passthrough Checks of a channel identified by 'name'
|
||||
* should be handled as passthrough.
|
||||
*
|
||||
* @param config The proxy configuration to check against. Must NOT be NULL.
|
||||
* @param name The name of the channel. Must NOT be NULL.
|
||||
* @return -1 if the channel is not handled, 0 if the channel should be ignored,
|
||||
* 1 if the channel should be passed.
|
||||
*/
|
||||
int pf_utils_channel_is_passthrough(const proxyConfig* config, const char* name);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFUTILS_H */
|
92
server/proxy/proxy_modules.h
Normal file
92
server/proxy/proxy_modules.h
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
|
||||
* Copyright 2019 Idan Freiberg <speidy@gmail.com>
|
||||
*
|
||||
* 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_MODULES_H
|
||||
#define FREERDP_SERVER_PROXY_MODULES_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/server/proxy/proxy_modules_api.h>
|
||||
|
||||
enum _PF_FILTER_TYPE
|
||||
{
|
||||
FILTER_TYPE_KEYBOARD, /* proxyKeyboardEventInfo */
|
||||
FILTER_TYPE_MOUSE, /* proxyMouseEventInfo */
|
||||
FILTER_TYPE_CLIENT_PASSTHROUGH_CHANNEL_DATA, /* proxyChannelDataEventInfo */
|
||||
FILTER_TYPE_SERVER_PASSTHROUGH_CHANNEL_DATA, /* proxyChannelDataEventInfo */
|
||||
FILTER_TYPE_CLIENT_PASSTHROUGH_DYN_CHANNEL_CREATE, /* proxyChannelDataEventInfo */
|
||||
FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, /* proxyFetchTargetEventInfo */
|
||||
FILTER_TYPE_SERVER_PEER_LOGON, /* proxyServerPeerLogon */
|
||||
|
||||
FILTER_LAST
|
||||
};
|
||||
typedef enum _PF_FILTER_TYPE PF_FILTER_TYPE;
|
||||
|
||||
enum _PF_HOOK_TYPE
|
||||
{
|
||||
HOOK_TYPE_CLIENT_INIT_CONNECT,
|
||||
HOOK_TYPE_CLIENT_UNINIT_CONNECT,
|
||||
HOOK_TYPE_CLIENT_PRE_CONNECT,
|
||||
HOOK_TYPE_CLIENT_POST_CONNECT,
|
||||
HOOK_TYPE_CLIENT_POST_DISCONNECT,
|
||||
HOOK_TYPE_CLIENT_VERIFY_X509,
|
||||
HOOK_TYPE_CLIENT_LOGIN_FAILURE,
|
||||
HOOK_TYPE_CLIENT_END_PAINT,
|
||||
|
||||
HOOK_TYPE_SERVER_POST_CONNECT,
|
||||
HOOK_TYPE_SERVER_ACTIVATE,
|
||||
HOOK_TYPE_SERVER_CHANNELS_INIT,
|
||||
HOOK_TYPE_SERVER_CHANNELS_FREE,
|
||||
HOOK_TYPE_SERVER_SESSION_END,
|
||||
|
||||
HOOK_LAST
|
||||
};
|
||||
typedef enum _PF_HOOK_TYPE PF_HOOK_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
proxyModule* pf_modules_new(const char* root_dir, const char** modules, size_t count);
|
||||
|
||||
/**
|
||||
* @brief pf_modules_add Registers a new plugin
|
||||
* @param ep A module entry point function, must NOT be NULL
|
||||
* @return TRUE for success, FALSE otherwise
|
||||
*/
|
||||
BOOL pf_modules_add(proxyModule* module, proxyModuleEntryPoint ep, void* userdata);
|
||||
|
||||
BOOL pf_modules_is_plugin_loaded(proxyModule* module, const char* plugin_name);
|
||||
void pf_modules_list_loaded_plugins(proxyModule* module);
|
||||
|
||||
BOOL pf_modules_run_filter(proxyModule* module, PF_FILTER_TYPE type, proxyData* pdata,
|
||||
void* param);
|
||||
BOOL pf_modules_run_hook(proxyModule* module, PF_HOOK_TYPE type, proxyData* pdata,
|
||||
void* custom);
|
||||
|
||||
void pf_modules_free(proxyModule* module);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_MODULES_H */
|
Loading…
Reference in New Issue
Block a user