FreeRDP/server/Mac/mf_peer.c

439 lines
10 KiB
C
Raw Normal View History

2014-09-12 19:38:12 +04:00
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Mac OS X Server
*
* Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/listener.h>
#include <freerdp/codec/rfx.h>
#include <winpr/stream.h>
#include <freerdp/peer.h>
2017-11-24 14:46:01 +03:00
#include <freerdp/codec/color.h>
2014-09-12 19:38:12 +04:00
#include <winpr/crt.h>
#include "mf_peer.h"
#include "mf_info.h"
#include "mf_input.h"
#include "mf_event.h"
#include "mf_rdpsnd.h"
2017-11-24 14:46:01 +03:00
#include "mf_audin.h"
2014-09-12 19:38:12 +04:00
#include <mach/clock.h>
#include <mach/mach.h>
#include <dispatch/dispatch.h>
#include "OpenGL/OpenGL.h"
#include "OpenGL/gl.h"
#include "CoreVideo/CoreVideo.h"
2019-11-06 17:24:51 +03:00
// refactor these
2017-11-24 14:46:01 +03:00
static int info_last_sec = 0;
static int info_last_nsec = 0;
2014-09-12 19:38:12 +04:00
2017-11-24 14:46:01 +03:00
static dispatch_source_t info_timer;
static dispatch_queue_t info_queue;
2014-09-12 19:38:12 +04:00
2017-11-24 14:46:01 +03:00
static mfEventQueue* info_event_queue;
2014-09-12 19:38:12 +04:00
2017-11-24 14:46:01 +03:00
static CGLContextObj glContext;
static CGContextRef bmp;
static CGImageRef img;
2014-09-12 19:38:12 +04:00
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
2014-09-12 19:38:12 +04:00
{
if (info_event_queue->pipe_fd[0] == -1)
return TRUE;
2016-10-04 17:54:11 +03:00
2019-11-06 17:24:51 +03:00
rfds[*rcount] = (void*)(long)info_event_queue->pipe_fd[0];
2014-09-12 19:38:12 +04:00
(*rcount)++;
return TRUE;
}
2017-11-24 14:46:01 +03:00
static void mf_peer_rfx_update(freerdp_peer* client)
2014-09-12 19:38:12 +04:00
{
2019-11-06 17:24:51 +03:00
// check
2014-09-12 19:38:12 +04:00
mfInfo* mfi = mf_info_get_instance();
mf_info_find_invalid_region(mfi);
2016-10-04 17:54:11 +03:00
if (mf_info_have_invalid_region(mfi) == false)
{
2014-09-12 19:38:12 +04:00
return;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
long width;
long height;
int pitch;
BYTE* dataBits = NULL;
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
mf_info_clear_invalid_region(mfi);
2019-11-06 17:24:51 +03:00
// encode
2014-09-12 19:38:12 +04:00
wStream* s;
RFX_RECT rect;
rdpUpdate* update;
mfPeerContext* mfp;
2018-08-01 11:04:00 +03:00
SURFACE_BITS_COMMAND cmd = { 0 };
2014-09-12 19:38:12 +04:00
update = client->update;
2019-11-06 17:24:51 +03:00
mfp = (mfPeerContext*)client->context;
2014-09-12 19:38:12 +04:00
s = mfp->s;
Stream_Clear(s);
Stream_SetPosition(s, 0);
UINT32 x = mfi->invalid.x / mfi->scale;
UINT32 y = mfi->invalid.y / mfi->scale;
rect.x = 0;
rect.y = 0;
rect.width = width;
rect.height = height;
mfp->rfx_context->width = mfi->servscreen_width;
mfp->rfx_context->height = mfi->servscreen_height;
2016-10-04 17:54:11 +03:00
2019-11-06 17:24:51 +03:00
if (!(rfx_compose_message(mfp->rfx_context, s, &rect, 1, (BYTE*)dataBits, rect.width,
rect.height, pitch)))
codec/rfx: error checking and various fixes - removed some unneeded null checks for free() - fixed a memory leak in shadow_client - removed rfx_compose_message_header from API Changed the following functions to BOOL, check the result where they are called and handle failures: - rfx_compose_message - rfx_compose_message_header - rfx_write_tile - rfx_write_message_tileset - rfx_write_message_frame_begin - rfx_write_message_region - rfx_write_message_frame_end - rfx_write_message rfx_process_message: - check memory allocation failures - verify protocol-conform order of data messages to prevents memory leaks caused by repeated allocations - verify that header messages were parsed/received before the data messages - treat unknown rlgr mode as error - fixed/added error handling - fixed all callers to check/handle result rfx_encode_message: - fixed incorrect usage of realloc - missing malloc check - missing check of CreateThreadpoolWork - correct cleanup on failure (threadpool, memory) - check rfx_encode_message result rfx_encode_messages: - check rfx_split_message result - correct cleanup on failure - prevent memory leak on failure rfx_write_message_context: - fixed invalid channelId value (must be 0xFF for WBT_CONTEXT) rfx_process_message_codec_versions: - fixed invalid read size of codec_version (it is 16bit) rfx_process_message_channels: - verify protocol conform channelId value rfx_process_message_region: - replaced invalid reallocs with malloc - read and verify regionType and numTileSets from stream rfx_process_message_tileset: - check allocation results - fixed incorrect usages of realloc setupWorkers: - fixed incorrect usages of realloc rfx_split_message: - removed dead code - missing malloc check rfx_compose_message: - fixed a memory leak - check/handle rfx_encode_message result
2015-04-23 16:42:21 +03:00
{
return;
}
2016-10-04 17:54:11 +03:00
2018-08-01 11:04:00 +03:00
cmd.destLeft = x;
cmd.destTop = y;
cmd.destRight = x + rect.width;
cmd.destBottom = y + rect.height;
cmd.bmp.bpp = 32;
cmd.bmp.codecID = 3;
cmd.bmp.width = rect.width;
cmd.bmp.height = rect.height;
cmd.bmp.bitmapDataLength = Stream_GetPosition(s);
cmd.bmp.bitmapData = Stream_Buffer(s);
2019-11-06 17:24:51 +03:00
// send
2018-08-01 11:04:00 +03:00
update->SurfaceBits(update->context, &cmd);
2019-11-06 17:24:51 +03:00
// clean up... maybe?
2014-09-12 19:38:12 +04:00
}
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_check_fds(freerdp_peer* client)
{
2019-11-06 17:24:51 +03:00
mfPeerContext* context = (mfPeerContext*)client->context;
2017-11-24 14:46:01 +03:00
mfEvent* event;
if (context->activated == FALSE)
return TRUE;
event = mf_event_peek(info_event_queue);
if (event != NULL)
{
if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_REGION)
{
}
else if (event->type == FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK)
{
event = mf_event_pop(info_event_queue);
mf_peer_rfx_update(client);
mf_event_free(event);
}
}
return TRUE;
}
2014-09-12 19:38:12 +04:00
/* Called when we have a new peer connecting */
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
2014-09-12 19:38:12 +04:00
{
if (!(context->info = mf_info_get_instance()))
return FALSE;
if (!(context->rfx_context = rfx_context_new(TRUE)))
goto fail_rfx_context;
2014-09-12 19:38:12 +04:00
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;
2017-11-24 14:46:01 +03:00
rfx_context_set_pixel_format(context->rfx_context, PIXEL_FORMAT_BGRA32);
2016-10-04 17:54:11 +03:00
if (!(context->s = Stream_New(NULL, 0xFFFF)))
goto fail_stream_new;
2016-10-04 17:54:11 +03:00
2019-11-06 17:24:51 +03:00
context->vcm = WTSOpenServerA((LPSTR)client->context);
if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
goto fail_open_server;
2016-10-04 17:54:11 +03:00
mf_info_peer_register(context->info, context);
return TRUE;
fail_open_server:
Stream_Free(context->s, TRUE);
context->s = NULL;
fail_stream_new:
rfx_context_free(context->rfx_context);
context->rfx_context = NULL;
fail_rfx_context:
return FALSE;
2014-09-12 19:38:12 +04:00
}
/* Called after a peer disconnects */
2017-11-24 14:46:01 +03:00
static void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
2014-09-12 19:38:12 +04:00
{
if (context)
{
mf_info_peer_unregister(context->info, context);
dispatch_suspend(info_timer);
Stream_Free(context->s, TRUE);
rfx_context_free(context->rfx_context);
2019-11-06 17:24:51 +03:00
// nsc_context_free(context->nsc_context);
2014-09-12 19:38:12 +04:00
#ifdef CHANNEL_AUDIN_SERVER
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (context->audin)
audin_server_context_free(context->audin);
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
#endif
2017-11-24 14:46:01 +03:00
#ifdef CHANNEL_RDPSND_SERVER
2014-09-12 19:38:12 +04:00
mf_peer_rdpsnd_stop();
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (context->rdpsnd)
rdpsnd_server_context_free(context->rdpsnd);
2016-10-04 17:54:11 +03:00
2017-11-24 14:46:01 +03:00
#endif
2014-09-12 19:38:12 +04:00
WTSCloseServer(context->vcm);
}
}
/* Called when a new client connects */
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_init(freerdp_peer* client)
2014-09-12 19:38:12 +04:00
{
client->ContextSize = sizeof(mfPeerContext);
2019-11-06 17:24:51 +03:00
client->ContextNew = (psPeerContextNew)mf_peer_context_new;
client->ContextFree = (psPeerContextFree)mf_peer_context_free;
if (!freerdp_peer_context_new(client))
return FALSE;
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
info_event_queue = mf_event_queue_new();
2019-11-06 17:24:51 +03:00
info_queue = dispatch_queue_create("FreeRDP.update.timer", DISPATCH_QUEUE_SERIAL);
info_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, info_queue);
2016-10-04 17:54:11 +03:00
if (info_timer)
2014-09-12 19:38:12 +04:00
{
2019-11-06 17:24:51 +03:00
// DEBUG_WARN( "created timer\n");
2016-10-04 17:54:11 +03:00
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 42ull * NSEC_PER_MSEC,
100ull * NSEC_PER_MSEC);
2019-11-06 17:24:51 +03:00
dispatch_source_set_event_handler(info_timer, ^{
// DEBUG_WARN( "dispatch\n");
mfEvent* event = mf_event_new(FREERDP_SERVER_MAC_EVENT_TYPE_FRAME_TICK);
mf_event_push(info_event_queue, (mfEvent*)event);
});
2014-09-12 19:38:12 +04:00
dispatch_resume(info_timer);
}
return TRUE;
2014-09-12 19:38:12 +04:00
}
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_post_connect(freerdp_peer* client)
2014-09-12 19:38:12 +04:00
{
2019-11-06 17:24:51 +03:00
mfPeerContext* context = (mfPeerContext*)client->context;
2014-09-12 19:38:12 +04:00
rdpSettings* settings = client->settings;
mfInfo* mfi = mf_info_get_instance();
mfi->scale = 1;
2019-11-06 17:24:51 +03:00
// mfi->servscreen_width = 2880 / mfi->scale;
// mfi->servscreen_height = 1800 / mfi->scale;
2014-09-12 19:38:12 +04:00
UINT32 bitsPerPixel = 32;
2019-11-06 17:24:51 +03:00
if ((settings->DesktopWidth != mfi->servscreen_width) ||
(settings->DesktopHeight != mfi->servscreen_height))
2016-10-04 17:54:11 +03:00
{
2014-09-12 19:38:12 +04:00
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
settings->DesktopWidth = mfi->servscreen_width;
settings->DesktopHeight = mfi->servscreen_height;
settings->ColorDepth = bitsPerPixel;
client->update->DesktopResize(client->update->context);
mfi->mouse_down_left = FALSE;
mfi->mouse_down_right = FALSE;
mfi->mouse_down_other = FALSE;
2017-11-24 14:46:01 +03:00
#ifdef CHANNEL_RDPSND_SERVER
2014-09-12 19:38:12 +04:00
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd"))
{
mf_peer_rdpsnd_init(context); /* Audio Output */
}
2016-10-04 17:54:11 +03:00
2017-11-24 14:46:01 +03:00
#endif
2014-09-12 19:38:12 +04:00
/* Dynamic Virtual Channels */
#ifdef CHANNEL_AUDIN_SERVER
mf_peer_audin_init(context); /* Audio Input */
#endif
return TRUE;
}
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_activate(freerdp_peer* client)
2014-09-12 19:38:12 +04:00
{
2019-11-06 17:24:51 +03:00
mfPeerContext* context = (mfPeerContext*)client->context;
2017-11-24 14:46:01 +03:00
rfx_context_reset(context->rfx_context, client->settings->DesktopWidth,
client->settings->DesktopHeight);
2014-09-12 19:38:12 +04:00
context->activated = TRUE;
return TRUE;
}
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_synchronize_event(rdpInput* input, UINT32 flags)
2014-09-12 19:38:12 +04:00
{
2017-11-24 14:46:01 +03:00
return TRUE;
2014-09-12 19:38:12 +04:00
}
void mf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
UINT16 down = 0x4000;
2019-11-06 17:24:51 +03:00
// UINT16 up = 0x8000;
2014-09-12 19:38:12 +04:00
bool state_down = FALSE;
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (flags == down)
{
state_down = TRUE;
}
}
2017-11-24 14:46:01 +03:00
static BOOL mf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
2014-09-12 19:38:12 +04:00
{
2017-11-24 14:46:01 +03:00
return FALSE;
2014-09-12 19:38:12 +04:00
}
2019-11-06 17:24:51 +03:00
static BOOL mf_peer_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
2014-09-12 19:38:12 +04:00
{
return FALSE;
2014-09-12 19:38:12 +04:00
}
2017-11-24 14:46:01 +03:00
static void* mf_peer_main_loop(void* arg)
2014-09-12 19:38:12 +04:00
{
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
mfPeerContext* context;
2019-11-06 17:24:51 +03:00
freerdp_peer* client = (freerdp_peer*)arg;
2014-09-12 19:38:12 +04:00
memset(rfds, 0, sizeof(rfds));
2016-10-04 17:54:11 +03:00
if (!mf_peer_init(client))
{
freerdp_peer_free(client);
return NULL;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
/* Initialize the real server settings here */
client->settings->CertificateFile = _strdup("server.crt");
client->settings->PrivateKeyFile = _strdup("server.key");
2016-10-04 17:54:11 +03:00
if (!client->settings->CertificateFile || !client->settings->PrivateKeyFile)
{
freerdp_peer_free(client);
return NULL;
}
2014-09-12 19:38:12 +04:00
client->settings->NlaSecurity = FALSE;
client->settings->RemoteFxCodec = TRUE;
client->settings->ColorDepth = 32;
client->settings->SuppressOutput = TRUE;
client->settings->RefreshRect = FALSE;
client->PostConnect = mf_peer_post_connect;
client->Activate = mf_peer_activate;
client->input->SynchronizeEvent = mf_peer_synchronize_event;
2019-11-06 17:24:51 +03:00
client->input->KeyboardEvent = mf_input_keyboard_event; // mf_peer_keyboard_event;
2014-09-12 19:38:12 +04:00
client->input->UnicodeKeyboardEvent = mf_peer_unicode_keyboard_event;
client->input->MouseEvent = mf_input_mouse_event;
client->input->ExtendedMouseEvent = mf_input_extended_mouse_event;
2019-11-06 17:24:51 +03:00
// client->update->RefreshRect = mf_peer_refresh_rect;
2014-09-12 19:38:12 +04:00
client->update->SuppressOutput = mf_peer_suppress_output;
client->Initialize(client);
2019-11-06 17:24:51 +03:00
context = (mfPeerContext*)client->context;
2014-09-12 19:38:12 +04:00
while (1)
{
rcount = 0;
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE)
{
break;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (mf_peer_get_fds(client, rfds, &rcount) != TRUE)
{
break;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
max_fds = 0;
FD_ZERO(&rfds_set);
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (fds > max_fds)
max_fds = fds;
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
FD_SET(fds, &rfds_set);
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (max_fds == 0)
break;
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
/* these are not really errors */
2019-11-06 17:24:51 +03:00
if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
2014-09-12 19:38:12 +04:00
{
break;
}
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (client->CheckFileDescriptor(client) != TRUE)
{
break;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if ((mf_peer_check_fds(client)) != TRUE)
{
break;
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
{
break;
}
}
2016-10-04 17:54:11 +03:00
2014-09-12 19:38:12 +04:00
client->Disconnect(client);
freerdp_peer_context_free(client);
freerdp_peer_free(client);
return NULL;
}
2017-11-24 14:46:01 +03:00
BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
pthread_t th;
if (pthread_create(&th, 0, mf_peer_main_loop, client) == 0)
{
pthread_detach(th);
return TRUE;
}
return FALSE;
}