From c79c587ca901e3c1d1ace8ba139c4e47e986808a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Tue, 23 Aug 2011 23:28:28 +0800 Subject: [PATCH] server: add SurfaceCmds update. --- libfreerdp-core/fastpath.c | 91 ++++++++++++++++++++++++++++++++++---- libfreerdp-core/fastpath.h | 8 ++-- libfreerdp-core/surface.c | 32 ++++++++++++++ libfreerdp-core/surface.h | 3 ++ libfreerdp-core/update.c | 8 ++++ 5 files changed, 130 insertions(+), 12 deletions(-) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index 1a1de6df3..7dd5a048a 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -38,6 +38,8 @@ * two less significant bits of the first byte. */ +#define FASTPATH_MAX_PACKET_SIZE 0x7FFF + /** * Read a Fast-Path packet header.\n * @param s stream @@ -410,18 +412,19 @@ boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s) return True; } -STREAM* fastpath_pdu_init(rdpFastPath* fastpath) +STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode) { STREAM* s; s = transport_send_stream_init(fastpath->rdp->transport, 127); stream_seek(s, 2); /* fpInputHeader and length1 */ /* length2 is not necessary since input PDU should not exceed 127 bytes */ + stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */ return s; } -boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) +boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s) { - int length; + uint16 length; length = stream_get_length(s); if (length > 127) @@ -431,7 +434,7 @@ boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) } stream_set_pos(s, 0); - stream_write_uint8(s, (numberEvents << 2)); + stream_write_uint8(s, (1 << 2)); stream_write_uint8(s, length); stream_set_pos(s, length); @@ -441,17 +444,87 @@ boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents) return True; } -STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode) +STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath) { STREAM* s; - s = fastpath_pdu_init(fastpath); - stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */ + s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE); + stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */ return s; } -boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s) +boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s) { - return fastpath_send_pdu(fastpath, s, 1); + uint16 length; + + length = stream_get_length(s); + if (length > FASTPATH_MAX_PACKET_SIZE) + { + printf("Maximum FastPath Update PDU length is %d\n", FASTPATH_MAX_PACKET_SIZE); + return False; + } + + stream_set_pos(s, 0); + stream_write_uint8(s, 0); /* fpOutputHeader (1 byte) */ + stream_write_uint8(s, 0x80 | (length >> 8)); /* length1 */ + stream_write_uint8(s, length & 0xFF); /* length2 */ + + stream_set_pos(s, length); + if (transport_write(fastpath->rdp->transport, s) < 0) + return False; + + return True; +} + +boolean fastpath_send_surface_bits(rdpFastPath* fastpath, SURFACE_BITS_COMMAND* cmd) +{ + STREAM* s; + uint16 size; + uint8* bitmapData; + uint32 bitmapDataLength; + uint16 fragment_size; + uint8 fragmentation; + int i; + int bp, ep; + + bitmapData = cmd->bitmapData; + bitmapDataLength = cmd->bitmapDataLength; + for (i = 0; bitmapDataLength > 0; i++) + { + s = fastpath_update_pdu_init(fastpath); + + bp = stream_get_pos(s); + stream_seek_uint8(s); /* updateHeader (1 byte) */ + stream_seek_uint16(s); /* size (2 bytes) */ + size = 0; + + if (i == 0) + size += update_write_surfcmd_surface_bits_header(s, cmd); + + fragment_size = MIN(stream_get_left(s), bitmapDataLength); + if (fragment_size == bitmapDataLength) + { + fragmentation = (i == 0 ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST); + } + else + { + fragmentation = (i == 0 ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT); + } + size += fragment_size; + + ep = stream_get_pos(s); + stream_set_pos(s, bp); + stream_write_uint8(s, FASTPATH_UPDATETYPE_SURFCMDS | (fragmentation << 4)); + stream_write_uint16(s, size); + stream_set_pos(s, ep); + + stream_write(s, bitmapData, fragment_size); + bitmapData += fragment_size; + bitmapDataLength -= fragment_size; + + if (!fastpath_send_update_pdu(fastpath, s)) + return False; + } + return True; } rdpFastPath* fastpath_new(rdpRdp* rdp) diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index a047f97e6..7f13b7d12 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -102,12 +102,14 @@ boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s); -STREAM* fastpath_pdu_init(rdpFastPath* fastpath); -boolean fastpath_send_pdu(rdpFastPath* fastpath, STREAM* s, uint8 numberEvents); - STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode); 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); + rdpFastPath* fastpath_new(rdpRdp* rdp); void fastpath_free(rdpFastPath* fastpath); diff --git a/libfreerdp-core/surface.c b/libfreerdp-core/surface.c index 2e797fce7..48fa014ed 100644 --- a/libfreerdp-core/surface.c +++ b/libfreerdp-core/surface.c @@ -84,3 +84,35 @@ 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) +{ + stream_check_size(s, 22); + + stream_write_uint16(s, CMDTYPE_STREAM_SURFACE_BITS); + + stream_write_uint16(s, cmd->destLeft); + stream_write_uint16(s, cmd->destTop); + stream_write_uint16(s, cmd->destRight); + stream_write_uint16(s, cmd->destBottom); + stream_write_uint8(s, cmd->bpp); + stream_write_uint16(s, 0); /* reserved1, reserved2 */ + stream_write_uint8(s, cmd->codecID); + 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) +{ + stream_check_size(s, 8); + + stream_write_uint16(s, CMDTYPE_FRAME_MARKER); + + stream_write_uint16(s, frameAction); + stream_write_uint32(s, frameId); + + return 8; +} + diff --git a/libfreerdp-core/surface.h b/libfreerdp-core/surface.h index 960f5cbbf..37a9d069b 100644 --- a/libfreerdp-core/surface.h +++ b/libfreerdp-core/surface.h @@ -25,5 +25,8 @@ 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); + #endif /* __SURFACE */ diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 54163639b..c8a9bf65c 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -225,10 +225,18 @@ static void update_end_paint(rdpUpdate* update) { } +static void update_send_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command) +{ + rdpRdp* rdp = (rdpRdp*)update->rdp; + + fastpath_send_surface_bits(rdp->fastpath, surface_bits_command); +} + void update_register_server_callbacks(rdpUpdate* update) { update->BeginPaint = update_begin_paint; update->EndPaint = update_end_paint; + update->SurfaceBits = update_send_surface_bits; } rdpUpdate* update_new(rdpRdp* rdp)