wfreerdp-server: start handling more than one connected client at once

This commit is contained in:
Marc-André Moreau 2012-09-05 20:03:07 -04:00
parent 8c5ea19391
commit e5b5b09c38
11 changed files with 216 additions and 132 deletions

View File

@ -18,6 +18,10 @@
# limitations under the License.
add_executable(wfreerdp-server
wf_update.c
wf_update.h
wf_dxgi.c
wf_dxgi.h
wf_input.c
wf_input.h
wf_mirage.c

26
server/Windows/wf_dxgi.c Normal file
View File

@ -0,0 +1,26 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@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 "wf_dxgi.h"

27
server/Windows/wf_dxgi.h Normal file
View File

@ -0,0 +1,27 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@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.
*/
#ifndef WF_DXGI_H
#define WF_DXGI_H
#include "wfreerdp.h"
#endif /* WF_DXGI_H */

View File

@ -111,6 +111,8 @@ wfInfo* wf_info_init()
}
wfi->updateEvent = CreateEvent(0, 1, 0, 0);
wfi->peers = (wfPeerContext**) malloc(sizeof(wfPeerContext*) * 32);
}
return wfi;
@ -124,15 +126,16 @@ wfInfo* wf_info_get_instance()
return wfInfoInstance;
}
void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context)
void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
if (wfi->subscribers < 1)
context->info = wfi;
if (wfi->peerCount < 1)
{
context->info = wfi;
wf_check_disp_devices(wfi);
wf_disp_device_set_attach_mode(wfi, 1);
wf_disp_device_set_attach_mode(wfi, TRUE);
wf_update_mirror_drv(wfi, 0);
wf_map_mirror_mem(wfi);
@ -145,52 +148,34 @@ void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context)
wfi->s = stream_new(65536);
}
wfi->subscribers++;
wfi->peers[wfi->peerCount++] = context;
wf_info_unlock(wfi);
}
}
/**
* TODO: i think i can replace all the context->info here with info
* in fact it may not even care about subscribers
*/
void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context)
void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
if (context && (wfi->subscribers == 1))
if (wfi->peerCount <= 1)
{
wfi->subscribers--;
/* only the last peer needs to call this */
wf_mirror_cleanup(context->info);
wfi->peers[--(wfi->peerCount)] = NULL;
wf_mirror_cleanup(wfi);
wf_disp_device_set_attach_mode(context->info, FALSE);
wf_update_mirror_drv(context->info, 1);
wf_update_mirror_drv(wfi, 1);
stream_free(wfi->s);
rfx_context_free(wfi->rfx_context);
}
else
{
wfi->subscribers--;
wfi->peers[--(wfi->peerCount)] = NULL;
}
wf_info_unlock(wfi);
}
/**
* Note: if we released the last subscriber,
* block the encoder until next subscriber
*/
}
BOOL wf_info_has_subscribers(wfInfo* wfi)
{
if (wfi->subscribers > 0)
return TRUE;
return FALSE;
}
BOOL wf_info_have_updates(wfInfo* wfi)

View File

@ -20,6 +20,7 @@
#ifndef WF_INFO_H
#define WF_INFO_H
#include <freerdp/freerdp.h>
#include <freerdp/codec/rfx.h>
struct wf_peer_context;
@ -28,16 +29,17 @@ typedef struct wf_peer_context wfPeerContext;
struct wf_info
{
STREAM* s;
int width;
int height;
int bitsPerPix;
HDC driverDC;
int peerCount;
int threadCount;
BOOL activated;
void* changeBuffer;
LPTSTR deviceKey;
TCHAR deviceName[32];
int subscribers;
int threadCount;
int height;
int width;
int bitsPerPix;
wfPeerContext** peers;
RECT invalid;
HANDLE mutex;
@ -46,6 +48,7 @@ struct wf_info
RFX_CONTEXT* rfx_context;
unsigned long lastUpdate;
unsigned long nextUpdate;
SURFACE_BITS_COMMAND cmd;
};
typedef struct wf_info wfInfo;
@ -54,10 +57,9 @@ int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds);
int wf_info_unlock(wfInfo* wfi);
wfInfo* wf_info_get_instance();
void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context);
void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context);
void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context);
void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context);
BOOL wf_info_has_subscribers(wfInfo* wfi);
BOOL wf_info_have_updates(wfInfo* wfi);
void wf_info_update_changes(wfInfo* wfi);
void wf_info_find_invalid_region(wfInfo* wfi);

View File

