Merge pull request #62 from llyzs/server

Server: fix various bugs for mstsc client and enhance the server demo.
This commit is contained in:
Otavio Salvador 2011-08-24 08:33:04 -07:00
commit 4fe32908de
13 changed files with 5922 additions and 139 deletions

View File

@ -292,7 +292,8 @@ struct rdp_settings
boolean desktop_composition;
boolean rfx_decode;
boolean rfx_codec;
uint8 rfx_codec_id;
boolean frame_acknowledge;
boolean remote_app;

View File

@ -53,6 +53,9 @@ uint8 CAPSET_TYPE_STRINGS[][32] =
"Bitmap Codecs"
};
/* CODEC_GUID_REMOTEFX 0x76772F12BD724463AFB3B73C9C6F7886 */
#define CODEC_GUID_REMOTEFX "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86"
void rdp_read_capability_set_header(STREAM* s, uint16* length, uint16* type)
{
stream_read_uint16(s, *type); /* capabilitySetType */
@ -1323,10 +1326,24 @@ void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
stream_read_uint8(s, bitmapCodecCount); /* bitmapCodecCount (1 byte) */
if (settings->server_mode)
{
settings->rfx_codec = False;
}
while (bitmapCodecCount > 0)
{
stream_seek(s, 16); /* codecGUID (16 bytes) */
stream_seek_uint8(s); /* codecID (1 byte) */
if (settings->server_mode && strncmp((char*)stream_get_tail(s), CODEC_GUID_REMOTEFX, 16) == 0)
{
stream_seek(s, 16); /* codecGUID (16 bytes) */
stream_read_uint8(s, settings->rfx_codec_id);
settings->rfx_codec = True;
}
else
{
stream_seek(s, 16); /* codecGUID (16 bytes) */
stream_seek_uint8(s); /* codecID (1 byte) */
}
stream_read_uint16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */
stream_seek(s, codecPropertiesLength); /* codecProperties */
@ -1335,6 +1352,61 @@ void rdp_read_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
}
}
/**
* Write RemoteFX Client Capability Container.\n
* @param s stream
* @param settings settings
*/
void rdp_write_rfx_client_capability_container(STREAM* s, rdpSettings* settings)
{
stream_write_uint16(s, 49); /* codecPropertiesLength */
/* TS_RFX_CLNT_CAPS_CONTAINER */
stream_write_uint32(s, 49); /* length */
stream_write_uint32(s, CARDP_CAPS_CAPTURE_NON_CAC); /* captureFlags */
stream_write_uint32(s, 37); /* capsLength */
/* TS_RFX_CAPS */
stream_write_uint16(s, CBY_CAPS); /* blockType */
stream_write_uint32(s, 8); /* blockLen */
stream_write_uint16(s, 1); /* numCapsets */
/* TS_RFX_CAPSET */
stream_write_uint16(s, CBY_CAPSET); /* blockType */
stream_write_uint32(s, 29); /* blockLen */
stream_write_uint8(s, 0x01); /* codecId (MUST be set to 0x01) */
stream_write_uint16(s, CLY_CAPSET); /* capsetType */
stream_write_uint16(s, 2); /* numIcaps */
stream_write_uint16(s, 8); /* icapLen */
/* TS_RFX_ICAP (RLGR1) */
stream_write_uint16(s, CLW_VERSION_1_0); /* version */
stream_write_uint16(s, CT_TILE_64x64); /* tileSize */
stream_write_uint8(s, 0); /* flags */
stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */
stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */
stream_write_uint8(s, CLW_ENTROPY_RLGR1); /* entropyBits */
/* TS_RFX_ICAP (RLGR3) */
stream_write_uint16(s, CLW_VERSION_1_0); /* version */
stream_write_uint16(s, CT_TILE_64x64); /* tileSize */
stream_write_uint8(s, 0); /* flags */
stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */
stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */
stream_write_uint8(s, CLW_ENTROPY_RLGR3); /* entropyBits */
}
/**
* Write RemoteFX Server Capability Container.\n
* @param s stream
* @param settings settings
*/
void rdp_write_rfx_server_capability_container(STREAM* s, rdpSettings* settings)
{
stream_write_uint16(s, 4); /* codecPropertiesLength */
stream_write_uint32(s, 0); /* reserved */
}
/**
* Write bitmap codecs capability set.\n
* @msdn{dd891377}
@ -1350,51 +1422,25 @@ void rdp_write_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
header = rdp_capability_set_start(s);
bitmapCodecCount = 0;
if (settings->rfx_decode)
if (settings->rfx_codec)
bitmapCodecCount++;
stream_write_uint8(s, bitmapCodecCount);
if (settings->rfx_decode)
if (settings->rfx_codec)
{
/* CODEC_GUID_REMOTEFX 0x76772F12BD724463AFB3B73C9C6F7886 */
stream_write(s, "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86", 16); /* codecGUID */
stream_write_uint8(s, CODEC_ID_REMOTEFX); /* codecID */
stream_write_uint16(s, 49); /* codecPropertiesLength */
stream_write(s, CODEC_GUID_REMOTEFX, 16); /* codecGUID */
/* TS_RFX_CLNT_CAPS_CONTAINER */
stream_write_uint32(s, 49); /* length */
stream_write_uint32(s, CARDP_CAPS_CAPTURE_NON_CAC); /* captureFlags */
stream_write_uint32(s, 37); /* capsLength */
/* TS_RFX_CAPS */
stream_write_uint16(s, CBY_CAPS); /* blockType */
stream_write_uint32(s, 8); /* blockLen */
stream_write_uint16(s, 1); /* numCapsets */
/* TS_RFX_CAPSET */
stream_write_uint16(s, CBY_CAPSET); /* blockType */
stream_write_uint32(s, 29); /* blockLen */
stream_write_uint8(s, 0x01); /* codecId (MUST be set to 0x01) */
stream_write_uint16(s, CLY_CAPSET); /* capsetType */
stream_write_uint16(s, 2); /* numIcaps */
stream_write_uint16(s, 8); /* icapLen */
/* TS_RFX_ICAP (RLGR1) */
stream_write_uint16(s, CLW_VERSION_1_0); /* version */
stream_write_uint16(s, CT_TILE_64x64); /* tileSize */
stream_write_uint8(s, 0); /* flags */
stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */
stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */
stream_write_uint8(s, CLW_ENTROPY_RLGR1); /* entropyBits */
/* TS_RFX_ICAP (RLGR3) */
stream_write_uint16(s, CLW_VERSION_1_0); /* version */
stream_write_uint16(s, CT_TILE_64x64); /* tileSize */
stream_write_uint8(s, 0); /* flags */
stream_write_uint8(s, CLW_COL_CONV_ICT); /* colConvBits */
stream_write_uint8(s, CLW_XFORM_DWT_53_A); /* transformBits */
stream_write_uint8(s, CLW_ENTROPY_RLGR3); /* entropyBits */
if (settings->server_mode)
{
stream_write_uint8(s, 0); /* codecID is defined by the client */
rdp_write_rfx_server_capability_container(s, settings);
}
else
{
stream_write_uint8(s, CODEC_ID_REMOTEFX); /* codecID */
rdp_write_rfx_client_capability_container(s, settings);
}
}
rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS);

