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
65static 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
75static 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
142static 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 */
169static 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;
203fail:
204 mf_peer_context_free(client, context);
205 return FALSE;
206}
207
208/* Called after a peer disconnects */
209static 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 */
236static 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
265static 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
316static 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
333static BOOL mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
334{
335 return TRUE;
336}
337
338static 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
349static BOOL mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
350{
351 return FALSE;
352}
353
354static BOOL mf_peer_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
355{
356 return FALSE;
357}
358
359static 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);
465fail:
466 freerdp_peer_free(client);
467 return NULL;
468}
469
470BOOL 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