FreeRDP
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 
48 static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam);
49 
50 static 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 
73 static 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 
91 static 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 
99 static 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 
153 static 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 
165 static 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 
173 static BOOL wf_peer_synchronize_event(rdpInput* input, UINT32 flags)
174 {
175  return TRUE;
176 }
177 
178 BOOL 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 
189 static 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 
230 static 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(PrivateKeyFile);
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 
270 DWORD 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);
401 fail_socket_thread:
402  (void)CloseHandle(context->socketSemaphore);
403  context->socketSemaphore = NULL;
404 fail_socket_semaphore:
405  (void)CloseHandle(context->socketEvent);
406  context->socketEvent = NULL;
407 fail_socket_event:
408 fail_socked_closed:
409 fail_client_initialize:
410  freerdp_peer_context_free(client);
411 fail_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.