From 28d1abdd62907dd0a34651995de5de31f4c8d273 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sat, 3 Dec 2011 14:42:13 +0800 Subject: [PATCH] fastpath: refactor fastpath updates and merge fragmented codes. --- libfreerdp-core/fastpath.c | 118 ++++++++++--------------------------- libfreerdp-core/fastpath.h | 4 +- libfreerdp-core/update.c | 51 ++++++++-------- 3 files changed, 55 insertions(+), 118 deletions(-) diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index 327f10839..6f6d9dfa8 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -516,66 +516,64 @@ STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath) STREAM* s; s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE); stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */ + stream_seek(s, 3); /* updateHeader, size */ return s; } -boolean fastpath_send_update_pdu(rdpFastPath* fastpath, STREAM* s) -{ - uint16 length; - - length = stream_get_length(s); - - if (length > FASTPATH_MAX_PACKET_SIZE) - { - printf("Maximum FastPath Update PDU length is %d (actual:%d)\n", FASTPATH_MAX_PACKET_SIZE, length); - 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_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s) +boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s) { + uint8* bm; int fragment; uint16 length; + boolean result; + uint16 pduLength; uint16 maxLength; uint32 totalLength; uint8 fragmentation; STREAM* update; + result = true; + maxLength = FASTPATH_MAX_PACKET_SIZE - 6; - totalLength = stream_get_length(s); + totalLength = stream_get_length(s) - 6; stream_set_pos(s, 0); + update = stream_new(0); for (fragment = 0; totalLength > 0; fragment++) { - update = fastpath_update_pdu_init(fastpath); length = MIN(maxLength, totalLength); totalLength -= length; + pduLength = length + 6; if (totalLength == 0) fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST; else fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT; - fastpath_write_update_header(update, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0); - stream_write_uint16(update, length); - stream_write(update, s->p, length); - stream_seek(s, length); + stream_get_mark(s, bm); + stream_write_uint8(s, 0); /* fpOutputHeader (1 byte) */ + stream_write_uint8(s, 0x80 | (pduLength >> 8)); /* length1 */ + stream_write_uint8(s, pduLength & 0xFF); /* length2 */ + fastpath_write_update_header(s, updateCode, fragmentation, 0); + stream_write_uint16(s, length); - fastpath_send_update_pdu(fastpath, update); + stream_attach(update, bm, pduLength); + stream_seek(update, pduLength); + if (transport_write(fastpath->rdp->transport, update) < 0) + { + stream_detach(update); + result = false; + break; + } + stream_detach(update); + + /* Reserve 6 bytes for the next fragment header, if any. */ + stream_seek(s, length - 6); } - return true; + stream_free(update); + + return result; } boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAction, uint32 frameId) @@ -594,60 +592,6 @@ boolean fastpath_send_surfcmd_frame_marker(rdpFastPath* fastpath, uint16 frameAc return true; } -boolean fastpath_send_surfcmd_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) - { - update_write_surfcmd_surface_bits_header(s, cmd); - size += SURFCMD_SURFACE_BITS_HEADER_LENGTH; - } - - fragment_size = MIN((uint32)(FASTPATH_MAX_PACKET_SIZE - stream_get_length(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); - fastpath_write_update_header(s, FASTPATH_UPDATETYPE_SURFCMDS, fragmentation, 0); - 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) { rdpFastPath* fastpath; diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index 69f32e234..1997e1209 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -99,11 +99,9 @@ STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 e 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_fragmented_update_pdu(rdpFastPath* fastpath, STREAM* s); +boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s); 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); diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index d3446d40c..7baaaa90d 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -388,14 +388,25 @@ static void update_send_suppress_output(rdpContext* context, uint8 allow, RECTAN static void update_send_surface_command(rdpContext* context, STREAM* s) { + STREAM* update; rdpRdp* rdp = context->rdp; - fastpath_send_fragmented_update_pdu(rdp->fastpath, s); + + update = fastpath_update_pdu_init(rdp->fastpath); + stream_check_size(update, stream_get_length(s)); + stream_write(update, stream_get_head(s), stream_get_length(s)); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update); } static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command) { + STREAM* s; rdpRdp* rdp = context->rdp; - fastpath_send_surfcmd_surface_bits(rdp->fastpath, surface_bits_command); + + s = fastpath_update_pdu_init(rdp->fastpath); + stream_check_size(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + surface_bits_command->bitmapDataLength); + update_write_surfcmd_surface_bits_header(s, surface_bits_command); + stream_write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s); } static void update_send_synchronize(rdpContext* context) @@ -404,9 +415,7 @@ static void update_send_synchronize(rdpContext* context) rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); - stream_write_uint8(s, FASTPATH_UPDATETYPE_SYNCHRONIZE); /* updateHeader (1 byte) */ - stream_write_uint16(s, 0); /* size (2 bytes) */ - fastpath_send_update_pdu(rdp->fastpath, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s); } static void update_send_desktop_resize(rdpContext* context) @@ -421,8 +430,6 @@ static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) s = fastpath_update_pdu_init(rdp->fastpath); - stream_write_uint8(s, FASTPATH_UPDATETYPE_ORDERS); /* updateHeader (1 byte) */ - stream_write_uint16(s, 18); /* size (2 bytes) */ stream_write_uint16(s, 1); /* numberOrders (2 bytes) */ stream_write_uint8(s, ORDER_STANDARD | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */ stream_write_uint8(s, ORDER_TYPE_SCRBLT); /* orderType (1 byte) */ @@ -436,26 +443,26 @@ static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) stream_write_uint16(s, scrblt->nXSrc); stream_write_uint16(s, scrblt->nYSrc); - fastpath_send_update_pdu(rdp->fastpath, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); } static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system) { STREAM* s; + uint8 updateCode; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); - /* updateHeader (1 byte) */ if (pointer_system->type == SYSPTR_NULL) - stream_write_uint8(s, FASTPATH_UPDATETYPE_PTR_NULL); + updateCode = FASTPATH_UPDATETYPE_PTR_NULL; else - stream_write_uint8(s, FASTPATH_UPDATETYPE_PTR_DEFAULT); - stream_write_uint16(s, 0); /* size (2 bytes) */ - fastpath_send_update_pdu(rdp->fastpath, s); + updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT; + fastpath_send_update_pdu(rdp->fastpath, updateCode, s); } static void update_write_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color) { + stream_check_size(s, 15 + pointer_color->lengthAndMask + pointer_color->lengthXorMask); stream_write_uint16(s, pointer_color->cacheIndex); stream_write_uint16(s, pointer_color->xPos); stream_write_uint16(s, pointer_color->yPos); @@ -472,33 +479,23 @@ static void update_write_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_ static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color) { - uint32 size; STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); - stream_write_uint8(s, FASTPATH_UPDATETYPE_COLOR); /* updateHeader (1 byte) */ - size = 15 + pointer_color->lengthAndMask + pointer_color->lengthXorMask; - stream_write_uint16(s, size); /* size (2 bytes) */ - stream_check_size(s, size); update_write_pointer_color(s, pointer_color); - fastpath_send_update_pdu(rdp->fastpath, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s); } static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new) { - uint32 size; STREAM* s; rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); - stream_write_uint8(s, FASTPATH_UPDATETYPE_POINTER); /* updateHeader (1 byte) */ - size = 17 + pointer_new->colorPtrAttr.lengthAndMask + pointer_new->colorPtrAttr.lengthXorMask; - stream_write_uint16(s, size); /* size (2 bytes) */ - stream_check_size(s, size); stream_write_uint16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ update_write_pointer_color(s, &pointer_new->colorPtrAttr); - fastpath_send_update_pdu(rdp->fastpath, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s); } static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached) @@ -507,10 +504,8 @@ static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDAT rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); - stream_write_uint8(s, FASTPATH_UPDATETYPE_CACHED); /* updateHeader (1 byte) */ - stream_write_uint16(s, 2); /* size (2 bytes) */ stream_write_uint16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */ - fastpath_send_update_pdu(rdp->fastpath, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s); } void update_register_server_callbacks(rdpUpdate* update)