@ -31,22 +31,19 @@
#include "wf_input.h"
#include "wf_mirage.h"
#include "wf_update.h"
#include "wf_peer.h"
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
{
#ifndef WITH_WIN8
context->info = wf_info_get_instance();
wf_info_mirror_init(context->info, context);
#endif
wf_info_peer_register(context->info, context);
}
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
{
#ifndef WITH_WIN8
wf_info_subscriber_release(context->info, context);
#endif
wf_info_peer_unregister(context->info, context);
}
static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
@ -70,13 +67,13 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
if (wf_info_lock(wfi) > 0)
{
if (wf_info_has_subscribers(wfi))
if (wfi->peerCount > 0)
{
wf_info_update_changes(wfi);
if (wf_info_have_updates(wfi))
{
wf_rfx_encode(client);
wf_update_encode(wfi);
SetEvent(wfi->updateEvent);
}
}
@ -100,65 +97,6 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
return 0;
}
void wf_rfx_encode(freerdp_peer* client)
{
STREAM* s;
wfInfo* wfi;
long offset;
RFX_RECT rect;
long height, width;
rdpUpdate* update;
wfPeerContext* wfp;
GETCHANGESBUF* buf;
SURFACE_BITS_COMMAND* cmd;
wfp = (wfPeerContext*) client->context;
wfi = wfp->info;
if (client->activated == FALSE)
return;
if (wfp->activated == FALSE)
return;
wf_info_find_invalid_region(wfi);
update = client->update;
cmd = &update->surface_bits_command;
buf = (GETCHANGESBUF*) wfi->changeBuffer;
width = (wfi->invalid.right - wfi->invalid.left) + 1;
height = (wfi->invalid.bottom - wfi->invalid.top) + 1;
stream_clear(wfi->s);
stream_set_pos(wfi->s, 0);
s = wfi->s;
rect.x = 0;
rect.y = 0;
rect.width = (uint16) width;
rect.height = (uint16) height;
offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4);
rfx_compose_message(wfi->rfx_context, s, &rect, 1,
((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4);
cmd->destLeft = wfi->invalid.left;
cmd->destTop = wfi->invalid.top;
cmd->destRight = wfi->invalid.left + width;
cmd->destBottom = wfi->invalid.top + height;
cmd->bpp = 32;
cmd->codecID = client->settings->rfx_codec_id;
cmd->width = width;
cmd->height = height;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
wfi->updatePending = TRUE;
}
void wf_peer_init(freerdp_peer* client)
{
wfInfo* wfi;
@ -171,7 +109,6 @@ void wf_peer_init(freerdp_peer* client)
wfi = ((wfPeerContext*) client->context)->info;
#ifndef WITH_WIN8
wf_info_lock(wfi);
if (wfi->threadCount < 1)
@ -188,7 +125,6 @@ void wf_peer_init(freerdp_peer* client)
}
wf_info_unlock(wfi);
#endif
}
boolean wf_peer_post_connect(freerdp_peer* client)
@ -244,25 +180,3 @@ void wf_peer_synchronize_event(rdpInput* input, uint32 flags)
{
}
void wf_peer_send_changes(freerdp_peer* client)
{
wfInfo* wfi;
wfPeerContext* context = (wfPeerContext*) client->context;
wfi = context->info;
if (wf_info_lock(wfi) > 0)
{
if (wfi->updatePending)
{
wfi->lastUpdate = wfi->nextUpdate;
client->update->SurfaceBits(client->update->context, &client->update->surface_bits_command);
wfi->updatePending = FALSE;
}
wf_info_unlock(wfi);
}
}

View File

@ -21,6 +21,7 @@
#define WF_PEER_H
#include "wfreerdp.h"
#include "wf_info.h"
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);

View File

@ -0,0 +1,98 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@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/freerdp.h>
#include <freerdp/listener.h>
#include "wf_peer.h"
#include "wf_mirage.h"
#include "wf_update.h"
void wf_update_encode(wfInfo* wfi)
{
long offset;
RFX_RECT rect;
long height, width;
GETCHANGESBUF* changes;
SURFACE_BITS_COMMAND* cmd;
wf_info_find_invalid_region(wfi);
cmd = &wfi->cmd;
changes = (GETCHANGESBUF*) wfi->changeBuffer;
width = (wfi->invalid.right - wfi->invalid.left) + 1;
height = (wfi->invalid.bottom - wfi->invalid.top) + 1;
stream_clear(wfi->s);
stream_set_pos(wfi->s, 0);
rect.x = 0;
rect.y = 0;
rect.width = (uint16) width;
rect.height = (uint16) height;
offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4);
rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1,
((uint8*) (changes->Userbuffer)) + offset, width, height, wfi->width * 4);
cmd->destLeft = wfi->invalid.left;
cmd->destTop = wfi->invalid.top;
cmd->destRight = wfi->invalid.left + width;
cmd->destBottom = wfi->invalid.top + height;
cmd->bpp = 32;
cmd->codecID = 3;
cmd->width = width;
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)
{
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);
}
}

View File

@ -0,0 +1,28 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@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.
*/
#ifndef WF_UPDATE_H
#define WF_UPDATE_H
#include "wfreerdp.h"
void wf_update_encode(wfInfo* wfi);
void wf_update_send(wfInfo* wfi);
#endif /* WF_UPDATE_H */

View File

@ -36,6 +36,7 @@
#include <freerdp/utils/thread.h>
#include <freerdp/locale/keyboard.h>
#include "wf_update.h"
#include "wf_input.h"
#include "wf_peer.h"
@ -139,7 +140,7 @@ static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
}
if (client->activated)
wf_peer_send_changes(client);
wf_update_send(context->info);
}
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);

View File

@ -20,8 +20,6 @@
#ifndef WFREERDP_H
#define WFREERDP_H
//#define WITH_WIN8 1
#include <freerdp/freerdp.h>
#include "wf_info.h"