FreeRDP
Loading...
Searching...
No Matches
wf_peer.c
1
21#include <freerdp/config.h>
22
23#include <winpr/assert.h>
24#include <winpr/tchar.h>
25#include <winpr/stream.h>
26#include <winpr/windows.h>
27
28#include <freerdp/listener.h>
29#include <freerdp/codec/rfx.h>
30#include <freerdp/build-config.h>
31#include <freerdp/crypto/certificate.h>
32
33#include "wf_info.h"
34#include "wf_input.h"
35#include "wf_mirage.h"
36#include "wf_update.h"
37#include "wf_settings.h"
38#include "wf_rdpsnd.h"
39
40#include "wf_peer.h"
41#include <freerdp/peer.h>
42
43#include <freerdp/log.h>
44#define TAG SERVER_TAG("windows")
45
46#define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING
47
48static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam);
49
50static BOOL wf_peer_context_new(freerdp_peer* client, rdpContext* ctx)
51{
52 wfPeerContext* context = (wfPeerContext*)ctx;
53 WINPR_ASSERT(context);
54
55 if (!(context->info = wf_info_get_instance()))
56 return FALSE;
57
58 context->vcm = WTSOpenServerA((LPSTR)client->context);
59
60 if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
61 return FALSE;
62
63 if (!wf_info_peer_register(context->info, context))
64 {
65 WTSCloseServer(context->vcm);
66 context->vcm = NULL;
67 return FALSE;
68 }
69
70 return TRUE;
71}
72
73static void wf_peer_context_free(freerdp_peer* client, rdpContext* ctx)
74{
75 wfPeerContext* context = (wfPeerContext*)ctx;
76 WINPR_ASSERT(context);
77
78 wf_info_peer_unregister(context->info, context);
79
80 if (context->rdpsnd)
81 {
82 wf_rdpsnd_lock();
83 context->info->snd_stop = TRUE;
84 rdpsnd_server_context_free(context->rdpsnd);
85 wf_rdpsnd_unlock();
86 }
87
88 WTSCloseServer(context->vcm);
89}
90
91static BOOL wf_peer_init(freerdp_peer* client)
92{
93 client->ContextSize = sizeof(wfPeerContext);
94 client->ContextNew = wf_peer_context_new;
95 client->ContextFree = wf_peer_context_free;
96 return freerdp_peer_context_new(client);
97}
98
99static BOOL wf_peer_post_connect(freerdp_peer* client)
100{
101 wfInfo* wfi;
102 rdpSettings* settings;
103 wfPeerContext* context;
104
105 WINPR_ASSERT(client);
106
107 context = (wfPeerContext*)client->context;
108 WINPR_ASSERT(context);
109
110 wfi = context->info;
111 WINPR_ASSERT(wfi);
112
113 settings = client->context->settings;
114 WINPR_ASSERT(settings);
115
116 if ((get_screen_info(wfi->screenID, NULL, 0, &wfi->servscreen_width, &wfi->servscreen_height,
117 &wfi->bitsPerPixel) == 0) ||
118 (wfi->servscreen_width == 0) || (wfi->servscreen_height == 0) || (wfi->bitsPerPixel == 0))
119 {
120 WLog_ERR(TAG, "postconnect: error getting screen info for screen %d", wfi->screenID);
121 WLog_ERR(TAG, "\t%dx%dx%d", wfi->servscreen_height, wfi->servscreen_width,
122 wfi->bitsPerPixel);
123 return FALSE;
124 }
125
126 if ((freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) != wfi->servscreen_width) ||
127 (freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) != wfi->servscreen_height))
128 {
129 /*
130 WLog_DBG(TAG, "Client requested resolution %"PRIu32"x%"PRIu32", but will resize to %dx%d",
131 freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
132 freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight), wfi->servscreen_width,
133 wfi->servscreen_height);
134 */
135 if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, wfi->servscreen_width) ||
136 !freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, wfi->servscreen_height) ||
137 !freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, wfi->bitsPerPixel))
138 return FALSE;
139
140 WINPR_ASSERT(client->context->update);
141 WINPR_ASSERT(client->context->update->DesktopResize);
142 client->context->update->DesktopResize(client->context);
143 }
144
145 if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd"))
146 {
147 wf_peer_rdpsnd_init(context); /* Audio Output */
148 }
149
150 return TRUE;
151}
152
153static BOOL wf_peer_activate(freerdp_peer* client)
154{
155 wfInfo* wfi;
156 wfPeerContext* context = (wfPeerContext*)client->context;
157 wfi = context->info;
158 client->activated = TRUE;
159 wf_update_peer_activate(wfi, context);
160 wfreerdp_server_peer_callback_event(((rdpContext*)context)->peer->pId,
161 FREERDP_SERVER_WIN_SRV_CALLBACK_EVENT_ACTIVATE);
162 return TRUE;
163}
164
165static BOOL wf_peer_logon(freerdp_peer* client, const SEC_WINNT_AUTH_IDENTITY* identity,
166 BOOL automatic)
167{
168 wfreerdp_server_peer_callback_event(((rdpContext*)client->context)->peer->pId,
169 FREERDP_SERVER_WIN_SRV_CALLBACK_EVENT_AUTH);
170 return TRUE;
171}
172
173static BOOL wf_peer_synchronize_event(rdpInput* input, UINT32 flags)
174{
175 return TRUE;
176}
177
178BOOL wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
179{
180 HANDLE hThread;
181
182 if (!(hThread = CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL)))
183 return FALSE;
184
185 (void)CloseHandle(hThread);
186 return TRUE;
187}
188
189static DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
190{
191 wfPeerContext* context;
192 freerdp_peer* client = (freerdp_peer*)lpParam;
193
194 WINPR_ASSERT(client);
195 WINPR_ASSERT(client->GetEventHandles);
196 WINPR_ASSERT(client->CheckFileDescriptor);
197
198 context = (wfPeerContext*)client->context;
199 WINPR_ASSERT(context);
200
201 while (1)
202 {
203 DWORD status;
204 HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
205 DWORD count = client->GetEventHandles(client, handles, ARRAYSIZE(handles));
206
207 if (count == 0)
208 {
209 WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
210 break;
211 }
212
213 status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
214 if (status == WAIT_FAILED)
215 {
216 WLog_ERR(TAG, "WaitForMultipleObjects failed");
217 break;
218 }
219
220 (void)SetEvent(context->socketEvent);
221 (void)WaitForSingleObject(context->socketSemaphore, INFINITE);
222
223 if (context->socketClose)
224 break;
225 }
226
227 return 0;
228}
229
230static BOOL wf_peer_read_settings(freerdp_peer* client)
231{
232 rdpSettings* settings;
233
234 WINPR_ASSERT(client);
235 WINPR_ASSERT(client->context);
236
237 settings = client->context->settings;
238 WINPR_ASSERT(settings);
239
240 char* CertificateFile = NULL;
241 if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, SERVER_KEY, _T("CertificateFile"),
242 &(CertificateFile)))
243 CertificateFile = _strdup("server.crt");
244
245 rdpCertificate* cert = freerdp_certificate_new_from_file(CertificateFile);
246 free(CertificateFile);
247 if (!cert)
248 return FALSE;
249
250 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, cert, 1))
251 return FALSE;
252
253 char* PrivateKeyFile = NULL;
254 if (!wf_settings_read_string_ascii(HKEY_LOCAL_MACHINE, SERVER_KEY, _T("PrivateKeyFile"),
255 &(PrivateKeyFile)))
256 PrivateKeyFile = _strdup("server.key");
257
258 rdpPrivateKey* key = freerdp_key_new_from_file_enc(PrivateKeyFile, NULL);
259 free(PrivateKeyFile);
260
261 if (!key)
262 return FALSE;
263
264 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerRsaKey, key, 1))
265 return FALSE;
266
267 return TRUE;
268}
269
270DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
271{
272 wfInfo* wfi;
273 DWORD nCount;
274 DWORD status;
275 HANDLE handles[32];
276 rdpSettings* settings;
277 wfPeerContext* context;
278 freerdp_peer* client = (freerdp_peer*)lpParam;
279
280 if (!wf_peer_init(client))
281 goto fail_peer_init;
282
283 WINPR_ASSERT(client->context);
284
285 settings = client->context->settings;
286 WINPR_ASSERT(settings);
287
288 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE))
289 goto fail_peer_init;
290 if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32))
291 goto fail_peer_init;
292 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, FALSE))
293 goto fail_peer_init;
294 if (!freerdp_settings_set_bool(settings, FreeRDP_JpegCodec, FALSE))
295 goto fail_peer_init;
296
297 if (!wf_peer_read_settings(client))
298 goto fail_peer_init;
299
300 client->PostConnect = wf_peer_post_connect;
301 client->Activate = wf_peer_activate;
302 client->Logon = wf_peer_logon;
303
304 WINPR_ASSERT(client->context->input);
305 client->context->input->SynchronizeEvent = wf_peer_synchronize_event;
306 client->context->input->KeyboardEvent = wf_peer_keyboard_event;
307 client->context->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event;
308 client->context->input->MouseEvent = wf_peer_mouse_event;
309 client->context->input->ExtendedMouseEvent = wf_peer_extended_mouse_event;
310
311 WINPR_ASSERT(client->Initialize);
312 if (!client->Initialize(client))
313 goto fail_client_initialize;
314
315 context = (wfPeerContext*)client->context;
316
317 if (context->socketClose)
318 goto fail_socked_closed;
319
320 wfi = context->info;
321
322 if (wfi->input_disabled)
323 {
324 WLog_INFO(TAG, "client input is disabled");
325 client->context->input->KeyboardEvent = wf_peer_keyboard_event_dummy;
326 client->context->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event_dummy;
327 client->context->input->MouseEvent = wf_peer_mouse_event_dummy;
328 client->context->input->ExtendedMouseEvent = wf_peer_extended_mouse_event_dummy;
329 }
330
331 if (!(context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
332 goto fail_socket_event;
333
334 if (!(context->socketSemaphore = CreateSemaphore(NULL, 0, 1, NULL)))
335 goto fail_socket_semaphore;
336
337 if (!(context->socketThread = CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL)))
338 goto fail_socket_thread;
339
340 WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname);
341 nCount = 0;
342 handles[nCount++] = context->updateEvent;
343 handles[nCount++] = context->socketEvent;
344
345 while (1)
346 {
347 status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
348
349 if ((status == WAIT_FAILED) || (status == WAIT_TIMEOUT))
350 {
351 WLog_ERR(TAG, "WaitForMultipleObjects failed");
352 break;
353 }
354
355 if (WaitForSingleObject(context->updateEvent, 0) == 0)
356 {
357 if (client->activated)
358 wf_update_peer_send(wfi, context);
359
360 (void)ResetEvent(context->updateEvent);
361 ReleaseSemaphore(wfi->updateSemaphore, 1, NULL);
362 }
363
364 if (WaitForSingleObject(context->socketEvent, 0) == 0)
365 {
366 if (client->CheckFileDescriptor(client) != TRUE)
367 {
368 WLog_ERR(TAG, "Failed to check peer file descriptor");
369 context->socketClose = TRUE;
370 }
371
372 (void)ResetEvent(context->socketEvent);
373 ReleaseSemaphore(context->socketSemaphore, 1, NULL);
374
375 if (context->socketClose)
376 break;
377 }
378
379 // force disconnect
380 if (wfi->force_all_disconnect == TRUE)
381 {
382 WLog_INFO(TAG, "Forcing Disconnect -> ");
383 break;
384 }
385
386 /* FIXME: we should wait on this, instead of calling it every time */
387 if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
388 break;
389 }
390
391 WLog_INFO(TAG, "Client %s disconnected.", client->local ? "(local)" : client->hostname);
392
393 if (WaitForSingleObject(context->updateEvent, 0) == 0)
394 {
395 (void)ResetEvent(context->updateEvent);
396 ReleaseSemaphore(wfi->updateSemaphore, 1, NULL);
397 }
398
399 wf_update_peer_deactivate(wfi, context);
400 client->Disconnect(client);
401fail_socket_thread:
402 (void)CloseHandle(context->socketSemaphore);
403 context->socketSemaphore = NULL;
404fail_socket_semaphore:
405 (void)CloseHandle(context->socketEvent);
406 context->socketEvent = NULL;
407fail_socket_event:
408fail_socked_closed:
409fail_client_initialize:
410 freerdp_peer_context_free(client);
411fail_peer_init:
412 freerdp_peer_free(client);
413 return 0;
414}
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.