View File

@ -475,7 +475,23 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s)
return True;
}
boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd)
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId)
{
STREAM* s;
s = transport_send_stream_init(fastpath->rdp->transport, 127);
stream_write_uint8(s, 0); /* fpOutputHeader (1 byte) */
stream_write_uint8(s, 5 + SURFCMD_FRAME_MARKER_LENGTH); /* length1 */
stream_write_uint8(s, FASTPATH_UPDATETYPE_SURFCMDS); /* updateHeader (1 byte) */
stream_write_uint16(s, SURFCMD_FRAME_MARKER_LENGTH); /* size (2 bytes) */
update_write_surfcmd_frame_marker(s, frameAction, frameId);
if (transport_write(fastpath->rdp->transport, s) < 0)
return False;
return True;
}
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd)
{
STREAM* s;
uint16 size;
@ -498,7 +514,10 @@ boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND*
size = 0;
if (i == 0)
size += update_write_surfcmd_surface_bits_header(s, cmd);
{
update_write_surfcmd_surface_bits_header(s, cmd);
size += SURFCMD_SURFACE_BITS_HEADER_LENGTH;
}
fragment_size = MIN(stream_get_left(s), bitmapDataLength);
if (fragment_size == bitmapDataLength)
@ -524,6 +543,7 @@ boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND*
if (!fastpath_send_update_pdu(fastpath, s))
return False;
}
return True;
}

