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