Enable fragmented Fast-Path Updates

Fragmented updates are concatenated into temporary streams (one per
update type) that are processed when receiving an update with the
FASTPATH_FRAGMENT_LAST bit set.
This commit is contained in:
Karl Mikaelsson 2017-10-13 14:35:48 +02:00
parent 8e3ec9e57b
commit 0c7b4117ab
3 changed files with 94 additions and 41 deletions

View File

@ -57,6 +57,8 @@
#define FASTPATH_OUTPUT_COMPRESSION_USED (0x2 << 6)
#define RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE 32767
/* ISO PDU codes */
enum ISO_PDU_CODE
{
@ -378,6 +380,9 @@ enum RDP_INPUT_DEVICE
#define RDP_CAPLEN_BMPCACHE2 0x28
#define BMPCACHE2_FLAG_PERSIST ((uint32)1<<31)
#define RDP_CAPSET_MULTIFRAGMENTUPDATE 26
#define RDP_CAPLEN_MULTIFRAGMENTUPDATE 8
#define RDP_SOURCE "MSTSC"
/* Logon flags */

12
rdp.c
View File

@ -934,6 +934,14 @@ rdp_out_ts_glyphcache_capabilityset(STREAM s)
out_uint16_le(s, 0); /* pad2octets */
}
static void
rdp_out_ts_multifragmentupdate_capabilityset(STREAM s)
{
out_uint16_le(s, RDP_CAPSET_MULTIFRAGMENTUPDATE);
out_uint16_le(s, RDP_CAPLEN_MULTIFRAGMENTUPDATE);
out_uint32_le(s, RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE); /* MaxRequestSize */
}
#define RDP5_FLAG 0x0030
/* Send a confirm active PDU */
static void
@ -954,6 +962,7 @@ rdp_send_confirm_active(void)
RDP_CAPLEN_FONT +
RDP_CAPLEN_SOUND +
RDP_CAPLEN_GLYPHCACHE +
RDP_CAPLEN_MULTIFRAGMENTUPDATE +
4 /* w2k fix, sessionid */ ;
if (g_rdp_version >= RDP_V5)
@ -979,7 +988,7 @@ rdp_send_confirm_active(void)
out_uint16_le(s, caplen);
out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
out_uint16_le(s, 0xe); /* num_caps */
out_uint16_le(s, 15); /* num_caps */
out_uint8s(s, 2); /* pad */
rdp_out_ts_general_capabilityset(s);
@ -1005,6 +1014,7 @@ rdp_send_confirm_active(void)
rdp_out_ts_sound_capabilityset(s);
rdp_out_ts_font_capabilityset(s);
rdp_out_ts_glyphcache_capabilityset(s);
rdp_out_ts_multifragmentupdate_capabilityset(s);
s_mark_end(s);
sec_send(s, sec_flags);

118
rdp5.c
View File

@ -25,10 +25,59 @@ extern uint8 *g_next_packet;
extern RDPCOMP g_mppc_dict;
static void
process_ts_fp_update_by_code(STREAM s, uint8 code)
{
uint16 count, x, y;
switch (code)
{
case FASTPATH_UPDATETYPE_ORDERS:
in_uint16_le(s, count);
process_orders(s, count);
break;
case FASTPATH_UPDATETYPE_BITMAP:
in_uint8s(s, 2); /* part length */
process_bitmap_updates(s);
break;
case FASTPATH_UPDATETYPE_PALETTE:
in_uint8s(s, 2); /* uint16 = 2 */
process_palette(s);
break;
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
break;
case FASTPATH_UPDATETYPE_PTR_NULL:
ui_set_null_cursor();
break;
case FASTPATH_UPDATETYPE_PTR_DEFAULT:
set_system_pointer(SYSPTR_DEFAULT);
break;
case FASTPATH_UPDATETYPE_PTR_POSITION:
in_uint16_le(s, x);
in_uint16_le(s, y);
if (s_check(s))
ui_move_pointer(x, y);
break;
case FASTPATH_UPDATETYPE_COLOR:
process_colour_pointer_pdu(s);
break;
case FASTPATH_UPDATETYPE_CACHED:
process_cached_pointer_pdu(s);
break;
case FASTPATH_UPDATETYPE_POINTER:
process_new_pointer_pdu(s);
break;
default:
logger(Protocol, Warning, "process_ts_fp_updates_by_code(), unhandled opcode %d",
code);
}
}
void
process_ts_fp_updates(STREAM s)
{
uint16 length, count, x, y;
uint16 length;
uint8 hdr, code, frag, comp, ctype = 0;
uint8 *next;
@ -36,6 +85,8 @@ process_ts_fp_updates(STREAM s)
struct stream *ns = &(g_mppc_dict.ns);
struct stream *ts;
static STREAM assembled[0x0F] = { 0 };
ui_begin_update();
while (s->p < s->end)
{
@ -73,46 +124,33 @@ process_ts_fp_updates(STREAM s)
else
ts = s;
switch (code)
if (frag == FASTPATH_FRAGMENT_SINGLE)
{
case FASTPATH_UPDATETYPE_ORDERS:
in_uint16_le(ts, count);
process_orders(ts, count);
break;
case FASTPATH_UPDATETYPE_BITMAP:
in_uint8s(ts, 2); /* part length */
process_bitmap_updates(ts);
break;
case FASTPATH_UPDATETYPE_PALETTE:
in_uint8s(ts, 2); /* uint16 = 2 */
process_palette(ts);
break;
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
break;
case FASTPATH_UPDATETYPE_PTR_NULL:
ui_set_null_cursor();
break;
case FASTPATH_UPDATETYPE_PTR_DEFAULT:
set_system_pointer(SYSPTR_DEFAULT);
break;
case FASTPATH_UPDATETYPE_PTR_POSITION:
in_uint16_le(ts, x);
in_uint16_le(ts, y);
if (s_check(ts))
ui_move_pointer(x, y);
break;
case FASTPATH_UPDATETYPE_COLOR:
process_colour_pointer_pdu(ts);
break;
case FASTPATH_UPDATETYPE_CACHED:
process_cached_pointer_pdu(ts);
break;
case FASTPATH_UPDATETYPE_POINTER:
process_new_pointer_pdu(ts);
break;
default:
logger(Protocol, Warning, "process_ts_fp_updates(), unhandled opcode %d",
code);
process_ts_fp_update_by_code(ts, code);
}
else /* Fragmented packet, we must reassemble */
{
if (assembled[code] == NULL)
{
assembled[code] = xmalloc(sizeof(struct stream));
memset(assembled[code], 0, sizeof(struct stream));
s_realloc(assembled[code], RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE);
s_reset(assembled[code]);
}
if (frag == FASTPATH_FRAGMENT_FIRST)
{
s_reset(assembled[code]);
}
out_uint8p(assembled[code], ts->p, length);
if (frag == FASTPATH_FRAGMENT_LAST)
{
s_mark_end(assembled[code]);
assembled[code]->p = assembled[code]->data;
process_ts_fp_update_by_code(assembled[code], code);
}
}
s->p = next;