mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 18:03:30 +08:00
server: use rdpContext for server-side components.
This commit is contained in:
parent
c11dc9a36e
commit
296d5ea753
@ -28,6 +28,7 @@ typedef struct rdp_channels rdpChannels;
|
||||
|
||||
typedef struct rdp_freerdp freerdp;
|
||||
typedef struct rdp_context rdpContext;
|
||||
typedef struct rdp_freerdp_peer freerdp_peer;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
@ -55,6 +56,7 @@ typedef int (*pcReceiveChannelData)(freerdp* instance, int channelId, uint8* dat
|
||||
struct rdp_context
|
||||
{
|
||||
freerdp* instance;
|
||||
freerdp_peer* peer;
|
||||
|
||||
int argc;
|
||||
char** argv;
|
||||
|
@ -20,14 +20,16 @@
|
||||
#ifndef __FREERDP_PEER_H
|
||||
#define __FREERDP_PEER_H
|
||||
|
||||
typedef struct rdp_freerdp_peer freerdp_peer;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/input.h>
|
||||
#include <freerdp/update.h>
|
||||
|
||||
typedef void (*psPeerContextSize)(freerdp_peer* client, uint32* size);
|
||||
typedef void (*psPeerContextNew)(freerdp_peer* client, rdpContext* context);
|
||||
typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context);
|
||||
|
||||
typedef boolean (*psPeerInitialize)(freerdp_peer* client);
|
||||
typedef boolean (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount);
|
||||
typedef boolean (*psPeerCheckFileDescriptor)(freerdp_peer* client);
|
||||
@ -37,17 +39,18 @@ typedef boolean (*psPeerActivate)(freerdp_peer* client);
|
||||
|
||||
struct rdp_freerdp_peer
|
||||
{
|
||||
void* info;
|
||||
void* peer;
|
||||
void* param1;
|
||||
void* param2;
|
||||
void* param3;
|
||||
void* param4;
|
||||
rdpContext* context;
|
||||
int sockfd;
|
||||
char hostname[50];
|
||||
|
||||
rdpInput* input;
|
||||
rdpUpdate* update;
|
||||
rdpSettings* settings;
|
||||
|
||||
psPeerContextSize ContextSize;
|
||||
psPeerContextNew ContextNew;
|
||||
psPeerContextFree ContextFree;
|
||||
|
||||
psPeerInitialize Initialize;
|
||||
psPeerGetFileDescriptor GetFileDescriptor;
|
||||
psPeerCheckFileDescriptor CheckFileDescriptor;
|
||||
@ -57,6 +60,9 @@ struct rdp_freerdp_peer
|
||||
psPeerActivate Activate;
|
||||
};
|
||||
|
||||
FREERDP_API void freerdp_peer_context_new(freerdp_peer* client);
|
||||
FREERDP_API void freerdp_peer_context_free(freerdp_peer* client);
|
||||
|
||||
FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd);
|
||||
FREERDP_API void freerdp_peer_free(freerdp_peer* client);
|
||||
|
||||
|
@ -183,10 +183,7 @@ static boolean freerdp_listener_check_fds(freerdp_listener* instance)
|
||||
sin_addr = &(((struct sockaddr_in*)&peer_addr)->sin_addr);
|
||||
else
|
||||
sin_addr = &(((struct sockaddr_in6*)&peer_addr)->sin6_addr);
|
||||
client->settings->hostname = xzalloc(50);
|
||||
inet_ntop(peer_addr.ss_family, sin_addr, client->settings->hostname, 50);
|
||||
|
||||
printf("Accepted client from %s.\n", client->settings->hostname);
|
||||
inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname));
|
||||
|
||||
IFCALL(instance->PeerAccepted, instance, client);
|
||||
}
|
||||
|
@ -21,19 +21,15 @@
|
||||
|
||||
static boolean freerdp_peer_initialize(freerdp_peer* client)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*)client->peer;
|
||||
|
||||
peer->rdp->settings->server_mode = True;
|
||||
peer->rdp->state = CONNECTION_STATE_INITIAL;
|
||||
client->context->rdp->settings->server_mode = True;
|
||||
client->context->rdp->state = CONNECTION_STATE_INITIAL;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static boolean freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*)client->peer;
|
||||
|
||||
rfds[*rcount] = (void*)(long)(peer->rdp->transport->tcp->sockfd);
|
||||
rfds[*rcount] = (void*)(long)(client->context->rdp->transport->tcp->sockfd);
|
||||
(*rcount)++;
|
||||
|
||||
return True;
|
||||
@ -41,11 +37,10 @@ static boolean freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcou
|
||||
|
||||
static boolean freerdp_peer_check_fds(freerdp_peer* client)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*)client->peer;
|
||||
rdpRdp* rdp;
|
||||
int status;
|
||||
|
||||
rdp = (rdpRdp*) peer->rdp;
|
||||
rdp = client->context->rdp;
|
||||
|
||||
status = rdp_check_fds(rdp);
|
||||
if (status < 0)
|
||||
@ -54,7 +49,7 @@ static boolean freerdp_peer_check_fds(freerdp_peer* client)
|
||||
return True;
|
||||
}
|
||||
|
||||
static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
|
||||
static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s)
|
||||
{
|
||||
uint8 type;
|
||||
uint16 length;
|
||||
@ -74,7 +69,7 @@ static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_CONTROL:
|
||||
if (!rdp_server_accept_client_control_pdu(peer->rdp, s))
|
||||
if (!rdp_server_accept_client_control_pdu(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
@ -83,28 +78,28 @@ static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_FONT_LIST:
|
||||
if (!rdp_server_accept_client_font_list_pdu(peer->rdp, s))
|
||||
if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s))
|
||||
return False;
|
||||
if (peer->client->PostConnect)
|
||||
if (client->PostConnect)
|
||||
{
|
||||
if (!peer->client->PostConnect(peer->client))
|
||||
if (!client->PostConnect(client))
|
||||
return False;
|
||||
/**
|
||||
* PostConnect should only be called once and should not be called
|
||||
* after a reactivation sequence.
|
||||
*/
|
||||
peer->client->PostConnect = NULL;
|
||||
client->PostConnect = NULL;
|
||||
}
|
||||
if (peer->client->Activate)
|
||||
if (client->Activate)
|
||||
{
|
||||
/* Activate will be called everytime after the client is activated/reactivated. */
|
||||
if (!peer->client->Activate(peer->client))
|
||||
if (!client->Activate(client))
|
||||
return False;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
|
||||
mcs_send_disconnect_provider_ultimatum(peer->rdp->mcs);
|
||||
mcs_send_disconnect_provider_ultimatum(client->context->rdp->mcs);
|
||||
return False;
|
||||
|
||||
default:
|
||||
@ -115,14 +110,14 @@ static boolean peer_recv_data_pdu(rdpPeer* peer, STREAM* s)
|
||||
return True;
|
||||
}
|
||||
|
||||
static boolean peer_recv_tpkt_pdu(rdpPeer* peer, STREAM* s)
|
||||
static boolean peer_recv_tpkt_pdu(freerdp_peer* client, STREAM* s)
|
||||
{
|
||||
uint16 length;
|
||||
uint16 pduType;
|
||||
uint16 pduLength;
|
||||
uint16 channelId;
|
||||
|
||||
if (!rdp_read_header(peer->rdp, s, &length, &channelId))
|
||||
if (!rdp_read_header(client->context->rdp, s, &length, &channelId))
|
||||
{
|
||||
printf("Incorrect RDP header.\n");
|
||||
return False;
|
||||
@ -134,13 +129,13 @@ static boolean peer_recv_tpkt_pdu(rdpPeer* peer, STREAM* s)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &peer->rdp->settings->pdu_source))
|
||||
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &client->settings->pdu_source))
|
||||
return False;
|
||||
|
||||
switch (pduType)
|
||||
{
|
||||
case PDU_TYPE_DATA:
|
||||
if (!peer_recv_data_pdu(peer, s))
|
||||
if (!peer_recv_data_pdu(client, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
@ -153,13 +148,13 @@ static boolean peer_recv_tpkt_pdu(rdpPeer* peer, STREAM* s)
|
||||
return True;
|
||||
}
|
||||
|
||||
static boolean peer_recv_fastpath_pdu(rdpPeer* peer, STREAM* s)
|
||||
static boolean peer_recv_fastpath_pdu(freerdp_peer* client, STREAM* s)
|
||||
{
|
||||
uint16 length;
|
||||
rdpRdp* rdp;
|
||||
rdpFastPath* fastpath;
|
||||
|
||||
rdp = peer->rdp;
|
||||
rdp = client->context->rdp;
|
||||
fastpath = rdp->fastpath;
|
||||
length = fastpath_read_header_rdp(fastpath, s);
|
||||
|
||||
@ -177,62 +172,62 @@ static boolean peer_recv_fastpath_pdu(rdpPeer* peer, STREAM* s)
|
||||
return fastpath_recv_inputs(fastpath, s);
|
||||
}
|
||||
|
||||
static boolean peer_recv_pdu(rdpPeer* peer, STREAM* s)
|
||||
static boolean peer_recv_pdu(freerdp_peer* client, STREAM* s)
|
||||
{
|
||||
if (tpkt_verify_header(s))
|
||||
return peer_recv_tpkt_pdu(peer, s);
|
||||
return peer_recv_tpkt_pdu(client, s);
|
||||
else
|
||||
return peer_recv_fastpath_pdu(peer, s);
|
||||
return peer_recv_fastpath_pdu(client, s);
|
||||
}
|
||||
|
||||
static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*) extra;
|
||||
freerdp_peer* client = (freerdp_peer*) extra;
|
||||
|
||||
switch (peer->rdp->state)
|
||||
switch (client->context->rdp->state)
|
||||
{
|
||||
case CONNECTION_STATE_INITIAL:
|
||||
if (!rdp_server_accept_nego(peer->rdp, s))
|
||||
if (!rdp_server_accept_nego(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_NEGO:
|
||||
if (!rdp_server_accept_mcs_connect_initial(peer->rdp, s))
|
||||
if (!rdp_server_accept_mcs_connect_initial(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
if (!rdp_server_accept_mcs_erect_domain_request(peer->rdp, s))
|
||||
if (!rdp_server_accept_mcs_erect_domain_request(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
|
||||
if (!rdp_server_accept_mcs_attach_user_request(peer->rdp, s))
|
||||
if (!rdp_server_accept_mcs_attach_user_request(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
if (!rdp_server_accept_mcs_channel_join_request(peer->rdp, s))
|
||||
if (!rdp_server_accept_mcs_channel_join_request(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||
if (!rdp_server_accept_client_info(peer->rdp, s))
|
||||
if (!rdp_server_accept_client_info(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSE:
|
||||
if (!rdp_server_accept_confirm_active(peer->rdp, s))
|
||||
if (!rdp_server_accept_confirm_active(client->context->rdp, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
if (!peer_recv_pdu(peer, s))
|
||||
if (!peer_recv_pdu(client, s))
|
||||
return False;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Invalid state %d\n", peer->rdp->state);
|
||||
printf("Invalid state %d\n", client->context->rdp->state);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -241,49 +236,65 @@ static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extr
|
||||
|
||||
static void freerdp_peer_disconnect(freerdp_peer* client)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*) client->peer;
|
||||
transport_disconnect(client->context->rdp->transport);
|
||||
}
|
||||
|
||||
transport_disconnect(peer->rdp->transport);
|
||||
void freerdp_peer_context_new(freerdp_peer* client)
|
||||
{
|
||||
rdpRdp* rdp;
|
||||
uint32 size = sizeof(rdpContext);
|
||||
|
||||
rdp = rdp_new(NULL);
|
||||
client->input = rdp->input;
|
||||
client->update = rdp->update;
|
||||
client->settings = rdp->settings;
|
||||
|
||||
IFCALL(client->ContextSize, client, &size);
|
||||
|
||||
client->context = (rdpContext*) xzalloc(size);
|
||||
client->context->rdp = rdp;
|
||||
client->context->peer = client;
|
||||
|
||||
client->update->context = client->context;
|
||||
client->input->context = client->context;
|
||||
|
||||
update_register_server_callbacks(client->update);
|
||||
|
||||
transport_attach(rdp->transport, client->sockfd);
|
||||
|
||||
rdp->transport->recv_callback = peer_recv_callback;
|
||||
rdp->transport->recv_extra = client;
|
||||
transport_set_blocking_mode(rdp->transport, False);
|
||||
|
||||
IFCALL(client->ContextNew, client, client->context);
|
||||
}
|
||||
|
||||
void freerdp_peer_context_free(freerdp_peer* client)
|
||||
{
|
||||
IFCALL(client->ContextFree, client, client->context);
|
||||
}
|
||||
|
||||
freerdp_peer* freerdp_peer_new(int sockfd)
|
||||
{
|
||||
freerdp_peer* client;
|
||||
rdpPeer* peer;
|
||||
|
||||
client = xnew(freerdp_peer);
|
||||
|
||||
client->sockfd = sockfd;
|
||||
client->Initialize = freerdp_peer_initialize;
|
||||
client->GetFileDescriptor = freerdp_peer_get_fds;
|
||||
client->CheckFileDescriptor = freerdp_peer_check_fds;
|
||||
client->Disconnect = freerdp_peer_disconnect;
|
||||
|
||||
peer = xnew(rdpPeer);
|
||||
peer->client = client;
|
||||
peer->rdp = rdp_new(NULL);
|
||||
|
||||
client->peer = (void*) peer;
|
||||
client->settings = peer->rdp->settings;
|
||||
client->input = peer->rdp->input;
|
||||
client->update = peer->rdp->update;
|
||||
|
||||
update_register_server_callbacks(client->update);
|
||||
|
||||
transport_attach(peer->rdp->transport, sockfd);
|
||||
|
||||
peer->rdp->transport->recv_callback = peer_recv_callback;
|
||||
peer->rdp->transport->recv_extra = peer;
|
||||
transport_set_blocking_mode(peer->rdp->transport, False);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void freerdp_peer_free(freerdp_peer* client)
|
||||
{
|
||||
rdpPeer* peer = (rdpPeer*)client->peer;
|
||||
|
||||
rdp_free(peer->rdp);
|
||||
xfree(peer);
|
||||
xfree(client);
|
||||
if (client)
|
||||
{
|
||||
rdp_free(client->context->rdp);
|
||||
xfree(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,17 +20,8 @@
|
||||
#ifndef __PEER
|
||||
#define __PEER
|
||||
|
||||
typedef struct rdp_peer rdpPeer;
|
||||
|
||||
#include "rdp.h"
|
||||
#include <freerdp/peer.h>
|
||||
|
||||
struct rdp_peer
|
||||
{
|
||||
freerdp_peer* client;
|
||||
|
||||
rdpRdp* rdp;
|
||||
};
|
||||
|
||||
#endif /* __PEER */
|
||||
|
||||
|
@ -32,40 +32,123 @@ extern char* xf_pcap_file;
|
||||
|
||||
#include "xf_peer.h"
|
||||
|
||||
void xf_peer_init(freerdp_peer* client)
|
||||
xfInfo* xf_info_init()
|
||||
{
|
||||
xfPeer* info;
|
||||
int i;
|
||||
xfInfo* xfi;
|
||||
int pf_count;
|
||||
int vi_count;
|
||||
XVisualInfo* vi;
|
||||
XVisualInfo* vis;
|
||||
XVisualInfo template;
|
||||
XPixmapFormatValues* pf;
|
||||
XPixmapFormatValues* pfs;
|
||||
|
||||
info = xnew(xfPeer);
|
||||
xfi = xnew(xfInfo);
|
||||
|
||||
info->context = rfx_context_new();
|
||||
info->context->mode = RLGR3;
|
||||
info->context->width = client->settings->width;
|
||||
info->context->height = client->settings->height;
|
||||
rfx_context_set_pixel_format(info->context, RFX_PIXEL_FORMAT_RGB);
|
||||
xfi->display = XOpenDisplay(NULL);
|
||||
|
||||
info->s = stream_new(65536);
|
||||
if (xfi->display == NULL)
|
||||
printf("failed to open display: %s\n", XDisplayName(NULL));
|
||||
|
||||
client->param1 = info;
|
||||
xfi->number = DefaultScreen(xfi->display);
|
||||
xfi->screen = ScreenOfDisplay(xfi->display, xfi->number);
|
||||
xfi->depth = DefaultDepthOfScreen(xfi->screen);
|
||||
xfi->width = WidthOfScreen(xfi->screen);
|
||||
xfi->height = HeightOfScreen(xfi->screen);
|
||||
|
||||
pfs = XListPixmapFormats(xfi->display, &pf_count);
|
||||
|
||||
if (pfs == NULL)
|
||||
{
|
||||
printf("XListPixmapFormats failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < pf_count; i++)
|
||||
{
|
||||
pf = pfs + i;
|
||||
|
||||
if (pf->depth == xfi->depth)
|
||||
{
|
||||
xfi->bpp = pf->bits_per_pixel;
|
||||
xfi->scanline_pad = pf->scanline_pad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(pfs);
|
||||
|
||||
memset(&template, 0, sizeof(template));
|
||||
template.class = TrueColor;
|
||||
template.screen = xfi->number;
|
||||
|
||||
vis = XGetVisualInfo(xfi->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
|
||||
|
||||
if (vis == NULL)
|
||||
{
|
||||
printf("XGetVisualInfo failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < vi_count; i++)
|
||||
{
|
||||
vi = vis + i;
|
||||
|
||||
if (vi->depth == xfi->depth)
|
||||
{
|
||||
xfi->visual = vi->visual;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(vis);
|
||||
|
||||
xfi->clrconv = (HCLRCONV) xnew(HCLRCONV);
|
||||
xfi->clrconv->invert = 1;
|
||||
xfi->clrconv->alpha = 1;
|
||||
|
||||
return xfi;
|
||||
}
|
||||
|
||||
void xf_peer_uninit(freerdp_peer* client)
|
||||
void xf_peer_context_size(freerdp_peer* client, uint32* size)
|
||||
{
|
||||
xfPeer* info = (xfPeer*) client->param1;
|
||||
*size = sizeof(xfPeerContext);
|
||||
}
|
||||
|
||||
if (info)
|
||||
void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context)
|
||||
{
|
||||
context->info = xf_info_init();
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = client->settings->width;
|
||||
context->rfx_context->height = client->settings->height;
|
||||
rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_RGB);
|
||||
|
||||
context->s = stream_new(65536);
|
||||
}
|
||||
|
||||
void xf_peer_context_free(freerdp_peer* client, xfPeerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
stream_free(info->s);
|
||||
rfx_context_free(info->context);
|
||||
xfree(info);
|
||||
stream_free(context->s);
|
||||
rfx_context_free(context->rfx_context);
|
||||
xfree(context);
|
||||
}
|
||||
}
|
||||
|
||||
STREAM* xf_peer_stream_init(xfPeer* info)
|
||||
void xf_peer_init(freerdp_peer* client)
|
||||
{
|
||||
stream_clear(info->s);
|
||||
stream_set_pos(info->s, 0);
|
||||
return info->s;
|
||||
client->ContextSize = (psPeerContextSize) xf_peer_context_size;
|
||||
client->ContextNew = (psPeerContextNew) xf_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) xf_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
}
|
||||
|
||||
STREAM* xf_peer_stream_init(xfPeerContext* context)
|
||||
{
|
||||
stream_clear(context->s);
|
||||
stream_set_pos(context->s, 0);
|
||||
return context->s;
|
||||
}
|
||||
|
||||
void xf_peer_live_rfx(freerdp_peer* client)
|
||||
@ -79,19 +162,19 @@ void xf_peer_live_rfx(freerdp_peer* client)
|
||||
int nrects;
|
||||
uint8* data;
|
||||
xfInfo* xfi;
|
||||
xfPeer* xfp;
|
||||
XImage* image;
|
||||
RFX_RECT* rects;
|
||||
uint32 seconds;
|
||||
uint32 useconds;
|
||||
rdpUpdate* update;
|
||||
xfPeerContext* xfp;
|
||||
SURFACE_BITS_COMMAND* cmd;
|
||||
|
||||
seconds = 1;
|
||||
useconds = 0;
|
||||
update = client->update;
|
||||
xfi = (xfInfo*) client->info;
|
||||
xfp = (xfPeer*) client->param1;
|
||||
xfp = (xfPeerContext*) client->context;
|
||||
xfi = (xfInfo*) xfp->info;
|
||||
cmd = &update->surface_bits_command;
|
||||
|
||||
wrects = 16;
|
||||
@ -128,7 +211,7 @@ void xf_peer_live_rfx(freerdp_peer* client)
|
||||
|
||||
image = xf_snapshot(xfi, 0, 0, width, height);
|
||||
freerdp_image_convert((uint8*) image->data, data, width, height, 32, 24, xfi->clrconv);
|
||||
rfx_compose_message(xfp->context, s, rects, nrects, data, width, height, 64 * wrects * 3);
|
||||
rfx_compose_message(xfp->rfx_context, s, rects, nrects, data, width, height, 64 * wrects * 3);
|
||||
|
||||
cmd->destLeft = 0;
|
||||
cmd->destTop = 0;
|
||||
@ -198,7 +281,7 @@ boolean xf_peer_post_connect(freerdp_peer* client)
|
||||
* The server may start sending graphics output and receiving keyboard/mouse input after this
|
||||
* callback returns.
|
||||
*/
|
||||
printf("Client %s is activated", client->settings->hostname);
|
||||
printf("Client %s is activated", client->hostname);
|
||||
if (client->settings->autologon)
|
||||
{
|
||||
printf(" and wants to login automatically as %s\\%s",
|
||||
@ -213,7 +296,6 @@ boolean xf_peer_post_connect(freerdp_peer* client)
|
||||
client->settings->width, client->settings->height, client->settings->color_depth);
|
||||
|
||||
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
|
||||
xf_peer_init(client);
|
||||
|
||||
/* Return False here would stop the execution of the peer mainloop. */
|
||||
return True;
|
||||
@ -221,9 +303,9 @@ boolean xf_peer_post_connect(freerdp_peer* client)
|
||||
|
||||
boolean xf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
xfPeer* xfp = (xfPeer*) client->param1;
|
||||
xfPeerContext* xfp = (xfPeerContext*) client->context;
|
||||
|
||||
rfx_context_reset(xfp->context);
|
||||
rfx_context_reset(xfp->rfx_context);
|
||||
xfp->activated = True;
|
||||
|
||||
if (xf_pcap_file != NULL)
|
||||
@ -246,9 +328,9 @@ void xf_peer_synchronize_event(rdpInput* input, uint32 flags)
|
||||
|
||||
void xf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
freerdp_peer* client = (freerdp_peer*) input->param1;
|
||||
freerdp_peer* client = (freerdp_peer*) input->context->peer;
|
||||
rdpUpdate* update = client->update;
|
||||
xfPeer* xfp = (xfPeer*) client->param1;
|
||||
xfPeerContext* xfp = (xfPeerContext*) input->context;
|
||||
|
||||
printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code);
|
||||
|
||||
@ -296,7 +378,9 @@ void* xf_peer_main_loop(void* arg)
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
printf("We've got a client %s\n", client->settings->hostname);
|
||||
printf("We've got a client %s\n", client->hostname);
|
||||
|
||||
xf_peer_init(client);
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->cert_file = xstrdup("server.crt");
|
||||
@ -307,7 +391,6 @@ void* xf_peer_main_loop(void* arg)
|
||||
client->PostConnect = xf_peer_post_connect;
|
||||
client->Activate = xf_peer_activate;
|
||||
|
||||
client->input->param1 = client;
|
||||
client->input->SynchronizeEvent = xf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = xf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = xf_peer_unicode_keyboard_event;
|
||||
@ -359,10 +442,10 @@ void* xf_peer_main_loop(void* arg)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Client %s disconnected.\n", client->settings->hostname);
|
||||
printf("Client %s disconnected.\n", client->hostname);
|
||||
|
||||
client->Disconnect(client);
|
||||
xf_peer_uninit(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
return NULL;
|
||||
@ -372,7 +455,6 @@ void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
|
||||
{
|
||||
pthread_t th;
|
||||
|
||||
client->info = instance->info;
|
||||
pthread_create(&th, 0, xf_peer_main_loop, client);
|
||||
pthread_detach(th);
|
||||
}
|
||||
|
@ -24,13 +24,18 @@
|
||||
#include <freerdp/listener.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
struct xf_peer_info
|
||||
#include "xfreerdp.h"
|
||||
|
||||
struct xf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
|
||||
STREAM* s;
|
||||
xfInfo* info;
|
||||
boolean activated;
|
||||
RFX_CONTEXT* context;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
};
|
||||
typedef struct xf_peer_info xfPeer;
|
||||
typedef struct xf_peer_context xfPeerContext;
|
||||
|
||||
void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
|
||||
|
||||
|
@ -27,83 +27,6 @@
|
||||
|
||||
char* xf_pcap_file = NULL;
|
||||
|
||||
xfInfo* xf_info_init()
|
||||
{
|
||||
int i;
|
||||
xfInfo* xfi;
|
||||
int pf_count;
|
||||
int vi_count;
|
||||
XVisualInfo* vi;
|
||||
XVisualInfo* vis;
|
||||
XVisualInfo template;
|
||||
XPixmapFormatValues* pf;
|
||||
XPixmapFormatValues* pfs;
|
||||
|
||||
xfi = xnew(xfInfo);
|
||||
|
||||
xfi->display = XOpenDisplay(NULL);
|
||||
|
||||
if (xfi->display == NULL)
|
||||
printf("failed to open display: %s\n", XDisplayName(NULL));
|
||||
|
||||
xfi->number = DefaultScreen(xfi->display);
|
||||
xfi->screen = ScreenOfDisplay(xfi->display, xfi->number);
|
||||
xfi->depth = DefaultDepthOfScreen(xfi->screen);
|
||||
xfi->width = WidthOfScreen(xfi->screen);
|
||||
xfi->height = HeightOfScreen(xfi->screen);
|
||||
|
||||
pfs = XListPixmapFormats(xfi->display, &pf_count);
|
||||
|
||||
if (pfs == NULL)
|
||||
{
|
||||
printf("XListPixmapFormats failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < pf_count; i++)
|
||||
{
|
||||
pf = pfs + i;
|
||||
|
||||
if (pf->depth == xfi->depth)
|
||||
{
|
||||
xfi->bpp = pf->bits_per_pixel;
|
||||
xfi->scanline_pad = pf->scanline_pad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(pfs);
|
||||
|
||||
memset(&template, 0, sizeof(template));
|
||||
template.class = TrueColor;
|
||||
template.screen = xfi->number;
|
||||
|
||||
vis = XGetVisualInfo(xfi->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
|
||||
|
||||
if (vis == NULL)
|
||||
{
|
||||
printf("XGetVisualInfo failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < vi_count; i++)
|
||||
{
|
||||
vi = vis + i;
|
||||
|
||||
if (vi->depth == xfi->depth)
|
||||
{
|
||||
xfi->visual = vi->visual;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(vis);
|
||||
|
||||
xfi->clrconv = (HCLRCONV) xnew(HCLRCONV);
|
||||
xfi->clrconv->invert = 1;
|
||||
xfi->clrconv->alpha = 1;
|
||||
|
||||
return xfi;
|
||||
}
|
||||
|
||||
void xf_server_main_loop(freerdp_listener* instance)
|
||||
{
|
||||
int i;
|
||||
@ -172,7 +95,6 @@ int main(int argc, char* argv[])
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
instance = freerdp_listener_new();
|
||||
instance->info = (void*) xf_info_init();
|
||||
instance->PeerAccepted = xf_peer_accepted;
|
||||
|
||||
if (argc > 1)
|
||||
|
@ -40,9 +40,11 @@ static const unsigned int test_quantization_values[] =
|
||||
6, 6, 6, 6, 7, 7, 8, 8, 8, 9
|
||||
};
|
||||
|
||||
struct test_peer_info
|
||||
struct test_peer_context
|
||||
{
|
||||
RFX_CONTEXT* context;
|
||||
rdpContext _p;
|
||||
|
||||
RFX_CONTEXT* rfx_context;
|
||||
STREAM* s;
|
||||
uint8* icon_data;
|
||||
uint8* bg_data;
|
||||
@ -52,52 +54,57 @@ struct test_peer_info
|
||||
int icon_y;
|
||||
boolean activated;
|
||||
};
|
||||
typedef struct test_peer_info testPeerInfo;
|
||||
typedef struct test_peer_context testPeerContext;
|
||||
|
||||
static void test_peer_init(freerdp_peer* client)
|
||||
void test_peer_context_size(freerdp_peer* client, uint32* size)
|
||||
{
|
||||
testPeerInfo* info;
|
||||
|
||||
info = xnew(testPeerInfo);
|
||||
|
||||
info->context = rfx_context_new();
|
||||
info->context->mode = RLGR3;
|
||||
info->context->width = client->settings->width;
|
||||
info->context->height = client->settings->height;
|
||||
rfx_context_set_pixel_format(info->context, RFX_PIXEL_FORMAT_RGB);
|
||||
|
||||
info->s = stream_new(65536);
|
||||
|
||||
info->icon_x = -1;
|
||||
info->icon_y = -1;
|
||||
|
||||
client->param1 = info;
|
||||
*size = sizeof(testPeerContext);
|
||||
}
|
||||
|
||||
static void test_peer_uninit(freerdp_peer* client)
|
||||
void test_peer_context_new(freerdp_peer* client, testPeerContext* context)
|
||||
{
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = client->settings->width;
|
||||
context->rfx_context->height = client->settings->height;
|
||||
rfx_context_set_pixel_format(context->rfx_context, RFX_PIXEL_FORMAT_RGB);
|
||||
|
||||
if (info)
|
||||
context->s = stream_new(65536);
|
||||
|
||||
context->icon_x = -1;
|
||||
context->icon_y = -1;
|
||||
}
|
||||
|
||||
void test_peer_context_free(freerdp_peer* client, testPeerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
stream_free(info->s);
|
||||
xfree(info->icon_data);
|
||||
xfree(info->bg_data);
|
||||
rfx_context_free(info->context);
|
||||
xfree(info);
|
||||
stream_free(context->s);
|
||||
xfree(context->icon_data);
|
||||
xfree(context->bg_data);
|
||||
rfx_context_free(context->rfx_context);
|
||||
xfree(context);
|
||||
}
|
||||
}
|
||||
|
||||
static STREAM* test_peer_stream_init(testPeerInfo* info)
|
||||
static void test_peer_init(freerdp_peer* client)
|
||||
{
|
||||
stream_clear(info->s);
|
||||
stream_set_pos(info->s, 0);
|
||||
return info->s;
|
||||
client->ContextSize = (psPeerContextSize) test_peer_context_size;
|
||||
client->ContextNew = (psPeerContextNew) test_peer_context_new;
|
||||
client->ContextFree = (psPeerContextFree) test_peer_context_free;
|
||||
freerdp_peer_context_new(client);
|
||||
}
|
||||
|
||||
static STREAM* test_peer_stream_init(testPeerContext* context)
|
||||
{
|
||||
stream_clear(context->s);
|
||||
stream_set_pos(context->s, 0);
|
||||
return context->s;
|
||||
}
|
||||
|
||||
static void test_peer_draw_background(freerdp_peer* client)
|
||||
{
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
testPeerContext* context = (testPeerContext*) client->context;
|
||||
rdpUpdate* update = client->update;
|
||||
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
|
||||
STREAM* s;
|
||||
@ -108,7 +115,7 @@ static void test_peer_draw_background(freerdp_peer* client)
|
||||
if (!client->settings->rfx_codec)
|
||||
return;
|
||||
|
||||
s = test_peer_stream_init(info);
|
||||
s = test_peer_stream_init(context);
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
@ -119,7 +126,7 @@ static void test_peer_draw_background(freerdp_peer* client)
|
||||
rgb_data = xmalloc(size);
|
||||
memset(rgb_data, 0xA0, size);
|
||||
|
||||
rfx_compose_message(info->context, s,
|
||||
rfx_compose_message(context->rfx_context, s,
|
||||
&rect, 1, rgb_data, rect.width, rect.height, rect.width * 3);
|
||||
|
||||
cmd->destLeft = 0;
|
||||
@ -139,7 +146,7 @@ static void test_peer_draw_background(freerdp_peer* client)
|
||||
|
||||
static void test_peer_load_icon(freerdp_peer* client)
|
||||
{
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
testPeerContext* context = (testPeerContext*) client->context;
|
||||
FILE* fp;
|
||||
int i;
|
||||
char line[50];
|
||||
@ -158,13 +165,13 @@ static void test_peer_load_icon(freerdp_peer* client)
|
||||
fgets(line, sizeof(line), fp);
|
||||
/* width height */
|
||||
fgets(line, sizeof(line), fp);
|
||||
sscanf(line, "%d %d", &info->icon_width, &info->icon_height);
|
||||
sscanf(line, "%d %d", &context->icon_width, &context->icon_height);
|
||||
/* Max */
|
||||
fgets(line, sizeof(line), fp);
|
||||
|
||||
rgb_data = xmalloc(info->icon_width * info->icon_height * 3);
|
||||
rgb_data = xmalloc(context->icon_width * context->icon_height * 3);
|
||||
|
||||
for (i = 0; i < info->icon_width * info->icon_height * 3; i++)
|
||||
for (i = 0; i < context->icon_width * context->icon_height * 3; i++)
|
||||
{
|
||||
if (fgets(line, sizeof(line), fp))
|
||||
{
|
||||
@ -173,16 +180,16 @@ static void test_peer_load_icon(freerdp_peer* client)
|
||||
}
|
||||
}
|
||||
|
||||
info->icon_data = rgb_data;
|
||||
context->icon_data = rgb_data;
|
||||
|
||||
/* background with same size, which will be used to erase the icon from old position */
|
||||
info->bg_data = xmalloc(info->icon_width * info->icon_height * 3);
|
||||
memset(info->bg_data, 0xA0, info->icon_width * info->icon_height * 3);
|
||||
context->bg_data = xmalloc(context->icon_width * context->icon_height * 3);
|
||||
memset(context->bg_data, 0xA0, context->icon_width * context->icon_height * 3);
|
||||
}
|
||||
|
||||
static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
|
||||
{
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
testPeerContext* context = (testPeerContext*) client->context;
|
||||
rdpUpdate* update = client->update;
|
||||
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
|
||||
RFX_RECT rect;
|
||||
@ -190,53 +197,53 @@ static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
|
||||
|
||||
if (client->update->dump_rfx)
|
||||
return;
|
||||
if (!client->settings->rfx_codec || !info)
|
||||
if (!client->settings->rfx_codec || !context)
|
||||
return;
|
||||
if (info->icon_width < 1 || !info->activated)
|
||||
if (context->icon_width < 1 || !context->activated)
|
||||
return;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = info->icon_width;
|
||||
rect.height = info->icon_height;
|
||||
rect.width = context->icon_width;
|
||||
rect.height = context->icon_height;
|
||||
|
||||
if (info->icon_x >= 0)
|
||||
if (context->icon_x >= 0)
|
||||
{
|
||||
s = test_peer_stream_init(info);
|
||||
rfx_compose_message(info->context, s,
|
||||
&rect, 1, info->bg_data, rect.width, rect.height, rect.width * 3);
|
||||
s = test_peer_stream_init(context);
|
||||
rfx_compose_message(context->rfx_context, s,
|
||||
&rect, 1, context->bg_data, rect.width, rect.height, rect.width * 3);
|
||||
|
||||
cmd->destLeft = info->icon_x;
|
||||
cmd->destTop = info->icon_y;
|
||||
cmd->destRight = info->icon_x + info->icon_width;
|
||||
cmd->destBottom = info->icon_y + info->icon_height;
|
||||
cmd->destLeft = context->icon_x;
|
||||
cmd->destTop = context->icon_y;
|
||||
cmd->destRight = context->icon_x + context->icon_width;
|
||||
cmd->destBottom = context->icon_y + context->icon_height;
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = client->settings->rfx_codec_id;
|
||||
cmd->width = info->icon_width;
|
||||
cmd->height = info->icon_height;
|
||||
cmd->width = context->icon_width;
|
||||
cmd->height = context->icon_height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
update->SurfaceBits(update, cmd);
|
||||
}
|
||||
|
||||
s = test_peer_stream_init(info);
|
||||
rfx_compose_message(info->context, s,
|
||||
&rect, 1, info->icon_data, rect.width, rect.height, rect.width * 3);
|
||||
s = test_peer_stream_init(context);
|
||||
rfx_compose_message(context->rfx_context, s,
|
||||
&rect, 1, context->icon_data, rect.width, rect.height, rect.width * 3);
|
||||
|
||||
cmd->destLeft = x;
|
||||
cmd->destTop = y;
|
||||
cmd->destRight = x + info->icon_width;
|
||||
cmd->destBottom = y + info->icon_height;
|
||||
cmd->destRight = x + context->icon_width;
|
||||
cmd->destBottom = y + context->icon_height;
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = client->settings->rfx_codec_id;
|
||||
cmd->width = info->icon_width;
|
||||
cmd->height = info->icon_height;
|
||||
cmd->width = context->icon_width;
|
||||
cmd->height = context->icon_height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
update->SurfaceBits(update, cmd);
|
||||
|
||||
info->icon_x = x;
|
||||
info->icon_y = y;
|
||||
context->icon_x = x;
|
||||
context->icon_y = y;
|
||||
}
|
||||
|
||||
void tf_peer_dump_rfx(freerdp_peer* client)
|
||||
@ -287,7 +294,7 @@ boolean tf_peer_post_connect(freerdp_peer* client)
|
||||
* The server may start sending graphics output and receiving keyboard/mouse input after this
|
||||
* callback returns.
|
||||
*/
|
||||
printf("Client %s is activated", client->settings->hostname);
|
||||
printf("Client %s is activated", client->hostname);
|
||||
if (client->settings->autologon)
|
||||
{
|
||||
printf(" and wants to login automatically as %s\\%s",
|
||||
@ -302,7 +309,6 @@ boolean tf_peer_post_connect(freerdp_peer* client)
|
||||
client->settings->width, client->settings->height, client->settings->color_depth);
|
||||
|
||||
/* A real server should tag the peer as activated here and start sending updates in mainloop. */
|
||||
test_peer_init(client);
|
||||
test_peer_load_icon(client);
|
||||
|
||||
/* Return False here would stop the execution of the peer mainloop. */
|
||||
@ -311,10 +317,10 @@ boolean tf_peer_post_connect(freerdp_peer* client)
|
||||
|
||||
boolean tf_peer_activate(freerdp_peer* client)
|
||||
{
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
testPeerContext* context = (testPeerContext*) client->context;
|
||||
|
||||
rfx_context_reset(info->context);
|
||||
info->activated = True;
|
||||
rfx_context_reset(context->rfx_context);
|
||||
context->activated = True;
|
||||
|
||||
if (test_pcap_file != NULL)
|
||||
{
|
||||
@ -336,9 +342,9 @@ void tf_peer_synchronize_event(rdpInput* input, uint32 flags)
|
||||
|
||||
void tf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
{
|
||||
freerdp_peer* client = (freerdp_peer*) input->param1;
|
||||
freerdp_peer* client = input->context->peer;
|
||||
rdpUpdate* update = client->update;
|
||||
testPeerInfo* info = (testPeerInfo*)client->param1;
|
||||
testPeerContext* context = (testPeerContext*) input->context;
|
||||
|
||||
printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code);
|
||||
|
||||
@ -355,7 +361,7 @@ void tf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code)
|
||||
client->settings->height = 480;
|
||||
}
|
||||
update->DesktopResize(update);
|
||||
info->activated = False;
|
||||
context->activated = False;
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +374,7 @@ void tf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
|
||||
{
|
||||
printf("Client sent a mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y);
|
||||
|
||||
test_peer_draw_icon(input->param1, x + 10, y);
|
||||
test_peer_draw_icon(input->context->peer, x + 10, y);
|
||||
}
|
||||
|
||||
void tf_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
|
||||
@ -388,7 +394,7 @@ static void* test_peer_mainloop(void* arg)
|
||||
|
||||
memset(rfds, 0, sizeof(rfds));
|
||||
|
||||
printf("We've got a client %s\n", client->settings->hostname);
|
||||
test_peer_init(client);
|
||||
|
||||
/* Initialize the real server settings here */
|
||||
client->settings->cert_file = xstrdup("server.crt");
|
||||
@ -399,7 +405,6 @@ static void* test_peer_mainloop(void* arg)
|
||||
client->PostConnect = tf_peer_post_connect;
|
||||
client->Activate = tf_peer_activate;
|
||||
|
||||
client->input->param1 = client;
|
||||
client->input->SynchronizeEvent = tf_peer_synchronize_event;
|
||||
client->input->KeyboardEvent = tf_peer_keyboard_event;
|
||||
client->input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event;
|
||||
@ -408,6 +413,8 @@ static void* test_peer_mainloop(void* arg)
|
||||
|
||||
client->Initialize(client);
|
||||
|
||||
printf("We've got a client %s\n", client->hostname);
|
||||
|
||||
while (1)
|
||||
{
|
||||
rcount = 0;
|
||||
@ -451,10 +458,10 @@ static void* test_peer_mainloop(void* arg)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Client %s disconnected.\n", client->settings->hostname);
|
||||
printf("Client %s disconnected.\n", client->hostname);
|
||||
|
||||
client->Disconnect(client);
|
||||
test_peer_uninit(client);
|
||||
freerdp_peer_context_free(client);
|
||||
freerdp_peer_free(client);
|
||||
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user