View File

@ -60,13 +60,6 @@ enum FASTPATH_FRAGMENT
FASTPATH_FRAGMENT_NEXT = 0x3
};
enum SURFCMD_CMDTYPE
{
CMDTYPE_SET_SURFACE_BITS = 0x0001,
CMDTYPE_FRAME_MARKER = 0x0004,
CMDTYPE_STREAM_SURFACE_BITS = 0x0006
};
enum FASTPATH_OUTPUT_COMPRESSION
{
FASTPATH_OUTPUT_COMPRESSION_USED = 0x2
@ -108,7 +101,8 @@ boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s);
STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath);
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s);
boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId);
boolean fastpath_send_surfcmd_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd);
rdpFastPath* fastpath_new(rdpRdp* rdp);
void fastpath_free(rdpFastPath* fastpath);

View File

@ -84,9 +84,9 @@ boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s)
return True;
}
int update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd)
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd)
{
stream_check_size(s, 22);
stream_check_size(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH);
stream_write_uint16(s, CMDTYPE_STREAM_SURFACE_BITS);
@ -100,19 +100,15 @@ int update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cm
stream_write_uint16(s, cmd->width);
stream_write_uint16(s, cmd->height);
stream_write_uint32(s, cmd->bitmapDataLength);
return 22;
}
int update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId)
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId)
{
stream_check_size(s, 8);
stream_check_size(s, SURFCMD_FRAME_MARKER_LENGTH);
stream_write_uint16(s, CMDTYPE_FRAME_MARKER);
stream_write_uint16(s, frameAction);
stream_write_uint32(s, frameId);
return 8;
}

View File

@ -23,10 +23,26 @@
#include "rdp.h"
#include <freerdp/utils/stream.h>
#define SURFCMD_SURFACE_BITS_HEADER_LENGTH 22
#define SURFCMD_FRAME_MARKER_LENGTH 8
enum SURFCMD_CMDTYPE
{
CMDTYPE_SET_SURFACE_BITS = 0x0001,
CMDTYPE_FRAME_MARKER = 0x0004,
CMDTYPE_STREAM_SURFACE_BITS = 0x0006
};
enum SURFCMD_FRAME_ACTION
{
SURFACECMD_FRAMEACTION_BEGIN = 0x0000,
SURFACECMD_FRAMEACTION_END = 0x0001
};
boolean update_recv_surfcmds(rdpUpdate* update, uint16 size, STREAM* s);
int update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
int update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
void update_write_surfcmd_surface_bits_header(STREAM* s, SURFACE_BITS_COMMAND* cmd);
void update_write_surfcmd_frame_marker(STREAM* s, uint16 frameAction, uint32 frameId);
#endif /* __SURFACE */

View File

