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

12
rdp.c
View File

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

118
rdp5.c
View File

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