mirror of https://github.com/FreeRDP/FreeRDP
wfreerdp-server: start handling more than one connected client at once
This commit is contained in:
parent
8c5ea19391
commit
e5b5b09c38
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#ifndef WFREERDP_H
|
||||
#define WFREERDP_H
|
||||
|
||||
//#define WITH_WIN8 1
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include "wf_info.h"
|
||||
|
|
Loading…
Reference in New Issue