@ -19,6 +19,7 @@
#include "update.h"
#include "bitmap.h"
#include "surface.h"
uint8 UPDATE_TYPE_STRINGS[][32] =
{
@ -326,7 +327,7 @@ static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* su
{
rdpRdp* rdp = (rdpRdp*)update->rdp;
fastpath_send_surface_bits(rdp->fastpath, surface_bits_command);
fastpath_send_surfcmd_surface_bits(rdp->fastpath, surface_bits_command);
}
void update_register_server_callbacks(rdpUpdate* update)

View File

@ -808,7 +808,7 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm
message->rects[i].width, message->rects[i].height);
}
}
else /* RDSH */
else if (message->num_rects == 1) /* RDSH */
{
gdi_SetClipRgn(gdi->primary->hdc,
surface_bits_command->destLeft + message->rects[0].x,

View File

@ -614,6 +614,14 @@ static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* data_out)
properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */
properties |= (SCALAR_QUANTIZATION << 13); /* qt */
stream_write_uint16(data_out, properties);
/* properties in tilesets: note that this has different format from the one in TS_RFX_CONTEXT */
properties = 1; /* lt */
properties |= (context->flags << 1); /* flags */
properties |= (COL_CONV_ICT << 4); /* cct */
properties |= (CLW_XFORM_DWT_53_A << 6); /* xft */
properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 10); /* et */
properties |= (SCALAR_QUANTIZATION << 14); /* qt */
context->properties = properties;
}
@ -622,9 +630,9 @@ void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* data_out)
stream_check_size(data_out, 12 + 10 + 12 + 13);
rfx_compose_message_sync(context, data_out);
rfx_compose_message_context(context, data_out);
rfx_compose_message_codec_versions(context, data_out);
rfx_compose_message_channels(context, data_out);
rfx_compose_message_context(context, data_out);
}
static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, STREAM* data_out)

View File

