wfreerdp-server: add support for parallel sending to multiple clients

This commit is contained in:
Marc-André Moreau 2012-09-07 22:48:30 +02:00
parent c59b7dedad
commit 271aa3edb5
6 changed files with 78 additions and 59 deletions

View File

@ -117,7 +117,9 @@ wfInfo* wf_info_init()
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
}
wfi->updateEvent = CreateEvent(0, 1, 0, 0);
wfi->updateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
wfi->updateSemaphore = CreateSemaphore(NULL, 0, 32, NULL);
wfi->updateThread = CreateThread(NULL, 0, wf_update_thread, wfi, CREATE_SUSPENDED, NULL);
@ -179,21 +181,30 @@ void wf_update_encoder_reinit(wfInfo* wfi)
wf_update_encoder_init(wfi);
}
void wf_mirror_driver_init(wfInfo* wfi)
{
wf_mirror_driver_find_display_device(wfi);
wf_mirror_driver_display_device_attach(wfi, 1);
wf_mirror_driver_update(wfi, FALSE);
wf_mirror_driver_map_memory(wfi);
}
void wf_mirror_driver_uninit(wfInfo* wfi)
{
wf_mirror_driver_cleanup(wfi);
wf_mirror_driver_display_device_attach(wfi, 0);
wf_mirror_driver_update(wfi, 1);
}
void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
context->info = wfi;
context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (wfi->peerCount < 1)
{
wf_mirror_driver_find_display_device(wfi);
wf_mirror_driver_display_device_attach(wfi, 1);
wf_mirror_driver_update(wfi, FALSE);
wf_mirror_driver_map_memory(wfi);
//wf_update_encoder_init(wfi);
}
wf_mirror_driver_init(wfi);
wf_update_encoder_reinit(wfi);
wfi->peers[wfi->peerCount++] = context;
@ -206,20 +217,10 @@ void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
if (wfi->peerCount <= 1)
{
wfi->peers[--(wfi->peerCount)] = NULL;
if (wfi->peerCount == 1)
wf_mirror_driver_uninit(wfi);
wf_mirror_driver_cleanup(wfi);
wf_mirror_driver_display_device_attach(wfi, 0);
wf_mirror_driver_update(wfi, 1);
//wf_update_encoder_uninit(wfi);
}
else
{
wfi->peers[--(wfi->peerCount)] = NULL;
}
wfi->peers[--(wfi->peerCount)] = NULL;
wf_info_unlock(wfi);
}

View File

@ -46,6 +46,7 @@ struct wf_info
BOOL updatePending;
HANDLE updateEvent;
HANDLE updateThread;
HANDLE updateSemaphore;
RFX_CONTEXT* rfx_context;
unsigned long lastUpdate;
unsigned long nextUpdate;

View File

@ -33,6 +33,7 @@
DWORD WINAPI wf_update_thread(LPVOID lpParam)
{
int index;
DWORD fps;
wfInfo* wfi;
DWORD beg, end;
@ -56,7 +57,14 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam)
if (wf_info_have_updates(wfi))
{
wf_update_encode(wfi);
SetEvent(wfi->updateEvent);
for (index = 0; index < wfi->peerCount; index++)
SetEvent(wfi->peers[index]->updateEvent);
for (index = 0; index < wfi->peerCount; index++)
WaitForSingleObject(wfi->updateSemaphore, INFINITE);
wfi->lastUpdate = wfi->nextUpdate;
}
}
@ -115,30 +123,11 @@ void wf_update_encode(wfInfo* wfi)
cmd->height = height;
cmd->bitmapDataLength = stream_get_length(wfi->s);
cmd->bitmapData = stream_get_head(wfi->s);
wfi->updatePending = TRUE;
}
void wf_update_send(wfInfo* wfi)
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
if (wfi->updatePending)
{
int index;
freerdp_peer* client;
for (index = 0; index < wfi->peerCount; index++)
{
client = ((rdpContext*) wfi->peers[index])->peer;
wfi->cmd.codecID = client->settings->rfx_codec_id;
client->update->SurfaceBits(client->update->context, &wfi->cmd);
}
wfi->lastUpdate = wfi->nextUpdate;
wfi->updatePending = FALSE;
}
wf_info_unlock(wfi);
}
freerdp_peer* client = ((rdpContext*) context)->peer;
wfi->cmd.codecID = client->settings->rfx_codec_id;
client->update->SurfaceBits(client->update->context, &wfi->cmd);
}

View File

@ -27,4 +27,8 @@ void wf_update_send(wfInfo* wfi);
DWORD WINAPI wf_update_thread(LPVOID lpParam);
void wf_update_begin(wfInfo* wfi);
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context);
void wf_update_end(wfInfo* wfi);
#endif /* WF_UPDATE_H */

View File

@ -58,13 +58,16 @@ static DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
memset(rfds, 0, sizeof(rfds));
context = (wfPeerContext*) client->context;
context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->socketSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
while (1)
{
rcount = 0;
if (client->GetFileDescriptor(client, rfds, &rcount) != true)
{
printf("Failed to get FreeRDP file descriptor\n");
printf("Failed to get peer file descriptor\n");
break;
}
@ -87,6 +90,10 @@ static DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
select(max_fds + 1, &rfds_set, NULL, NULL, NULL);
SetEvent(context->socketEvent);
WaitForSingleObject(context->socketSemaphore, INFINITE);
if (context->socketClose)
break;
}
return 0;
@ -168,15 +175,15 @@ static void wf_peer_read_settings(freerdp_peer* client)
static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
{
wfInfo* wfi;
DWORD nCount;
DWORD status;
HANDLE handles[32];
wfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) lpParam;
wf_peer_init(client);
/* Initialize the real server settings here */
wf_peer_read_settings(client);
client->PostConnect = wf_peer_post_connect;
@ -191,29 +198,42 @@ static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
client->Initialize(client);
context = (wfPeerContext*) client->context;
context->socketEvent = CreateEvent(0, 1, 0, 0);
CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL);
wfi = context->info;
context->socketThread = CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL);
printf("We've got a client %s\n", client->local ? "(local)" : client->hostname);
nCount = 0;
handles[nCount++] = context->updateEvent;
handles[nCount++] = context->socketEvent;
handles[nCount++] = context->info->updateEvent;
while (1)
{
DWORD status;
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (client->CheckFileDescriptor(client) != true)
if (WaitForSingleObject(context->updateEvent, 0) == 0)
{
printf("Failed to check FreeRDP file descriptor\n");
break;
if (client->activated)
wf_update_peer_send(wfi, context);
ResetEvent(context->updateEvent);
ReleaseSemaphore(wfi->updateSemaphore, 1, NULL);
}
if (client->activated)
wf_update_send(context->info);
if (WaitForSingleObject(context->socketEvent, 0) == 0)
{
if (client->CheckFileDescriptor(client) != true)
{
printf("Failed to check peer file descriptor\n");
context->socketClose = TRUE;
}
ResetEvent(context->socketEvent);
ReleaseSemaphore(context->socketSemaphore, 1, NULL);
if (context->socketClose)
break;
}
}
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);

View File

@ -30,7 +30,11 @@ struct wf_peer_context
wfInfo* info;
boolean activated;
HANDLE updateEvent;
BOOL socketClose;
HANDLE socketEvent;
HANDLE socketThread;
HANDLE socketSemaphore;
};
typedef struct wf_peer_context wfPeerContext;