FreeRDP
mf_peer.c
1 
20 #include <freerdp/config.h>
21 
22 #include <freerdp/listener.h>
23 #include <freerdp/codec/rfx.h>
24 #include <winpr/stream.h>
25 #include <freerdp/peer.h>
26 #include <freerdp/codec/color.h>
27 
28 #include <winpr/crt.h>
29 #include <winpr/assert.h>
30 
31 #include "mf_peer.h"
32 #include "mf_info.h"
33 #include "mf_input.h"
34 #include "mf_event.h"
35 #include "mf_rdpsnd.h"
36 #include "mf_audin.h"
37 
38 #include <mach/clock.h>
39 #include <mach/mach.h>
40 #include <dispatch/dispatch.h>
41 
42 #include "OpenGL/OpenGL.h"
43 #include "OpenGL/gl.h"
44 
45 #include "CoreVideo/CoreVideo.h"
46 
47 #include <freerdp/log.h>
48 #define TAG SERVER_TAG("mac")
49 
50 // refactor these
51 static int info_last_sec = 0;
52 static int info_last_nsec = 0;
53 
54 static dispatch_source_t info_timer;
55 static dispatch_queue_t info_queue;
56 
57 static mfEventQueue* info_event_queue;
58 
59 static CGLContextObj glContext;
60 static CGContextRef bmp;
61 static CGImageRef img;
62 
63 static void mf_peer_context_free(freerdp_peer* client, rdpContext* context);
64 
65 static BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
66 {
67  if (info_event_queue->pipe_fd[0] == -1)
68  return TRUE;
69 
70  rfds[*rcount] = (void*)(long)info_event_queue->pipe_fd[0];
71  (*rcount)++;
72  return TRUE;
73 }
74 
75 static void mf_peer_rfx_update(freerdp_peer* client)
76 {
77  // check
78  mfInfo* mfi = mf_info_get_instance();
79  mf_info_find_invalid_region(mfi);
80 
81  if (mf_info_have_invalid_region(mfi) == false)
82  {
83  return;
84  }
85 
86  long width;
87  long height;
88  int pitch;
89  BYTE* dataBits = NULL;
90  mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
91  mf_info_clear_invalid_region(mfi);
92  // encode
93  wStream* s;
94  RFX_RECT rect;
95  rdpUpdate* update;
96  mfPeerContext* mfp;
97  SURFACE_BITS_COMMAND cmd = { 0 };
98 
99  WINPR_ASSERT(client);
100 
101  mfp = (mfPeerContext*)client->context;
102  WINPR_ASSERT(mfp);
103 
104  update = client->context->update;
105  WINPR_ASSERT(update);
106 
107  s = mfp->s;
108  WINPR_ASSERT(s);
109 
110  Stream_Clear(s);
111  Stream_SetPosition(s, 0);
112  UINT32 x = mfi->invalid.x / mfi->scale;
113  UINT32 y = mfi->invalid.y / mfi->scale;
114  rect.x = 0;
115  rect.y = 0;
116  rect.width = width;
117  rect.height = height;
118 
119  rfx_context_reset(mfp->rfx_context, mfi->servscreen_width, mfi->servscreen_height);
120 
121  if (!(rfx_compose_message(mfp->rfx_context, s, &rect, 1, (BYTE*)dataBits, rect.width,
122  rect.height, pitch)))
123  {
124  return;
125  }
126 
127  cmd.destLeft = x;
128  cmd.destTop = y;
129  cmd.destRight = x + rect.width;
130  cmd.destBottom = y + rect.height;
131  cmd.bmp.bpp = 32;
132  cmd.bmp.codecID = 3;
133  cmd.bmp.width = rect.width;
134  cmd.bmp.height = rect.height;
135  cmd.bmp.bitmapDataLength = Stream_GetPosition(s);
136  cmd.bmp.bitmapData = Stream_Buffer(s);
137  // send
138  update->SurfaceBits(update->context, &cmd);
139  // clean up... maybe?
140 }
141 
142 static BOOL mf_peer_check_fds(freerdp_peer* client)
143 {
144  mfPeerContext* context = (mfPeerContext*)client->context;
145  mfEvent* event;
146 
147  if (context->activated == FALSE)
148  return TRUE;
149 
150  event = mf_event_peek(info_event_queue);
151 
152  if (event != NULL)
153  {
154  if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_REGION)
155  {
156  }
157  else if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK)
158  {
159  event = mf_event_pop(info_event_queue);
160  mf_peer_rfx_update(client);
161  mf_event_free(event);
162  }
163  }
164 
165  return TRUE;
166 }
167 
168 /* Called when we have a new peer connecting */
169 static BOOL mf_peer_context_new(freerdp_peer* client, rdpContext* context)
170 {
171  rdpSettings* settings;
172  mfPeerContext* peer = (mfPeerContext*)context;
173 
174  WINPR_ASSERT(client);
175  WINPR_ASSERT(context);
176 
177  settings = context->settings;
178  WINPR_ASSERT(settings);
179 
180  if (!(peer->info = mf_info_get_instance()))
181  return FALSE;
182 
183  if (!(peer->rfx_context = rfx_context_new_ex(
184  TRUE, freerdp_settings_get_uint32(settings, FreeRDP_ThreadingFlags))))
185  goto fail;
186 
187  rfx_context_reset(peer->rfx_context,
188  freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
189  freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
190  rfx_context_set_mode(peer->rfx_context, RLGR3);
191  rfx_context_set_pixel_format(peer->rfx_context, PIXEL_FORMAT_BGRA32);
192 
193  if (!(peer->s = Stream_New(NULL, 0xFFFF)))
194  goto fail;
195 
196  peer->vcm = WTSOpenServerA((LPSTR)client->context);
197 
198  if (!peer->vcm || (peer->vcm == INVALID_HANDLE_VALUE))
199  goto fail;
200 
201  mf_info_peer_register(peer->info, peer);
202  return TRUE;
203 fail:
204  mf_peer_context_free(client, context);
205  return FALSE;
206 }
207 
208 /* Called after a peer disconnects */
209 static void mf_peer_context_free(freerdp_peer* client, rdpContext* context)
210 {
211  mfPeerContext* peer = (mfPeerContext*)context;
212  if (context)
213  {
214  mf_info_peer_unregister(peer->info, peer);
215  dispatch_suspend(info_timer);
216  Stream_Free(peer->s, TRUE);
217  rfx_context_free(peer->rfx_context);
218  // nsc_context_free(peer->nsc_context);
219 #ifdef CHANNEL_AUDIN_SERVER
220 
221  mf_peer_audin_uninit(peer);
222 
223 #endif
224 #ifdef CHANNEL_RDPSND_SERVER
225  mf_peer_rdpsnd_stop();
226 
227  if (peer->rdpsnd)
228  rdpsnd_server_context_free(peer->rdpsnd);
229 
230 #endif
231  WTSCloseServer(peer->vcm);
232  }
233 }
234 
235 /* Called when a new client connects */
236 static BOOL mf_peer_init(freerdp_peer* client)
237 {
238  client->ContextSize = sizeof(mfPeerContext);
239  client->ContextNew = mf_peer_context_new;
240  client->ContextFree = mf_peer_context_free;
241 
242  if (!freerdp_peer_context_new(client))
243  return FALSE;
244 
245  info_event_queue = mf_event_queue_new();
246  info_queue = dispatch_queue_create("FreeRDP.update.timer", DISPATCH_QUEUE_SERIAL);
247  info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
248 
249  if (info_timer)
250  {
251  // DEBUG_WARN( "created timer\n");
252  dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC,
253  100ull * NSEC_PER_MSEC);
254  dispatch_source_set_event_handler(info_timer, ^{
255  // DEBUG_WARN( "dispatch\n");
256  mfEvent* event = mf_event_new(FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK);
257  mf_event_push(info_event_queue, (mfEvent*)event);
258  });
259  dispatch_resume(info_timer);
260  }
261 
262  return TRUE;
263 }
264 
265 static BOOL mf_peer_post_connect(freerdp_peer* client)
266 {
267  mfInfo* mfi = mf_info_get_instance();
268 
269  WINPR_ASSERT(client);
270 
271  mfPeerContext* context = (mfPeerContext*)client->context;
272  WINPR_ASSERT(context);
273 
274  rdpSettings* settings = client->context->settings;
275  WINPR_ASSERT(settings);
276 
277  mfi->scale = 1;
278  // mfi->servscreen_width = 2880 / mfi->scale;
279  // mfi->servscreen_height = 1800 / mfi->scale;
280  UINT32 bitsPerPixel = 32;
281 
282  if ((freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) != mfi->servscreen_width) ||
283  (freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) != mfi->servscreen_height))
284  {
285  }
286 
287  if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, mfi->servscreen_width))
288  return FALSE;
289  if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, mfi->servscreen_height))
290  return FALSE;
291  if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, bitsPerPixel))
292  return FALSE;
293 
294  WINPR_ASSERT(client->context->update);
295  WINPR_ASSERT(client->context->update->DesktopResize);
296  client->context->update->DesktopResize(client->context);
297 
298  mfi->mouse_down_left = FALSE;
299  mfi->mouse_down_right = FALSE;
300  mfi->mouse_down_other = FALSE;
301 #ifdef CHANNEL_RDPSND_SERVER
302 
303  if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd"))
304  {
305  mf_peer_rdpsnd_init(context); /* Audio Output */
306  }
307 
308 #endif
309  /* Dynamic Virtual Channels */
310 #ifdef CHANNEL_AUDIN_SERVER
311  mf_peer_audin_init(context); /* Audio Input */
312 #endif
313  return TRUE;
314 }
315 
316 static BOOL mf_peer_activate(freerdp_peer* client)
317 {
318  WINPR_ASSERT(client);
319 
320  mfPeerContext* context = (mfPeerContext*)client->context;
321  WINPR_ASSERT(context);
322 
323  rdpSettings* settings = client->context->settings;
324  WINPR_ASSERT(settings);
325 
326  rfx_context_reset(context->rfx_context,
327  freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
328  freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
329  context->activated = TRUE;
330  return TRUE;
331 }
332 
333 static BOOL mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
334 {
335  return TRUE;
336 }
337 
338 static BOOL mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
339 {
340  bool state_down = FALSE;
341 
342  if (flags == KBD_FLAGS_DOWN)
343  {
344  state_down = TRUE;
345  }
346  return TRUE;
347 }
348 
349 static BOOL mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
350 {
351  return FALSE;
352 }
353 
354 static BOOL mf_peer_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
355 {
356  return FALSE;
357 }
358 
359 static void* mf_peer_main_loop(void* arg)
360 {
361  mfPeerContext* context;
362  rdpSettings* settings;
363  rdpInput* input;
364  rdpUpdate* update;
365  freerdp_peer* client = (freerdp_peer*)arg;
366 
367  if (!mf_peer_init(client))
368  goto fail;
369 
370  const mf_server_info* info = client->ContextExtra;
371  WINPR_ASSERT(info);
372 
373  WINPR_ASSERT(client->context);
374 
375  settings = client->context->settings;
376  WINPR_ASSERT(settings);
377 
378  /* Initialize the real server settings here */
379  rdpPrivateKey* key = freerdp_key_new_from_file(info->key);
380  if (!key)
381  goto fail;
382  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerRsaKey, key, 1))
383  goto fail;
384  rdpCertificate* cert = freerdp_certificate_new_from_file(info->cert);
385  if (!cert)
386  goto fail;
387  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, cert, 1))
388  goto fail;
389 
390  if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
391  goto fail;
392  if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE))
393  goto fail;
394  if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32))
395  goto fail;
396 
397  if (!freerdp_settings_set_bool(settings, FreeRDP_SuppressOutput, TRUE))
398  goto fail;
399  if (!freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, FALSE))
400  goto fail;
401 
402  client->PostConnect = mf_peer_post_connect;
403  client->Activate = mf_peer_activate;
404 
405  input = client->context->input;
406  WINPR_ASSERT(input);
407 
408  input->SynchronizeEvent = mf_peer_synchronize_event;
409  input->KeyboardEvent = mf_input_keyboard_event; // mf_peer_keyboard_event;
410  input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
411  input->MouseEvent = mf_input_mouse_event;
412  input->ExtendedMouseEvent = mf_input_extended_mouse_event;
413 
414  update = client->context->update;
415  WINPR_ASSERT(update);
416 
417  // update->RefreshRect = mf_peer_refresh_rect;
418  update->SuppressOutput = mf_peer_suppress_output;
419 
420  WINPR_ASSERT(client->Initialize);
421  const BOOL rc = client->Initialize(client);
422  if (!rc)
423  goto fail;
424  context = (mfPeerContext*)client->context;
425 
426  while (1)
427  {
428  DWORD status;
429  HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
430  DWORD count = client->GetEventHandles(client, handles, ARRAYSIZE(handles));
431 
432  if ((count == 0) || (count == MAXIMUM_WAIT_OBJECTS))
433  {
434  WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
435  break;
436  }
437 
438  handles[count++] = WTSVirtualChannelManagerGetEventHandle(context->vcm);
439 
440  status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
441  if (status == WAIT_FAILED)
442  {
443  WLog_ERR(TAG, "WaitForMultipleObjects failed");
444  break;
445  }
446 
447  if (client->CheckFileDescriptor(client) != TRUE)
448  {
449  break;
450  }
451 
452  if ((mf_peer_check_fds(client)) != TRUE)
453  {
454  break;
455  }
456 
457  if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
458  {
459  break;
460  }
461  }
462 
463  client->Disconnect(client);
464  freerdp_peer_context_free(client);
465 fail:
466  freerdp_peer_free(client);
467  return NULL;
468 }
469 
470 BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
471 {
472  pthread_t th;
473 
474  WINPR_ASSERT(instance);
475  WINPR_ASSERT(client);
476 
477  client->ContextExtra = instance->info;
478  if (pthread_create(&th, 0, mf_peer_main_loop, client) == 0)
479  {
480  pthread_detach(th);
481  return TRUE;
482  }
483 
484  return FALSE;
485 }
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.
Definition: rfx.h:44