@ -262,13 +262,13 @@ int rfx_rlgr_decode(RLGR_MODE mode, const uint8* data, int data_size, sint16* bu
/* Outputs the Golomb/Rice encoding of a non-negative integer */
#define CodeGR(krp, val) rfx_rlgr_code_gr(bs, krp, val)
static void rfx_rlgr_code_gr(RFX_BITSTREAM* bs, int* krp, uint16 val)
static void rfx_rlgr_code_gr(RFX_BITSTREAM* bs, int* krp, uint32 val)
{
int kr = *krp >> LSGR;
/* unary part of GR code */
uint16 vk = (val) >> kr;
uint32 vk = (val) >> kr;
OutputBit(vk, 1);
OutputBit(1, 0);
@ -344,17 +344,17 @@ int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* bu
/* output the remaining run length using k bits */
OutputBits(k, numZeros);
if (input != 0)
{
/* encode the nonzero value using GR coding */
mag = (input < 0 ? -input : input); /* absolute value of input coefficient */
sign = (input < 0 ? 1 : 0); /* sign of input coefficient */
/* note: when we reach here and the last byte being encoded is 0, we still
need to output the last two bits, otherwise mstsc will crash */
OutputBit(1, sign); /* output the sign bit */
CodeGR(&krp, mag - 1); /* output GR code for (mag - 1) */
/* encode the nonzero value using GR coding */
mag = (input < 0 ? -input : input); /* absolute value of input coefficient */
sign = (input < 0 ? 1 : 0); /* sign of input coefficient */
UpdateParam(kp, -DN_GR, k);
}
OutputBit(1, sign); /* output the sign bit */
CodeGR(&krp, mag ? mag - 1 : 0); /* output GR code for (mag - 1) */
UpdateParam(kp, -DN_GR, k);
}
else
{
@ -372,13 +372,15 @@ int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* bu
CodeGR(&krp, twoMs);
/* update k, kp */
/* NOTE: as of Aug 2011, the algorithm is still wrongly documented
and the update direction is reversed */
if (twoMs)
{
UpdateParam(kp, UQ_GR, k);
UpdateParam(kp, -DQ_GR, k);
}
else
{
UpdateParam(kp, -DQ_GR, k);
UpdateParam(kp, UQ_GR, k);
}
}
else /* mode == RLGR3 */

View File

@ -203,7 +203,7 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
}
else if (strcmp("--rfx", argv[index]) == 0)
{
settings->rfx_decode = True;
settings->rfx_codec = True;
settings->fastpath_output = True;
settings->color_depth = 32;
settings->frame_acknowledge = False;

View File

@ -3,6 +3,7 @@
* FreeRDP Test Server
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,88 +35,208 @@ static const unsigned int test_quantization_values[] =
6, 6, 6, 6, 7, 7, 8, 8, 8, 9
};
static const uint8 rgb_scanline_data[] =
struct test_peer_info
{
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF
RFX_CONTEXT* context;
STREAM* bg_s;
STREAM* icon_s;
int icon_width;
int icon_height;
int icon_x;
int icon_y;
};
typedef struct test_peer_info testPeerInfo;
void test_peer_init_desktop(freerdp_peer* client)
static void test_peer_init(freerdp_peer* client)
{
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->bg_s = stream_new(65536);
info->icon_s = stream_new(65536);
info->icon_x = -1;
info->icon_y = -1;
client->param1 = info;
}
static void test_peer_uninit(freerdp_peer* client)
{
testPeerInfo* info = (testPeerInfo*)client->param1;
if (info)
{
stream_free(info->bg_s);
stream_free(info->icon_s);
rfx_context_free(info->context);
xfree(info);
}
}
static STREAM* test_peer_stream_init(testPeerInfo* info, boolean icon)
{
if (icon)
{
stream_clear(info->icon_s);
stream_set_pos(info->icon_s, 0);
return info->icon_s;
}
else
{
stream_clear(info->bg_s);
stream_set_pos(info->bg_s, 0);
return info->bg_s;
}
}
static void test_peer_draw_background(freerdp_peer* client)
{
testPeerInfo* info = (testPeerInfo*)client->param1;
rdpUpdate* update = client->update;
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
RFX_CONTEXT* context;
uint8* rgb_data;
STREAM* s;
int i;
RFX_RECT rect = {0, 0, 100, 80};
RFX_RECT rect;
uint8* rgb_data;
int size;
rgb_data = (uint8*) xmalloc(100 * 80 * 3);
for (i = 0; i < 80; i++)
memcpy(rgb_data + i * 100 * 3, rgb_scanline_data, 100 * 3);
if (!client->settings->rfx_codec)
return;
s = stream_new(65536);
stream_clear(s);
s = test_peer_stream_init(info, False);
context = rfx_context_new();
context->mode = RLGR3;
context->width = 800;
context->height = 600;
rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB);
rect.x = 0;
rect.y = 0;
rect.width = client->settings->width;
rect.height = client->settings->height;
size = rect.width * rect.height * 3;
rgb_data = xmalloc(size);
memset(rgb_data, 0xA0, size);
/* In Video mode, the RemoteFX header should only be sent once */
rfx_compose_message_header(context, s);
rfx_compose_message_header(info->context, s);
rfx_compose_message_data(info->context, s,
&rect, 1, rgb_data, rect.width, rect.height, rect.width * 3);
rfx_compose_message_data(context, s,
&rect, 1, rgb_data, 100, 80, 100 * 3);
cmd->destLeft = 0;
cmd->destTop = 0;
cmd->destRight = 100;
cmd->destBottom = 80;
cmd->destRight = rect.width;
cmd->destBottom = rect.height;
cmd->bpp = 32;
cmd->codecID = CODEC_ID_REMOTEFX;
cmd->width = 100;
cmd->height = 80;
cmd->codecID = client->settings->rfx_codec_id;
cmd->width = rect.width;
cmd->height = rect.height;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
update->SurfaceBits(update, cmd);
stream_free(s);
rfx_context_free(context);
xfree(rgb_data);
}
static void test_peer_load_icon(freerdp_peer* client)
{
testPeerInfo* info = (testPeerInfo*)client->param1;
STREAM* s;
FILE* fp;
int i;
char line[50];
uint8* rgb_data;
int c;
RFX_RECT rect;
if (!client->settings->rfx_codec)
return;
s = test_peer_stream_init(info, True);
if ((fp = fopen("test_icon.ppm", "r")) == NULL)
return;
/* P3 */
fgets(line, sizeof(line), fp);
/* Creater comment */
fgets(line, sizeof(line), fp);
/* width height */
fgets(line, sizeof(line), fp);
sscanf(line, "%d %d", &info->icon_width, &info->icon_height);
/* Max */
fgets(line, sizeof(line), fp);
rgb_data = xmalloc(info->icon_width * info->icon_height * 3);
for (i = 0; i < info->icon_width * info->icon_height * 3; i++)
{
if (fgets(line, sizeof(line), fp))
{
sscanf(line, "%d", &c);
rgb_data[i] = (uint8)c;
}
}
rect.x = 0;
rect.y = 0;
rect.width = info->icon_width;
rect.height = info->icon_height;
rfx_compose_message_data(info->context, s,
&rect, 1, rgb_data, rect.width, rect.height, rect.width * 3);
/* background with same size */
s = test_peer_stream_init(info, False);
memset(rgb_data, 0xA0, info->icon_width * info->icon_height * 3);
rfx_compose_message_data(info->context, s,
&rect, 1, rgb_data, rect.width, rect.height, rect.width * 3);
xfree(rgb_data);
}
static void test_peer_draw_icon(freerdp_peer* client, int x, int y)
{
testPeerInfo* info = (testPeerInfo*)client->param1;
rdpUpdate* update = client->update;
SURFACE_BITS_COMMAND* cmd = &update->surface_bits_command;
if (!client->settings->rfx_codec)
return;
if (stream_get_length(info->icon_s) < 1)
return;
cmd->destRight = info->icon_width;
cmd->destBottom = info->icon_height;
cmd->bpp = 32;
cmd->codecID = client->settings->rfx_codec_id;
cmd->width = info->icon_width;
cmd->height = info->icon_height;
if (info->icon_x >= 0)
{
cmd->destLeft = info->icon_x;
cmd->destTop = info->icon_y;
cmd->bitmapDataLength = stream_get_length(info->bg_s);
cmd->bitmapData = stream_get_head(info->bg_s);
update->SurfaceBits(update, cmd);
}
cmd->destLeft = x;
cmd->destTop = y;
cmd->bitmapDataLength = stream_get_length(info->icon_s);
cmd->bitmapData = stream_get_head(info->icon_s);
update->SurfaceBits(update, cmd);
info->icon_x = x;
info->icon_y = y;
}
boolean test_peer_post_connect(freerdp_peer* client)
{
/**
@ -139,7 +260,9 @@ boolean test_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_desktop(client);
test_peer_init(client);
test_peer_draw_background(client);
test_peer_load_icon(client);
/* Return False here would stop the execution of the peer mainloop. */
return True;
@ -163,6 +286,8 @@ void test_peer_unicode_keyboard_event(rdpInput* input, uint16 code)
void test_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, y);
}
void test_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y)
@ -188,6 +313,7 @@ static void* test_peer_mainloop(void* arg)
client->settings->cert_file = xstrdup("server.crt");
client->settings->privatekey_file = xstrdup("server.key");
client->settings->nla_security = False;
client->settings->rfx_codec = True;
client->PostConnect = test_peer_post_connect;
@ -246,6 +372,7 @@ static void* test_peer_mainloop(void* arg)
printf("Client %s disconnected.\n", client->settings->hostname);
client->Disconnect(client);
test_peer_uninit(client);
freerdp_peer_free(client);
return NULL;

5572
server/test/test_icon.ppm Normal file

File diff suppressed because it is too large Load Diff