From ff8821c308be44e20a340a02d84de3359fcdc700 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Fri, 7 Mar 2014 12:45:33 -0800 Subject: [PATCH] libxrdp: fastpath output, orders working --- libxrdp/libxrdp.h | 14 +++++ libxrdp/xrdp_fastpath.c | 20 ++++++- libxrdp/xrdp_orders.c | 124 +++++++++++++++++++++++----------------- libxrdp/xrdp_rdp.c | 68 ++++++++++++++++++++++ libxrdp/xrdp_sec.c | 88 ++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+), 52 deletions(-) diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 7a4342db..da8ebc3f 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -346,6 +346,10 @@ xrdp_sec_delete(struct xrdp_sec* self); int APP_CC xrdp_sec_init(struct xrdp_sec* self, struct stream* s); int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s); +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s); +int APP_CC xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan); @@ -370,6 +374,8 @@ xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s); int APP_CC xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s); int APP_CC +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s); +int APP_CC xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code); int APP_CC xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type); @@ -377,6 +383,9 @@ int APP_CC xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, int data_pdu_type); int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type); +int APP_CC xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self); int APP_CC xrdp_rdp_incoming(struct xrdp_rdp* self); @@ -554,4 +563,9 @@ int APP_CC xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s); int APP_CC xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s); + #endif diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 927f9407..681d5424 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -97,12 +97,27 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) } /*****************************************************************************/ +/* no fragmenation */ int APP_CC -xrdp_fastpath_init(struct xrdp_fastpath *self) +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s) { + init_stream(s, 32 * 1024); return 0; } +/*****************************************************************************/ +/* no fragmenation */ +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) +{ + if (trans_force_write_s(self->trans, s) != 0) + { + return 1; + } + return 0; +} + +#if 0 /*****************************************************************************/ int APP_CC xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode, @@ -165,6 +180,7 @@ xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode, return 0; } +#endif /*****************************************************************************/ int @@ -194,6 +210,7 @@ xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode, return 0; } +#if 0 /*****************************************************************************/ int APP_CC xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, @@ -249,6 +266,7 @@ xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, in_uint16_le(s, size); return xrdp_fastpath_process_update(self, updateCode, size, s); } +#endif /*****************************************************************************/ /* FASTPATH_INPUT_EVENT_SCANCODE */ diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 317e1135..819c3d06 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -64,7 +64,6 @@ xrdp_orders_delete(struct xrdp_orders *self) { return; } - xrdp_jpeg_deinit(self->jpeg_han); free_stream(self->out_s); g_free(self->orders_state.text_data); @@ -81,7 +80,6 @@ xrdp_orders_reset(struct xrdp_orders *self) { return 1; } - g_free(self->orders_state.text_data); g_memset(&(self->orders_state), 0, sizeof(self->orders_state)); self->order_count_ptr = 0; @@ -98,24 +96,33 @@ int APP_CC xrdp_orders_init(struct xrdp_orders *self) { self->order_level++; - if (self->order_level == 1) { self->order_count = 0; - - /* is this big enough */ - if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + LLOGLN(10, ("xrdp_orders_init: fastpath")); + if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + } + else + { + LLOGLN(10, ("xrdp_orders_init: slowpath")); + if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); + out_uint8s(self->out_s, 2); /* pad */ + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + out_uint8s(self->out_s, 2); /* pad */ } - - out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); - out_uint8s(self->out_s, 2); /* pad */ - self->order_count_ptr = self->out_s->p; - out_uint8s(self->out_s, 2); /* number of orders, set later */ - out_uint8s(self->out_s, 2); /* pad */ } - return 0; } @@ -127,11 +134,9 @@ xrdp_orders_send(struct xrdp_orders *self) int rv; rv = 0; - if (self->order_level > 0) { self->order_level--; - if ((self->order_level == 0) && (self->order_count > 0)) { s_mark_end(self->out_s); @@ -139,15 +144,24 @@ xrdp_orders_send(struct xrdp_orders *self) self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; self->order_count = 0; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) + { + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, 0) != 0) + { + rv = 1; + } + } + else { - rv = 1; + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + rv = 1; + } } } } - return rv; } @@ -160,21 +174,29 @@ xrdp_orders_force_send(struct xrdp_orders *self) { return 1; } - if ((self->order_level > 0) && (self->order_count > 0)) { s_mark_end(self->out_s); DEBUG(("xrdp_orders_force_send sending %d orders", self->order_count)); self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, 0) != 0) + { + return 1; + } + } + else + { + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + return 1; + } } } - self->order_count = 0; self->order_level = 0; return 0; @@ -1632,7 +1654,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, int present; char* present_ptr; char* order_flags_ptr; - + if (xrdp_orders_check(self, 80) != 0) { return 1; @@ -1653,9 +1675,9 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, order_flags |= RDP_ORDER_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - + order_flags |= RDP_ORDER_LASTBOUNDS; - + } } } @@ -1699,21 +1721,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, { xrdp_orders_out_bounds(self, rect); } - + if (srcidx != self->orders_state.com_blt_srcidx) { present |= 0x000001; out_uint16_le(self->out_s, srcidx); self->orders_state.com_blt_srcidx = srcidx; } - + if (srcformat != self->orders_state.com_blt_srcformat) { present |= 0x000002; out_uint32_le(self->out_s, srcformat); self->orders_state.com_blt_srcformat = srcformat; } - + if (srcwidth != self->orders_state.com_blt_srcwidth) { present |= 0x000004; @@ -1727,14 +1749,14 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcwidth = srcwidth; } - + if (srcrepeat != self->orders_state.com_blt_srcrepeat) { present |= 0x000008; out_uint8(self->out_s, srcrepeat); self->orders_state.com_blt_srcrepeat = srcrepeat; } - + if (srctransform != 0) { if (srctransform[0] != self->orders_state.com_blt_srctransform[0]) @@ -1768,21 +1790,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, self->orders_state.com_blt_srctransform[0] = 0; } } - + if (mskflags != self->orders_state.com_blt_mskflags) { present |= 0x000040; out_uint8(self->out_s, mskflags); self->orders_state.com_blt_mskflags = mskflags; } - + if (mskidx != self->orders_state.com_blt_mskidx) { present |= 0x000080; out_uint16_le(self->out_s, mskidx); self->orders_state.com_blt_mskidx = mskidx; } - + if (mskformat != self->orders_state.com_blt_mskformat) { present |= 0x000100; @@ -1803,21 +1825,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskwidth = mskwidth; } - + if (mskrepeat != self->orders_state.com_blt_mskrepeat) { present |= 0x000400; out_uint8(self->out_s, mskrepeat); self->orders_state.com_blt_mskrepeat = mskrepeat; } - + if (op != self->orders_state.com_blt_op) { present |= 0x000800; out_uint8(self->out_s, op); self->orders_state.com_blt_op = op; } - + if (srcx != self->orders_state.com_blt_srcx) { present |= 0x001000; @@ -1831,7 +1853,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcx = srcx; } - + if (srcy != self->orders_state.com_blt_srcy) { present |= 0x002000; @@ -1845,7 +1867,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcy = srcy; } - + if (mskx != self->orders_state.com_blt_mskx) { present |= 0x004000; @@ -1859,7 +1881,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskx = mskx; } - + if (msky != self->orders_state.com_blt_msky) { present |= 0x008000; @@ -1873,7 +1895,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_msky = msky; } - + if (dstx != self->orders_state.com_blt_dstx) { present |= 0x010000; @@ -1887,7 +1909,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dstx = dstx; } - + if (dsty != self->orders_state.com_blt_dsty) { present |= 0x020000; @@ -1901,7 +1923,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dsty = dsty; } - + if (width != self->orders_state.com_blt_width) { present |= 0x040000; @@ -1915,7 +1937,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_width = width; } - + if (height != self->orders_state.com_blt_height) { present |= 0x080000; @@ -1936,11 +1958,11 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, out_uint32_le(self->out_s, dstformat); self->orders_state.com_blt_dstformat = dstformat; } - + xrdp_order_pack_small_or_tiny(self, order_flags_ptr, order_flags, - + present_ptr, present, 3); - + return 0; } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 26e5c453..43daa874 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -26,6 +26,12 @@ #include #endif +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + /*****************************************************************************/ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -289,6 +295,7 @@ xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s) s_push_layer(s, rdp_hdr, 18); return 0; } + /*****************************************************************************/ /* returns error */ int APP_CC @@ -498,6 +505,65 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, return 0; } +/*****************************************************************************/ +int APP_CC +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) +{ + if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0) + { + return 1; + } + if (self->client_info.rdp_compression) + { + s_push_layer(s, rdp_hdr, 4); + } + else + { + s_push_layer(s, rdp_hdr, 3); + } + return 0; +} + +/*****************************************************************************/ +/* TODO: compression */ +int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type) +{ + int updateHeader; + int ctype; + int len; + + LLOGLN(10, ("xrdp_rdp_send_fastpath:")); + s_pop_layer(s, rdp_hdr); + len = (int)(s->end - s->p); + if (self->client_info.rdp_compression) + { + /* TODO: finish compression */ + LLOGLN(10, ("xrdp_rdp_send_fastpath: compress")); + updateHeader = data_pdu_type & 15; + updateHeader |= 2 << 6; /* FASTPATH_OUTPUT_COMPRESSION_USED */ + out_uint8(s, updateHeader); + ctype = 0; + out_uint8(s, ctype); + len -= 4; + } + else + { + LLOGLN(10, ("xrdp_rdp_send_fastpath: no compress")); + updateHeader = data_pdu_type & 15; + out_uint8(s, updateHeader); + len -= 3; + } + out_uint16_le(s, len); + if (xrdp_sec_send_fastpath(self->sec_layer, s) != 0) + { + LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); + return 1; + } + return 0; +} + /*****************************************************************************/ int APP_CC xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) @@ -1581,6 +1647,7 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) free_stream(s); return 0; } + /*****************************************************************************/ int APP_CC xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) @@ -1620,6 +1687,7 @@ xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) free_stream(s); return 0; } + /*****************************************************************************/ static int APP_CC xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 626fc91e..9db0594f 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1245,6 +1245,94 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) DEBUG((" out xrdp_sec_send")); return 0; } + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) +{ + if (xrdp_fastpath_init(self->fastpath_layer, s) != 0) + { + return 1; + } + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + s_push_layer(s, sec_hdr, 3 + 4 + 8); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + s_push_layer(s, sec_hdr, 3 + 8); + } + else + { + s_push_layer(s, sec_hdr, 3); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) +{ + int secFlags; + int fpOutputHeader; + int datalen; + int pdulen; + int pad; + + LLOGLN(10, ("xrdp_sec_send_fastpath:")); + s_pop_layer(s, sec_hdr); + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: fips")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 15; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + out_uint16_le(s, 16); /* crypto header size */ + out_uint8(s, 1); /* fips version */ + pad = (8 - (datalen % 8)) & 7; + g_memset(s->end, 0, pad); + s->end += pad; + out_uint8(s, pad); /* fips pad */ + xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: crypt")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 11; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_encrypt(self, s->p + 8, datalen); + } + else + { + LLOGLN(10, ("xrdp_sec_send_fastpath: no crypt")); + pdulen = (int)(s->end - s->p); + LLOGLN(10, ("xrdp_sec_send_fastpath: pdulen %d", pdulen)); + secFlags = 0x0; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + } + if (xrdp_fastpath_send(self->fastpath_layer, s) != 0) + { + return 1; + } + return 0; +} + /*****************************************************************************/ /* http://msdn.microsoft.com/en-us/library/cc240510.aspx 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */