From d18704d74060e41f45e7b772544d375fdf80099c Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sun, 9 Mar 2014 12:11:36 -0700 Subject: [PATCH] libxrdp: work on fastpath fragments --- libxrdp/libxrdp.h | 2 + libxrdp/xrdp_fastpath.c | 195 +++++++--------------------------------- libxrdp/xrdp_orders.c | 13 +-- libxrdp/xrdp_rdp.c | 90 +++++++++++++++---- libxrdp/xrdp_sec.c | 19 +++- 5 files changed, 127 insertions(+), 192 deletions(-) diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index da8ebc3f..39e36d4b 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -346,6 +346,8 @@ 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_get_fastpath_bytes(struct xrdp_sec *self); +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); diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 681d5424..27877ef1 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -117,161 +117,11 @@ xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) return 0; } -#if 0 -/*****************************************************************************/ -int APP_CC -xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode, - struct stream *s) -{ - tui16 len; - tui16 maxLen; - tui32 payloadLeft; - tui8 fragment; - struct stream *s_send; - int compression; - int i; - int i32; - - compression = 0; -// s_send = self->out_s; - maxLen = FASTPATH_MAX_PACKET_SIZE - 6; /* 6 bytes for header */ - payloadLeft = (s->end - s->data); - - for (i = 0; payloadLeft > 0; i++) - { - if (payloadLeft > maxLen) - { - len = maxLen; - } - else - { - len = payloadLeft; - } - - payloadLeft -= len; - - if (payloadLeft == 0) - { - fragment = i ? FASTPATH_FRAGMENT_LAST : FASTPATH_FRAGMENT_SINGLE; - } - else - { - fragment = i ? FASTPATH_FRAGMENT_NEXT : FASTPATH_FRAGMENT_FIRST; - } - - init_stream(s_send, 0); - out_uint8(s_send, 0); /* fOutputHeader */ - i32 = ((len + 6) >> 8) | 0x80; - out_uint8(s_send, i32); /* use 2 bytes for length even length < 128 ??? */ - i32 = (len + 6) & 0xff; - out_uint8(s_send, i32); - i32 = (updateCode & 0x0f) | ((fragment & 0x03) << 4) | - ((compression & 0x03) << 6); - out_uint8(s_send, i32); - out_uint16_le(s_send, len); -// s_copy(s_send, s, len); - s_mark_end(s_send); - -// if (xrdp_tcp_send(self->tcp_layer, s_send) != 0) -// { -// return 1; -// } - } - - return 0; -} -#endif - -/*****************************************************************************/ -int -xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode, - tui32 size, struct stream *s) -{ - switch (updateCode) - { - case FASTPATH_UPDATETYPE_ORDERS: - case FASTPATH_UPDATETYPE_BITMAP: - case FASTPATH_UPDATETYPE_PALETTE: - case FASTPATH_UPDATETYPE_SYNCHRONIZE: - case FASTPATH_UPDATETYPE_SURFCMDS: - case FASTPATH_UPDATETYPE_PTR_NULL: - case FASTPATH_UPDATETYPE_PTR_DEFAULT: - case FASTPATH_UPDATETYPE_PTR_POSITION: - case FASTPATH_UPDATETYPE_COLOR: - case FASTPATH_UPDATETYPE_CACHED: - case FASTPATH_UPDATETYPE_POINTER: - break; - default: - g_writeln("xrdp_fastpath_process_update: unknown updateCode 0x%X", - updateCode); - break; - } - - return 0; -} - -#if 0 -/*****************************************************************************/ -int APP_CC -xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, - tui8 header) -{ - tui8 encryptionFlags; - tui8 numberEvents; - tui8 length2; - tui8 updateHeader; - tui8 updateCode; - tui8 updateFrag; - tui8 updateComp; - tui16 length; - tui32 size; - - encryptionFlags = (header & 0xc0) >> 6; - numberEvents = (header & 0x3c) >> 2; -// xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length); - - if (length & 0x80) - { -// xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length2); - length = (length & 0x7f) << 8 + length2 - 3; - } - else - { - length -= 2; - } - -// xrdp_tcp_recv(self->tcp_layer, s, length); - - if (encryptionFlags != 0) - { - /* TODO decryption ...*/ - } - - /* parse updateHeader */ - in_uint8(s, updateHeader); - updateCode = (updateHeader & 0x0f); - updateFrag = (updateHeader & 0x30) >> 4; - updateComp = (updateHeader & 0xc0) >> 6; - - if (updateFrag && updateComp) - { - /* TODO */ - g_writeln("xrdp_fastpath_process_data: updateFrag=%d, updateComp=%d", - updateFrag, updateComp); - return 1; - } - - in_uint16_le(s, size); - return xrdp_fastpath_process_update(self, updateCode, size, s); -} -#endif - /*****************************************************************************/ /* FASTPATH_INPUT_EVENT_SCANCODE */ int APP_CC -xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, int eventFlags, struct stream *s) +xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) { int flags; int code; @@ -284,9 +134,13 @@ xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, int eventFlags, in_uint8(s, code); /* keyCode (1 byte) */ if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) + { flags |= KBD_FLAG_UP; + } else + { flags |= KBD_FLAG_DOWN; + } if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED)) flags |= KBD_FLAG_EXT; @@ -372,11 +226,14 @@ xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self, /*****************************************************************************/ /* FASTPATH_INPUT_EVENT_SYNC */ int APP_CC -xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self, int eventCode, int eventFlags, struct stream *s) +xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self, int eventCode, + int eventFlags, struct stream *s) { /* - * The eventCode bitfield (3 bits in size) MUST be set to FASTPATH_INPUT_EVENT_SYNC (3). - * The eventFlags bitfield (5 bits in size) contains flags indicating the "on" + * The eventCode bitfield (3 bits in size) MUST be set to + * FASTPATH_INPUT_EVENT_SYNC (3). + * The eventFlags bitfield (5 bits in size) contains flags + * indicating the "on" * status of the keyboard toggle keys. */ if (self->session->callback != 0) @@ -417,7 +274,7 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s) int eventCode; int eventFlags; - // process fastpath input events + /* process fastpath input events */ for (i = 0; i < self->numEvents; i++) { if (!s_check_rem(s, 1)) @@ -429,44 +286,52 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s) eventFlags = (eventHeader & 0x1F); eventCode = (eventHeader >> 5); - //DEBUG(("xrdp_fastpath_process_input_event: eventCode= %d, eventFlags= %d, numEvents= %d", - // eventCode, eventFlags, self->sec_layer->fastpath_layer->numEvents)); - switch (eventCode) { case FASTPATH_INPUT_EVENT_SCANCODE: - if (xrdp_fastpath_process_EVENT_SCANCODE(self, eventFlags, s) != 0) + if (xrdp_fastpath_process_EVENT_SCANCODE(self, + eventFlags, + s) != 0) { return 1; } break; case FASTPATH_INPUT_EVENT_MOUSE: - if (xrdp_fastpath_process_EVENT_MOUSE(self, eventFlags, s) != 0) + if (xrdp_fastpath_process_EVENT_MOUSE(self, + eventFlags, + s) != 0) { return 1; } break; case FASTPATH_INPUT_EVENT_MOUSEX: - if (xrdp_fastpath_process_EVENT_MOUSEX(self, eventFlags, s) != 0) + if (xrdp_fastpath_process_EVENT_MOUSEX(self, + eventFlags, + s) != 0) { return 1; } break; case FASTPATH_INPUT_EVENT_SYNC: - if (xrdp_fastpath_process_EVENT_SYNC(self, eventCode, eventFlags, s) != 0) + if (xrdp_fastpath_process_EVENT_SYNC(self, eventCode, + eventFlags, + s) != 0) { return 1; } break; case FASTPATH_INPUT_EVENT_UNICODE: - if (xrdp_fastpath_process_EVENT_UNICODE(self, eventFlags, s) != 0) + if (xrdp_fastpath_process_EVENT_UNICODE(self, + eventFlags, + s) != 0) { return 1; } break; default: - g_writeln("xrdp_fastpath_process_input_event: unknown eventCode %d", eventCode); + g_writeln("xrdp_fastpath_process_input_event: unknown " + "eventCode %d", eventCode); break; } } diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 819c3d06..fd96e2a4 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -34,6 +34,8 @@ } \ } +#define MAX_ORDERS_SIZE (16 * 1024 + 512) + /*****************************************************************************/ struct xrdp_orders *APP_CC xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) @@ -44,7 +46,7 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) self->session = session; self->rdp_layer = rdp_layer; make_stream(self->out_s); - init_stream(self->out_s, 16384); + init_stream(self->out_s, 32 * 1024); self->orders_state.clip_right = 1; /* silly rdp right clip */ self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */ self->jpeg_han = xrdp_jpeg_init(); @@ -212,14 +214,7 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) int size; int max_packet_size; - if (self->rdp_layer->client_info.bpp == 8) - { - max_packet_size = 8000; - } - else - { - max_packet_size = 16000; - } + max_packet_size = MAX_ORDERS_SIZE; if (self->order_level < 1) { diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 43daa874..86a4f7bf 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -32,6 +32,8 @@ #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) +#define FASTPATH_FRAG_SIZE (16 * 1024 + 1024) + /*****************************************************************************/ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -526,40 +528,94 @@ xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) /*****************************************************************************/ /* TODO: compression */ +/* returns error */ +/* 2.2.9.1.2.1 Fast-Path Update (TS_FP_UPDATE) + * http://msdn.microsoft.com/en-us/library/cc240622.aspx */ int APP_CC xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, int data_pdu_type) { int updateHeader; + int updateCode; + int fragmentation; + int compression; int ctype; int len; + int cont; + int header_bytes; + int sec_bytes; + struct stream ls; + char *holdp; + char *holdend; LLOGLN(10, ("xrdp_rdp_send_fastpath:")); s_pop_layer(s, rdp_hdr); - len = (int)(s->end - s->p); + updateCode = data_pdu_type; 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; + compression = 2; + header_bytes = 4; } else { - LLOGLN(10, ("xrdp_rdp_send_fastpath: no compress")); - updateHeader = data_pdu_type & 15; - out_uint8(s, updateHeader); - len -= 3; + compression = 0; + header_bytes = 3; } - out_uint16_le(s, len); - if (xrdp_sec_send_fastpath(self->sec_layer, s) != 0) + sec_bytes = xrdp_sec_get_fastpath_bytes(self->sec_layer); + fragmentation = 0; + ls = *s; + cont = 1; + while (cont) { - LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); - return 1; + len = (int)(ls.end - ls.p); + if (len > FASTPATH_FRAG_SIZE) + { + len = FASTPATH_FRAG_SIZE; + if (fragmentation == 0) + { + fragmentation = 2; /* FASTPATH_FRAGMENT_FIRST */ + } + else if (fragmentation == 2) + { + fragmentation = 3; /* FASTPATH_FRAGMENT_NEXT */ + } + } + else + { + if (fragmentation != 0) + { + fragmentation = 1; /* FASTPATH_FRAGMENT_LAST */ + } + } + len = MIN(len, 32 * 1024); + LLOGLN(10, ("xrdp_rdp_send_fastpath: len %d fragmentation %d", + len, fragmentation)); + updateHeader = (updateCode & 15) | + ((fragmentation & 3) << 4) | + ((compression & 3) << 6); + out_uint8(&ls, updateHeader); + if (compression != 0) + { + /* TODO: */ + ctype = 0; + out_uint8(&ls, ctype); + } + len -= header_bytes; + out_uint16_le(&ls, len); + holdp = ls.p; + holdend = ls.end; + ls.end = ls.p + len; + if (xrdp_sec_send_fastpath(self->sec_layer, &ls) != 0) + { + LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); + return 1; + } + ls.p = holdp + len; + ls.end = holdend; + cont = ls.p < ls.end; + ls.p -= header_bytes; + ls.sec_hdr = ls.p - sec_bytes; + ls.data = ls.sec_hdr; } return 0; } diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 15c784d8..5e4e8800 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -1246,6 +1246,22 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) return 0; } +/*****************************************************************************/ +/* returns the fastpath sec byte count */ +int APP_CC +xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self) +{ + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + return 3 + 4 + 8; + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + return 3 + 8; + } + return 3; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -1272,6 +1288,8 @@ xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) /*****************************************************************************/ /* returns error */ +/* 2.2.9.1.2 Server Fast-Path Update PDU (TS_FP_UPDATE_PDU) + * http://msdn.microsoft.com/en-us/library/cc240621.aspx */ int APP_CC xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) { @@ -1297,7 +1315,6 @@ xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) out_uint16_be(s, pdulen); out_uint16_le(s, 16); /* crypto header size */ out_uint8(s, 1); /* fips version */ - 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);