mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge pull request #5405 from m4ntis/proxy/filters-api
Proxy: Filters API
This commit is contained in:
@@ -43,6 +43,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
pf_config.h
|
||||
pf_graphics.c
|
||||
pf_graphics.h
|
||||
pf_filters.c
|
||||
pf_filters.h
|
||||
pf_log.h)
|
||||
|
||||
# On windows create dll version information.
|
||||
@@ -74,3 +76,5 @@ if (WITH_DEBUG_SYMBOLS AND MSVC)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/proxy")
|
||||
|
||||
add_subdirectory("filters")
|
||||
|
||||
@@ -31,3 +31,7 @@ RdpSecurity = 1
|
||||
WhitelistMode = 0
|
||||
AllowedChannels = "cliprdr,Microsoft::Windows::RDS::Video::Control"
|
||||
DeniedChannels = "Microsoft::Windows::RDS::Geometry"
|
||||
|
||||
[Filters]
|
||||
; FilterName = FilterPath
|
||||
DemoFilter = "server/proxy/filters/libdemo_filter.so"
|
||||
|
||||
3
server/proxy/filters/CMakeLists.txt
Normal file
3
server/proxy/filters/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add_library(demo_filter SHARED
|
||||
filter_demo.c
|
||||
)
|
||||
27
server/proxy/filters/README.md
Normal file
27
server/proxy/filters/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Proxy filter 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.
|
||||
|
||||
During startup, the proxy loads its filters from the configuration:
|
||||
```ini
|
||||
[Filters]
|
||||
; FilterName = FilterPath
|
||||
DemoFilter = "server/proxy/demo.so"
|
||||
```
|
||||
|
||||
## Currently supported events
|
||||
* Mouse event
|
||||
* Keyboard event
|
||||
|
||||
## 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.
|
||||
* 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.
|
||||
|
||||
A demo can be found in `filter_demo.c`.
|
||||
48
server/proxy/filters/filter_demo.c
Normal file
48
server/proxy/filters/filter_demo.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Kobi Mizrachi <kmizrachi18@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.
|
||||
*/
|
||||
|
||||
#include "filters_api.h"
|
||||
|
||||
static PF_FILTER_RESULT demo_filter_keyboard_event(connectionInfo* info, void* param)
|
||||
{
|
||||
proxyKeyboardEventInfo* event_data = (proxyKeyboardEventInfo*) param;
|
||||
WINPR_UNUSED(event_data);
|
||||
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
static PF_FILTER_RESULT demo_filter_mouse_event(connectionInfo* info, void* param)
|
||||
{
|
||||
proxyMouseEventInfo* event_data = (proxyMouseEventInfo*) param;
|
||||
|
||||
if (event_data->x % 100 == 0)
|
||||
{
|
||||
return FILTER_DROP;
|
||||
}
|
||||
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
BOOL filter_init(proxyEvents* events)
|
||||
{
|
||||
events->KeyboardEvent = demo_filter_keyboard_event;
|
||||
events->MouseEvent = demo_filter_mouse_event;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
69
server/proxy/filters/filters_api.h
Normal file
69
server/proxy/filters/filters_api.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
|
||||
* 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_FILTERS_API_H
|
||||
#define FREERDP_SERVER_PROXY_FILTERS_API_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
enum pf_filter_result {
|
||||
FILTER_PASS = 0,
|
||||
FILTER_DROP,
|
||||
FILTER_IGNORE
|
||||
};
|
||||
|
||||
typedef enum pf_filter_result PF_FILTER_RESULT;
|
||||
typedef struct connection_info connectionInfo;
|
||||
typedef struct proxy_events proxyEvents;
|
||||
typedef struct proxy_keyboard_event_info proxyKeyboardEventInfo;
|
||||
typedef struct proxy_mouse_event_info proxyMouseEventInfo;
|
||||
typedef PF_FILTER_RESULT(*proxyEvent)(connectionInfo* info, void* param);
|
||||
|
||||
struct connection_info {
|
||||
char* TargetHostname;
|
||||
char* ClientHostname;
|
||||
char* Username;
|
||||
};
|
||||
|
||||
struct proxy_events {
|
||||
proxyEvent KeyboardEvent;
|
||||
proxyEvent MouseEvent;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct proxy_keyboard_event_info {
|
||||
UINT16 flags;
|
||||
UINT16 rdp_scan_code;
|
||||
};
|
||||
|
||||
struct proxy_mouse_event_info {
|
||||
UINT16 flags;
|
||||
UINT16 x;
|
||||
UINT16 y;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/* implement this method and register callbacks for proxy events
|
||||
* return TRUE if initialization succeeded, otherwise FALSE.
|
||||
**/
|
||||
BOOL filter_init(proxyEvents* events);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_FILTERS_API_H */
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "pf_server.h"
|
||||
#include "pf_config.h"
|
||||
#include "pf_log.h"
|
||||
#include "pf_filters.h"
|
||||
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#define TAG PROXY_TAG("server")
|
||||
|
||||
@@ -31,6 +34,7 @@ int main(int argc, char* argv[])
|
||||
int status = 0;
|
||||
DWORD ld;
|
||||
UINT32 i;
|
||||
UINT32 count;
|
||||
proxyConfig* config = calloc(1, sizeof(proxyConfig));
|
||||
|
||||
if (!config)
|
||||
@@ -58,16 +62,18 @@ int main(int argc, char* argv[])
|
||||
if (config->WhitelistMode)
|
||||
{
|
||||
WLog_INFO(TAG, "Channels mode: WHITELIST");
|
||||
count = ArrayList_Count(config->AllowedChannels);
|
||||
|
||||
for (i = 0; i < config->AllowedChannelsCount; i++)
|
||||
WLog_INFO(TAG, "Allowing %s", config->AllowedChannels[i]);
|
||||
for (i = 0; i < count; i++)
|
||||
WLog_INFO(TAG, "Allowing %s", (char*) ArrayList_GetItem(config->AllowedChannels, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_INFO(TAG, "Channels mode: BLACKLIST");
|
||||
count = ArrayList_Count(config->BlockedChannels);
|
||||
|
||||
for (i = 0; i < config->BlockedChannelsCount; i++)
|
||||
WLog_INFO(TAG, "Blocking %s", config->BlockedChannels[i]);
|
||||
for (i = 0; i < count; i++)
|
||||
WLog_INFO(TAG, "Blocking %s", (char*) ArrayList_GetItem(config->BlockedChannels, i));
|
||||
}
|
||||
|
||||
status = pf_server_start(config);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_server.h"
|
||||
#include "pf_config.h"
|
||||
@@ -30,39 +32,56 @@
|
||||
|
||||
#define CHANNELS_SEPERATOR ","
|
||||
|
||||
static char** parse_channels_from_str(const char* str, UINT32* length)
|
||||
wArrayList* parse_string_array_from_str(const char* str)
|
||||
{
|
||||
char* s = strdup(str);
|
||||
size_t tokens_alloc = 1;
|
||||
size_t tokens_count = 0;
|
||||
char** tokens = calloc(tokens_alloc, sizeof(char*));
|
||||
wArrayList* list = ArrayList_New(FALSE);
|
||||
char* s;
|
||||
char* temp;
|
||||
char* token;
|
||||
|
||||
while ((token = StrSep(&s, CHANNELS_SEPERATOR)) != NULL)
|
||||
if (list == NULL)
|
||||
{
|
||||
if (tokens_count == tokens_alloc)
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): ArrayList_New failed!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
temp = s = _strdup(str);
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): strdup failed!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): strdup failed!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((token = StrSep(&temp, CHANNELS_SEPERATOR)) != NULL)
|
||||
{
|
||||
char* current_token = _strdup(token);
|
||||
|
||||
if (current_token == NULL)
|
||||
{
|
||||
tokens_alloc *= 2;
|
||||
tokens = realloc(tokens, tokens_alloc * sizeof(char*));
|
||||
WLog_ERR(TAG, "parse_string_array_from_str(): strdup failed!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
tokens[tokens_count++] = strdup(token);
|
||||
if (ArrayList_Add(list, current_token) < 0)
|
||||
{
|
||||
free(current_token);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tokens_count == 0) || (tokens_count > UINT32_MAX))
|
||||
{
|
||||
free(tokens);
|
||||
tokens = NULL;
|
||||
tokens_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens = realloc(tokens, tokens_count * sizeof(char*));
|
||||
}
|
||||
|
||||
*length = (DWORD)tokens_count;
|
||||
free(s);
|
||||
return tokens;
|
||||
return list;
|
||||
error:
|
||||
free(s);
|
||||
ArrayList_Free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL pf_server_is_config_valid(proxyConfig* config)
|
||||
@@ -100,7 +119,10 @@ static BOOL pf_server_is_config_valid(proxyConfig* config)
|
||||
DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
{
|
||||
const char* input;
|
||||
char** filters_names;
|
||||
int rc;
|
||||
int filters_count = 0;
|
||||
UINT32 index;
|
||||
DWORD result = CONFIG_PARSE_ERROR;
|
||||
wIniFile* ini = IniFile_New();
|
||||
|
||||
@@ -141,10 +163,11 @@ DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
/* channels filtering */
|
||||
config->WhitelistMode = IniFile_GetKeyValueInt(ini, "Channels", "WhitelistMode");
|
||||
input = IniFile_GetKeyValueString(ini, "Channels", "AllowedChannels");
|
||||
/* filters api */
|
||||
|
||||
if (input)
|
||||
{
|
||||
config->AllowedChannels = parse_channels_from_str(input, &config->AllowedChannelsCount);
|
||||
config->AllowedChannels = parse_string_array_from_str(input);
|
||||
|
||||
if (config->AllowedChannels == NULL)
|
||||
goto out;
|
||||
@@ -154,13 +177,34 @@ DWORD pf_server_load_config(const char* path, proxyConfig* config)
|
||||
|
||||
if (input)
|
||||
{
|
||||
config->BlockedChannels = parse_channels_from_str(input, &config->BlockedChannelsCount);
|
||||
config->BlockedChannels = parse_string_array_from_str(input);
|
||||
|
||||
if (config->BlockedChannels == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = CONFIG_PARSE_SUCCESS;
|
||||
|
||||
if (!pf_filters_init(&config->Filters))
|
||||
goto out;
|
||||
|
||||
filters_names = IniFile_GetSectionKeyNames(ini, "Filters", &filters_count);
|
||||
|
||||
for (index = 0; index < filters_count; index++)
|
||||
{
|
||||
char* filter_name = filters_names[index];
|
||||
const char* path = IniFile_GetKeyValueString(ini, "Filters", filter_name);
|
||||
|
||||
if (!pf_filters_register_new(config->Filters, path, filter_name))
|
||||
{
|
||||
WLog_DBG(TAG, "pf_server_load_config(): failed to register %s (%s)", filter_name, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_DBG(TAG, "pf_server_load_config(): registered filter %s (%s) successfully", filter_name, path);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
IniFile_Free(ini);
|
||||
|
||||
@@ -172,16 +216,9 @@ out:
|
||||
|
||||
void pf_server_config_free(proxyConfig* config)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
for (i = 0; i < config->AllowedChannelsCount; i++)
|
||||
free(config->AllowedChannels[i]);
|
||||
|
||||
for (i = 0; i < config->BlockedChannelsCount; i++)
|
||||
free(config->BlockedChannels[i]);
|
||||
|
||||
free(config->AllowedChannels);
|
||||
free(config->BlockedChannels);
|
||||
pf_filters_unregister_all(config->Filters);
|
||||
ArrayList_Free(config->AllowedChannels);
|
||||
ArrayList_Free(config->BlockedChannels);
|
||||
free(config->TargetHost);
|
||||
free(config->Host);
|
||||
free(config);
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <winpr/ini.h>
|
||||
|
||||
#include "pf_filters.h"
|
||||
|
||||
struct proxy_config
|
||||
{
|
||||
/* server */
|
||||
@@ -56,11 +58,11 @@ struct proxy_config
|
||||
/* channels */
|
||||
BOOL WhitelistMode;
|
||||
|
||||
char** AllowedChannels;
|
||||
UINT32 AllowedChannelsCount;
|
||||
wArrayList* AllowedChannels;
|
||||
wArrayList* BlockedChannels;
|
||||
|
||||
char** BlockedChannels;
|
||||
UINT32 BlockedChannelsCount;
|
||||
/* filters */
|
||||
filters_list* Filters;
|
||||
};
|
||||
|
||||
typedef struct proxy_config proxyConfig;
|
||||
|
||||
@@ -56,8 +56,7 @@ BOOL init_p_server_context(freerdp_peer* client)
|
||||
return freerdp_peer_context_new(client);
|
||||
}
|
||||
|
||||
rdpContext* p_client_context_create(rdpSettings* clientSettings,
|
||||
char* host, DWORD port)
|
||||
rdpContext* p_client_context_create(rdpSettings* clientSettings)
|
||||
{
|
||||
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
|
||||
rdpContext* context;
|
||||
@@ -73,8 +72,6 @@ rdpContext* p_client_context_create(rdpSettings* clientSettings,
|
||||
settings->Username = _strdup(clientSettings->Username);
|
||||
settings->Password = _strdup(clientSettings->Password);
|
||||
settings->Domain = _strdup(clientSettings->Domain);
|
||||
settings->ServerHostname = host;
|
||||
settings->ServerPort = port;
|
||||
settings->SoftwareGdi = FALSE;
|
||||
settings->RedirectClipboard = FALSE;
|
||||
/* Client Monitor Data */
|
||||
@@ -119,3 +116,61 @@ error:
|
||||
freerdp_client_context_free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void connection_info_free(connectionInfo* info)
|
||||
{
|
||||
free(info->TargetHostname);
|
||||
free(info->ClientHostname);
|
||||
free(info->Username);
|
||||
free(info);
|
||||
}
|
||||
|
||||
proxyData* proxy_data_new()
|
||||
{
|
||||
proxyData* pdata = calloc(1, sizeof(proxyData));
|
||||
|
||||
if (pdata == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdata->info = calloc(1, sizeof(connectionInfo));
|
||||
|
||||
if (pdata->info == NULL)
|
||||
{
|
||||
free(pdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(pdata->connectionClosed = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
proxy_data_free(pdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
BOOL proxy_data_set_connection_info(proxyData* pdata, rdpSettings* clientSettings,
|
||||
const char* target)
|
||||
{
|
||||
if (!(pdata->info->TargetHostname = _strdup(target)))
|
||||
goto out_fail;
|
||||
|
||||
if (!(pdata->info->ClientHostname = _strdup(clientSettings->ClientHostname)))
|
||||
goto out_fail;
|
||||
|
||||
if (!(pdata->info->Username = _strdup(clientSettings->Username)))
|
||||
goto out_fail;
|
||||
|
||||
return TRUE;
|
||||
out_fail:
|
||||
proxy_data_free(pdata);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void proxy_data_free(proxyData* pdata)
|
||||
{
|
||||
connection_info_free(pdata->info);
|
||||
free(pdata);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include "pf_config.h"
|
||||
#include "pf_server.h"
|
||||
|
||||
#include "pf_filters.h"
|
||||
|
||||
typedef struct proxy_data proxyData;
|
||||
|
||||
@@ -75,9 +75,16 @@ struct proxy_data
|
||||
pClientContext* pc;
|
||||
|
||||
HANDLE connectionClosed;
|
||||
|
||||
connectionInfo* info;
|
||||
filters_list* filters;
|
||||
};
|
||||
|
||||
BOOL init_p_server_context(freerdp_peer* client);
|
||||
rdpContext* p_client_context_create(rdpSettings* clientSettings, char* host, DWORD port);
|
||||
rdpContext* p_client_context_create(rdpSettings* clientSettings);
|
||||
proxyData* proxy_data_new();
|
||||
BOOL proxy_data_set_connection_info(proxyData* pdata, rdpSettings* clientSettings,
|
||||
const char* target);
|
||||
void proxy_data_free(proxyData* pdata);
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFCONTEXT_H */
|
||||
|
||||
216
server/proxy/pf_filters.c
Normal file
216
server/proxy/pf_filters.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/library.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "pf_log.h"
|
||||
#include "pf_filters.h"
|
||||
|
||||
#define TAG PROXY_TAG("filters")
|
||||
#define FILTER_INIT_METHOD "filter_init"
|
||||
|
||||
static const char* FILTER_RESULT_STRINGS[] =
|
||||
{
|
||||
"FILTER_PASS",
|
||||
"FILTER_DROP",
|
||||
"FILTER_IGNORE",
|
||||
};
|
||||
|
||||
static const char* EVENT_TYPE_STRINGS[] =
|
||||
{
|
||||
"KEYBOARD_EVENT",
|
||||
"MOUSE_EVENT",
|
||||
};
|
||||
|
||||
static const char* pf_filters_get_filter_result_string(PF_FILTER_RESULT result)
|
||||
{
|
||||
if (result >= FILTER_PASS && result <= FILTER_IGNORE)
|
||||
return FILTER_RESULT_STRINGS[result];
|
||||
else
|
||||
return "FILTER_UNKNOWN";
|
||||
}
|
||||
|
||||
static const char* pf_filters_get_event_type_string(PF_FILTER_TYPE result)
|
||||
{
|
||||
if (result >= FILTER_TYPE_KEYBOARD && result <= FILTER_TYPE_MOUSE)
|
||||
return EVENT_TYPE_STRINGS[result];
|
||||
else
|
||||
return "EVENT_UNKNOWN";
|
||||
}
|
||||
|
||||
BOOL pf_filters_init(filters_list** list)
|
||||
{
|
||||
if (list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_init(): list == NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*list = ArrayList_New(FALSE);
|
||||
|
||||
if (*list == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_init(): ArrayList_New failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PF_FILTER_RESULT pf_filters_run_by_type(filters_list* list, PF_FILTER_TYPE type,
|
||||
connectionInfo* info,
|
||||
void* param)
|
||||
{
|
||||
proxyFilter* filter;
|
||||
proxyEvents* events;
|
||||
PF_FILTER_RESULT result = FILTER_PASS;
|
||||
const size_t count = (size_t) ArrayList_Count(list);
|
||||
size_t index;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
filter = (proxyFilter*) ArrayList_GetItem(list, index);
|
||||
events = filter->events;
|
||||
WLog_DBG(TAG, "pf_filters_run_by_type(): Running filter: %s", filter->name);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case FILTER_TYPE_KEYBOARD:
|
||||
IFCALLRET(events->KeyboardEvent, result, info, param);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_MOUSE:
|
||||
IFCALLRET(events->MouseEvent, result, info, param);
|
||||
break;
|
||||
}
|
||||
|
||||
if (result != FILTER_PASS)
|
||||
{
|
||||
/* Filter returned FILTER_DROP or FILTER_IGNORE. There's no need to call next filters. */
|
||||
WLog_INFO(TAG, "Filter %s [%s] returned %s", filter->name,
|
||||
pf_filters_get_event_type_string(type), pf_filters_get_filter_result_string(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* all filters returned FILTER_PASS */
|
||||
return FILTER_PASS;
|
||||
}
|
||||
|
||||
static void pf_filters_filter_free(proxyFilter* filter)
|
||||
{
|
||||
assert(filter != NULL);
|
||||
if (filter->handle)
|
||||
FreeLibrary(filter->handle);
|
||||
|
||||
free(filter->name);
|
||||
free(filter->events);
|
||||
free(filter);
|
||||
}
|
||||
|
||||
void pf_filters_unregister_all(filters_list* list)
|
||||
{
|
||||
size_t count;
|
||||
size_t index;
|
||||
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
count = (size_t) ArrayList_Count(list);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
proxyFilter* filter = (proxyFilter*) ArrayList_GetItem(list, index);
|
||||
WLog_DBG(TAG, "pf_filters_unregister_all(): freeing filter: %s", filter->name);
|
||||
pf_filters_filter_free(filter);
|
||||
}
|
||||
|
||||
ArrayList_Free(list);
|
||||
}
|
||||
|
||||
BOOL pf_filters_register_new(filters_list* list, const char* module_path, const char* filter_name)
|
||||
{
|
||||
proxyEvents* events = NULL;
|
||||
proxyFilter* filter = NULL;
|
||||
HMODULE handle = NULL;
|
||||
filterInitFn fn;
|
||||
|
||||
assert(list != NULL);
|
||||
handle = LoadLibraryA(module_path);
|
||||
|
||||
if (handle == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed loading external module: %s", module_path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(fn = (filterInitFn) GetProcAddress(handle, FILTER_INIT_METHOD)))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): GetProcAddress failed while loading %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
filter = (proxyFilter*) malloc(sizeof(proxyFilter));
|
||||
|
||||
if (filter == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): malloc failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
events = calloc(1, sizeof(proxyEvents));
|
||||
|
||||
if (events == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): calloc proxyEvents failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!fn(events))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed calling external filter_init: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
filter->handle = handle;
|
||||
filter->name = _strdup(filter_name);
|
||||
filter->events = events;
|
||||
filter->enabled = TRUE;
|
||||
|
||||
if (ArrayList_Add(list, filter) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "pf_filters_register_new(): failed adding filter to list: %s", module_path);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
|
||||
if (handle)
|
||||
FreeLibrary(handle);
|
||||
|
||||
pf_filters_filter_free(filter);
|
||||
return FALSE;
|
||||
}
|
||||
74
server/proxy/pf_filters.h
Normal file
74
server/proxy/pf_filters.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* FreeRDP Proxy Server
|
||||
*
|
||||
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
|
||||
* 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_FILTERS_H
|
||||
#define FREERDP_SERVER_PROXY_FILTERS_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include "filters/filters_api.h"
|
||||
|
||||
/* filter init method */
|
||||
typedef BOOL (*filterInitFn)(proxyEvents* events);
|
||||
|
||||
typedef wArrayList filters_list;
|
||||
typedef struct proxy_filter proxyFilter;
|
||||
|
||||
typedef enum _PF_FILTER_TYPE PF_FILTER_TYPE;
|
||||
enum _PF_FILTER_TYPE
|
||||
{
|
||||
FILTER_TYPE_KEYBOARD,
|
||||
FILTER_TYPE_MOUSE
|
||||
};
|
||||
|
||||
struct proxy_filter
|
||||
{
|
||||
/* Handle to the loaded library. Used for freeing the library */
|
||||
HMODULE handle;
|
||||
|
||||
char* name;
|
||||
BOOL enabled;
|
||||
proxyEvents* events;
|
||||
};
|
||||
|
||||
BOOL pf_filters_init(filters_list** list);
|
||||
BOOL pf_filters_register_new(filters_list* list, const char* module_path, const char* filter_name);
|
||||
PF_FILTER_RESULT pf_filters_run_by_type(filters_list* list, PF_FILTER_TYPE type,
|
||||
connectionInfo* info,
|
||||
void* param);
|
||||
void pf_filters_unregister_all(filters_list* list);
|
||||
|
||||
#define RUN_FILTER(_filters,_type,_conn_info,_event_info,_ret,_cb,...) do { \
|
||||
switch(pf_filters_run_by_type(_filters,_type,_conn_info,_event_info)) { \
|
||||
case FILTER_PASS: \
|
||||
_ret = _cb(__VA_ARGS__); \
|
||||
break; \
|
||||
case FILTER_IGNORE: \
|
||||
_ret = TRUE; \
|
||||
break; \
|
||||
case FILTER_DROP: \
|
||||
default: \
|
||||
_ret = FALSE; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_FILTERS_H */
|
||||
@@ -32,15 +32,22 @@ static BOOL pf_server_synchronize_event(rdpInput* input, UINT32 flags)
|
||||
|
||||
static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
rdpContext* context = (rdpContext*) pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
proxyKeyboardEventInfo event;
|
||||
|
||||
if (!config->Keyboard)
|
||||
return TRUE;
|
||||
|
||||
return freerdp_input_send_keyboard_event(context->input, flags, code);
|
||||
event.flags = flags;
|
||||
event.rdp_scan_code = code;
|
||||
|
||||
RUN_FILTER(config->Filters, FILTER_TYPE_KEYBOARD, ps->pdata->info, &event, result,
|
||||
freerdp_input_send_keyboard_event, context->input, flags, code);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL pf_server_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
@@ -58,15 +65,23 @@ 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)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
pServerContext* ps = (pServerContext*)input->context;
|
||||
pClientContext* pc = ps->pdata->pc;
|
||||
rdpContext* context = (rdpContext*) pc;
|
||||
proxyConfig* config = ps->pdata->config;
|
||||
proxyMouseEventInfo event;
|
||||
|
||||
if (!config->Mouse)
|
||||
return TRUE;
|
||||
|
||||
return freerdp_input_send_mouse_event(context->input, flags, x, y);
|
||||
event.flags = flags;
|
||||
event.x = x;
|
||||
event.y = y;
|
||||
|
||||
RUN_FILTER(config->Filters, FILTER_TYPE_MOUSE, ps->pdata->info, &event, result,
|
||||
freerdp_input_send_mouse_event, context->input, flags, x, y);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL pf_server_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
|
||||
|
||||
@@ -71,7 +71,7 @@ static void pf_server_handle_client_disconnection(freerdp_peer* client)
|
||||
CloseHandle(ps->thread);
|
||||
}
|
||||
|
||||
static BOOL pf_server_parse_target_from_routing_token(freerdp_peer* client,
|
||||
static BOOL pf_server_parse_target_from_routing_token(rdpContext* context,
|
||||
char** target, DWORD* port)
|
||||
{
|
||||
#define TARGET_MAX (100)
|
||||
@@ -80,39 +80,70 @@ static BOOL pf_server_parse_target_from_routing_token(freerdp_peer* client,
|
||||
size_t len;
|
||||
const size_t prefix_len = strlen(ROUTING_TOKEN_PREFIX);
|
||||
DWORD routing_token_length;
|
||||
const char* routing_token = freerdp_nego_get_routing_token(client->context, &routing_token_length);
|
||||
const char* routing_token = freerdp_nego_get_routing_token(context, &routing_token_length);
|
||||
|
||||
if (routing_token &&
|
||||
(routing_token_length > prefix_len) && (routing_token_length < TARGET_MAX))
|
||||
if (routing_token == NULL)
|
||||
{
|
||||
len = routing_token_length - prefix_len;
|
||||
*target = malloc(len + 1);
|
||||
|
||||
if (!(*target))
|
||||
return FALSE;
|
||||
|
||||
CopyMemory(*target, routing_token + prefix_len, len);
|
||||
*(*target + len) = '\0';
|
||||
colon = strchr(*target, ':');
|
||||
WLog_INFO(TAG, "Target [parsed from routing token]: %s", *target);
|
||||
|
||||
if (colon)
|
||||
{
|
||||
/* port is specified */
|
||||
unsigned long p = strtoul(colon + 1, NULL, 10);
|
||||
|
||||
if (p > USHRT_MAX)
|
||||
return FALSE;
|
||||
|
||||
*port = (DWORD)p;
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
/* no routing token */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* no routing token */
|
||||
return FALSE;
|
||||
if ((routing_token_length <= prefix_len) || (routing_token_length >= TARGET_MAX))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_server_parse_target_from_routing_token: bad routing token length: %i",
|
||||
routing_token_length);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
len = routing_token_length - prefix_len;
|
||||
*target = malloc(len + 1);
|
||||
|
||||
if (!(*target))
|
||||
return FALSE;
|
||||
|
||||
CopyMemory(*target, routing_token + prefix_len, len);
|
||||
*(*target + len) = '\0';
|
||||
colon = strchr(*target, ':');
|
||||
WLog_INFO(TAG, "Target [parsed from routing token]: %s", *target);
|
||||
|
||||
if (colon)
|
||||
{
|
||||
/* port is specified */
|
||||
unsigned long p = strtoul(colon + 1, NULL, 10);
|
||||
|
||||
if (p > USHRT_MAX)
|
||||
{
|
||||
free(*target);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*port = (DWORD)p;
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings,
|
||||
proxyConfig* config)
|
||||
{
|
||||
WLog_INFO(TAG, "pf_server_get_target_info: UseLoadBalanceInfo = %d", config->UseLoadBalanceInfo);
|
||||
|
||||
if (config->UseLoadBalanceInfo)
|
||||
return pf_server_parse_target_from_routing_token(context, &settings->ServerHostname,
|
||||
&settings->ServerPort);
|
||||
|
||||
/* use hardcoded target info from configuration */
|
||||
if (!(settings->ServerHostname = _strdup(config->TargetHost)))
|
||||
{
|
||||
WLog_DBG(TAG, "pf_server_get_target_info(): strdup failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
settings->ServerPort = config->TargetPort > 0 ? 3389 : settings->ServerPort;
|
||||
WLog_INFO(TAG, "Using target host from config: %s:%i", settings->ServerHostname,
|
||||
settings->ServerPort);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Event callbacks */
|
||||
@@ -125,47 +156,35 @@ static BOOL pf_server_parse_target_from_routing_token(freerdp_peer* client,
|
||||
*/
|
||||
static BOOL pf_server_post_connect(freerdp_peer* client)
|
||||
{
|
||||
proxyConfig* config;
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
HANDLE connectionClosedEvent;
|
||||
rdpContext* pc;
|
||||
proxyData* pdata;
|
||||
char* host = NULL;
|
||||
DWORD port = 3389; /* default port */
|
||||
|
||||
ps = (pServerContext*)client->context;
|
||||
pdata = ps->pdata;
|
||||
config = pdata->config;
|
||||
|
||||
if (config->UseLoadBalanceInfo)
|
||||
{
|
||||
if (!pf_server_parse_target_from_routing_token(client, &host, &port))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_server_parse_target_from_routing_token failed!");
|
||||
return FALSE;
|
||||
}
|
||||
pc = p_client_context_create(client->settings);
|
||||
|
||||
WLog_DBG(TAG, "Parsed target from load-balance-info: %s:%i", host, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use hardcoded target info from configuration */
|
||||
host = _strdup(config->TargetHost);
|
||||
port = config->TargetPort > 0 ? config->TargetPort : port;
|
||||
WLog_DBG(TAG, "Using hardcoded target host: %s:%i", host, port);
|
||||
}
|
||||
|
||||
pc = (pClientContext*) p_client_context_create(client->settings, host, port);
|
||||
connectionClosedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
/* keep both sides of the connection in pdata */
|
||||
pc->pdata = ps->pdata;
|
||||
pdata->pc = (pClientContext*) pc;
|
||||
pdata->ps = ps;
|
||||
pdata->connectionClosed = connectionClosedEvent;
|
||||
((pClientContext*)pc)->pdata = ps->pdata;
|
||||
pdata->pc = (pClientContext*)pc;
|
||||
|
||||
if (!pf_server_get_target_info(client->context, pc->settings, pdata->config))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_server_post_connect(): pf_server_get_target_info failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!proxy_data_set_connection_info(pdata, client->settings, pc->settings->ServerHostname))
|
||||
{
|
||||
WLog_ERR(TAG, "proxy_data_set_connection_info failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pf_server_rdpgfx_init(ps);
|
||||
|
||||
/* Start a proxy's client in it's own thread */
|
||||
if (!(ps->thread = CreateThread(NULL, 0, pf_client_start, (rdpContext*) pc, 0,
|
||||
NULL)))
|
||||
if (!(ps->thread = CreateThread(NULL, 0, pf_client_start, pc, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
return FALSE;
|
||||
@@ -202,18 +221,25 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
rdpContext* pc;
|
||||
proxyData* pdata;
|
||||
proxyConfig* config;
|
||||
freerdp_peer* client = (freerdp_peer*) arg;
|
||||
freerdp_peer* client = (freerdp_peer*)arg;
|
||||
|
||||
if (!init_p_server_context(client))
|
||||
goto out_free_peer;
|
||||
|
||||
ps = (pServerContext*)client->context;
|
||||
if (!(ps->dynvcReady = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
freerdp_peer_free(client);
|
||||
return 0;
|
||||
WLog_ERR(TAG, "pf_server_post_connect(): CreateEvent failed!");
|
||||
goto out_free_peer;
|
||||
}
|
||||
|
||||
ps = (pServerContext*) client->context;
|
||||
ps->dynvcReady = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
pdata = calloc(1, sizeof(proxyData));
|
||||
ps->pdata = pdata;
|
||||
if (!(pdata = ps->pdata = proxy_data_new()))
|
||||
{
|
||||
WLog_ERR(TAG, "pf_server_post_connect(): proxy_data_new failed!");
|
||||
goto out_free_peer;
|
||||
}
|
||||
|
||||
pdata->ps = ps;
|
||||
/* keep configuration in proxyData */
|
||||
pdata->config = client->ContextExtra;
|
||||
config = pdata->config;
|
||||
@@ -223,12 +249,11 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
client->settings->PrivateKeyFile = _strdup("server.key");
|
||||
client->settings->RdpKeyFile = _strdup("server.key");
|
||||
|
||||
if (!client->settings->CertificateFile || !client->settings->PrivateKeyFile
|
||||
|| !client->settings->RdpKeyFile)
|
||||
if (!client->settings->CertificateFile || !client->settings->PrivateKeyFile ||
|
||||
!client->settings->RdpKeyFile)
|
||||
{
|
||||
WLog_ERR(TAG, "Memory allocation failed (strdup)");
|
||||
freerdp_peer_free(client);
|
||||
return 0;
|
||||
goto out_free_peer;
|
||||
}
|
||||
|
||||
client->settings->RdpSecurity = config->RdpSecurity;
|
||||
@@ -247,8 +272,7 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
pf_server_register_update_callbacks(client->update);
|
||||
client->settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */
|
||||
client->Initialize(client);
|
||||
WLog_INFO(TAG, "Client connected: %s",
|
||||
client->local ? "(local)" : client->hostname);
|
||||
WLog_INFO(TAG, "Client connected: %s", client->local ? "(local)" : client->hostname);
|
||||
/* Main client event handling loop */
|
||||
ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm);
|
||||
|
||||
@@ -256,8 +280,7 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
{
|
||||
eventCount = 0;
|
||||
{
|
||||
tmp = client->GetEventHandles(client, &eventHandles[eventCount],
|
||||
32 - eventCount);
|
||||
tmp = client->GetEventHandles(client, &eventHandles[eventCount], 32 - eventCount);
|
||||
|
||||
if (tmp == 0)
|
||||
{
|
||||
@@ -295,28 +318,28 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg)
|
||||
|
||||
switch (WTSVirtualChannelManagerGetDrdynvcState(ps->vcm))
|
||||
{
|
||||
/* Dynamic channel status may have been changed after processing */
|
||||
case DRDYNVC_STATE_NONE:
|
||||
/* Dynamic channel status may have been changed after processing */
|
||||
case DRDYNVC_STATE_NONE:
|
||||
|
||||
/* Initialize drdynvc channel */
|
||||
if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to initialize drdynvc channel");
|
||||
goto fail;
|
||||
}
|
||||
/* Initialize drdynvc channel */
|
||||
if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to initialize drdynvc channel");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case DRDYNVC_STATE_READY:
|
||||
if (WaitForSingleObject(ps->dynvcReady, 0) == WAIT_TIMEOUT)
|
||||
{
|
||||
SetEvent(ps->dynvcReady);
|
||||
}
|
||||
case DRDYNVC_STATE_READY:
|
||||
if (WaitForSingleObject(ps->dynvcReady, 0) == WAIT_TIMEOUT)
|
||||
{
|
||||
SetEvent(ps->dynvcReady);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,24 +350,23 @@ fail:
|
||||
pf_server_handle_client_disconnection(client);
|
||||
}
|
||||
|
||||
pc = (rdpContext*) pdata->pc;
|
||||
pc = (rdpContext*)pdata->pc;
|
||||
freerdp_client_stop(pc);
|
||||
free(pdata);
|
||||
proxy_data_free(pdata);
|
||||
freerdp_client_context_free(pc);
|
||||
client->Disconnect(client);
|
||||
out_free_peer:
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL pf_server_client_connected(freerdp_listener* listener,
|
||||
freerdp_peer* client)
|
||||
static BOOL pf_server_client_connected(freerdp_listener* listener, freerdp_peer* client)
|
||||
{
|
||||
HANDLE hThread;
|
||||
client->ContextExtra = listener->info;
|
||||
|
||||
if (!(hThread = CreateThread(NULL, 0, pf_server_handle_client,
|
||||
(void*) client, 0, NULL)))
|
||||
if (!(hThread = CreateThread(NULL, 0, pf_server_handle_client, (void*)client, 0, NULL)))
|
||||
return FALSE;
|
||||
|
||||
CloseHandle(hThread);
|
||||
@@ -408,7 +430,7 @@ int pf_server_start(proxyConfig* config)
|
||||
}
|
||||
|
||||
/* Determine filepath for local socket */
|
||||
sprintf_s(localSockName, sizeof(localSockName), "proxy.%"PRIu16"", config->Port);
|
||||
sprintf_s(localSockName, sizeof(localSockName), "proxy.%" PRIu16 "", config->Port);
|
||||
localSockPath = GetKnownSubPath(KNOWN_PATH_TEMP, localSockName);
|
||||
|
||||
if (!localSockPath)
|
||||
|
||||
Reference in New Issue
Block a user