diff options
author | Laxmikant Rashinkar <lk@Ubuntu-12.04-32bit> | 2014-10-11 14:49:46 -0700 |
---|---|---|
committer | Laxmikant Rashinkar <lk@Ubuntu-12.04-32bit> | 2014-10-11 14:49:46 -0700 |
commit | 8c316b46b8d6b1cb3cf32165daf817030aac1a47 (patch) | |
tree | 089c5741cb2a914501e5ab28898a5c71c4c4103b /libxrdp/libxrdp.c | |
parent | 5b6b74577fda4bbcd0a02a585d783c59d68953da (diff) | |
parent | bc7a6b9bc66afe4adf7c232c94e41694319d4155 (diff) | |
download | xrdp-proprietary-8c316b46b8d6b1cb3cf32165daf817030aac1a47.tar.gz xrdp-proprietary-8c316b46b8d6b1cb3cf32165daf817030aac1a47.zip |
Merge branch 'devel'
Diffstat (limited to 'libxrdp/libxrdp.c')
-rw-r--r-- | libxrdp/libxrdp.c | 418 |
1 files changed, 364 insertions, 54 deletions
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 7ab1f914..df755f2b 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -21,6 +21,12 @@ #include "libxrdp.h" #include "xrdp_orders_rail.h" +#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) + /******************************************************************************/ struct xrdp_session *EXPORT_CC libxrdp_init(tbus id, struct trans *trans) @@ -29,6 +35,7 @@ libxrdp_init(tbus id, struct trans *trans) session = (struct xrdp_session *)g_malloc(sizeof(struct xrdp_session), 1); session->id = id; + session->trans = trans; session->rdp = xrdp_rdp_create(session, trans); session->orders = xrdp_orders_create(session, (struct xrdp_rdp *)session->rdp); session->client_info = &(((struct xrdp_rdp *)session->rdp)->client_info); @@ -61,7 +68,103 @@ libxrdp_disconnect(struct xrdp_session *session) int EXPORT_CC libxrdp_process_incomming(struct xrdp_session *session) { - return xrdp_rdp_incoming((struct xrdp_rdp *)session->rdp); + int rv; + + rv = xrdp_rdp_incoming((struct xrdp_rdp *)(session->rdp)); + return rv; +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_get_pdu_bytes(const char *aheader) +{ + int rv; + const tui8 *header; + + rv = -1; + header = (const tui8 *) aheader; + + if (header[0] == 0x03) + { + /* TPKT */ + rv = (header[2] << 8) | header[3]; + } + else if (header[0] == 0x30) + { + /* TSRequest (NLA) */ + if (header[1] & 0x80) + { + if ((header[1] & ~(0x80)) == 1) + { + rv = header[2]; + rv += 3; + } + else if ((header[1] & ~(0x80)) == 2) + { + rv = (header[2] << 8) | header[3]; + rv += 4; + } + else + { + g_writeln("libxrdp_get_pdu_bytes: error TSRequest!"); + return -1; + } + } + else + { + rv = header[1]; + rv += 2; + } + } + else + { + /* Fast-Path */ + if (header[1] & 0x80) + { + rv = ((header[1] & 0x7F) << 8) | header[2]; + } + else + { + rv = header[1]; + } + } + return rv; +} + +/******************************************************************************/ +/* only used durring connection */ +struct stream * APP_CC +libxrdp_force_read(struct trans* trans) +{ + int bytes; + struct stream *s; + + s = trans->in_s; + init_stream(s, 32 * 1024); + + if (trans_force_read(trans, 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + bytes = libxrdp_get_pdu_bytes(s->data); + if (bytes < 1) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + if (bytes > 32 * 1024) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + + if (trans_force_read(trans, bytes - 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + return s; } /******************************************************************************/ @@ -73,9 +176,15 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) int code; int term; int dead_lock_counter; + int do_read; struct xrdp_rdp *rdp; - struct stream *ls; + do_read = s == 0; + if (do_read && session->up_and_running) + { + g_writeln("libxrdp_process_data: error logic"); + return 1; + } if (session->in_process_data != 0) { g_writeln("libxrdp_process_data: error reentry"); @@ -83,14 +192,6 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) } session->in_process_data++; - ls = 0; - if (s == 0) - { - make_stream(ls); - init_stream(ls, 8192 * 4); - s = ls; - } - term = 0; cont = 1; rv = 0; @@ -105,13 +206,36 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (session->is_term()) { term = 1; + break; } } code = 0; + if (do_read) + { + if (s == 0) + { + s = libxrdp_force_read(session->trans); + } + else + { + if ((s->next_packet == 0) || (s->next_packet >= s->end)) + { + s = libxrdp_force_read(session->trans); + } + } + if (s == 0) + { + g_writeln("libxrdp_process_data: libxrdp_force_read failed"); + rv = 1; + break; + } + } + if (xrdp_rdp_recv(rdp, s, &code) != 0) { + g_writeln("libxrdp_process_data: xrdp_rdp_recv failed"); rv = 1; break; } @@ -121,39 +245,33 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) switch (code) { case -1: - xrdp_rdp_send_demand_active(rdp); - - /* send Monitor Layout PDU for multimon */ - if (session->client_info->monitorCount > 0 && - session->client_info->multimon == 1) - { - DEBUG(("sending monitor layout pdu")); - if (xrdp_rdp_send_monitorlayout(rdp) != 0) - { - g_writeln("xrdp_rdp_send_monitorlayout: error"); - } - } - + xrdp_caps_send_demand_active(rdp); session->up_and_running = 0; break; case 0: dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active(rdp, s); + xrdp_caps_process_confirm_active(rdp, s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); cont = 0; term = 1; } - + break; + case 2: /* FASTPATH_INPUT_EVENT */ + if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0) + { + DEBUG(("libxrdp_process_data returned non zero")); + cont = 0; + term = 1; + } break; default: - g_writeln("unknown in libxrdp_process_data"); + g_writeln("unknown in libxrdp_process_data: code= %d", code); dead_lock_counter++; break; } @@ -169,16 +287,10 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (cont) { - cont = (s->next_packet != 0) && - (s->next_packet < s->end); + cont = (s->next_packet != 0) && (s->next_packet < s->end); } } - if (s == ls) - { - free_stream(s); - } - session->in_process_data--; return rv; @@ -198,11 +310,27 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } DEBUG(("libxrdp_send_palette sending palette")); + /* clear orders */ libxrdp_orders_force_send(session); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_palette: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + } + else { + LLOGLN(10, ("libxrdp_send_palette: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + } + + /* TS_UPDATE_PALETTE_DATA */ out_uint16_le(s, RDP_UPDATE_PALETTE); out_uint16_le(s, 0); out_uint16_le(s, 256); /* # of colors */ @@ -217,8 +345,22 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_PALETTE) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_UPDATE); + } free_stream(s); + /* send the orders palette too */ libxrdp_orders_init(session); libxrdp_orders_send_palette(session, palette, 0); @@ -482,20 +624,46 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - if ((session->client_info->pointer_flags & 1) == 0) + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { - out_uint16_le(s, RDP_POINTER_COLOR); - out_uint16_le(s, 0); /* pad */ - data_bytes = 3072; + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + + if ((session->client_info->pointer_flags & 1) == 0) + { + data_bytes = 3072; + } + else + { + data_bytes = ((bpp + 7) / 8) * 32 * 32; + out_uint16_le(s, bpp); + } } - else + else /* slowpath */ { - out_uint16_le(s, RDP_POINTER_POINTER); - out_uint16_le(s, 0); /* pad */ - out_uint16_le(s, bpp); - data_bytes = ((bpp + 7) / 8) * 32 * 32; + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + if ((session->client_info->pointer_flags & 1) == 0) + { + out_uint16_le(s, RDP_POINTER_COLOR); + out_uint16_le(s, 0); /* pad */ + data_bytes = 3072; + } + else + { + out_uint16_le(s, RDP_POINTER_POINTER); + out_uint16_le(s, 0); /* pad */ + out_uint16_le(s, bpp); + data_bytes = ((bpp + 7) / 8) * 32 * 32; + } } + + out_uint16_le(s, cache_idx); /* cache_idx */ out_uint16_le(s, x); out_uint16_le(s, y); @@ -506,7 +674,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, switch (bpp) { - case 15: + //case 15: /* coverity: this is logically dead code */ case 16: p16 = (tui16 *) data; for (i = 0; i < 32; i++) @@ -547,9 +715,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } out_uint8a(s, mask, 128); /* mask */ + out_uint8(s, 0); /* pad */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)(session->rdp), s, - RDP_DATA_PDU_POINTER); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if ((session->client_info->pointer_flags & 1) == 0) + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_COLOR) != 0) + { + free_stream(s); + return 1; + } + } + else + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_POINTER) != 0) + { + free_stream(s); + return 1; + } + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -563,12 +756,41 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx) DEBUG(("libxrdp_set_pointer sending cursor index")); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - out_uint16_le(s, RDP_POINTER_CACHED); - out_uint16_le(s, 0); /* pad */ + + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + return 1; + } + } + else + { + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + out_uint16_le(s, RDP_POINTER_CACHED); + out_uint16_le(s, 0); /* pad */ + } + out_uint16_le(s, cache_idx); /* cache_idx */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_CACHED) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -782,7 +1004,7 @@ libxrdp_reset(struct xrdp_session *session, } /* this should do the resizing */ - if (xrdp_rdp_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) + if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) { return 1; } @@ -1079,3 +1301,91 @@ libxrdp_monitored_desktop(struct xrdp_session *session, orders = (struct xrdp_orders *)(session->orders); return xrdp_orders_send_monitored_desktop(orders, mdo, flags); } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_codec_jpeg_compress(struct xrdp_session *session, + int format, char *inp_data, + int width, int height, + int stride, int x, int y, + int cx, int cy, int quality, + char *out_data, int *io_len) +{ + struct xrdp_orders *orders; + void* jpeg_han; + + orders = (struct xrdp_orders *)(session->orders); + jpeg_han = orders->jpeg_han; + return xrdp_codec_jpeg_compress(jpeg_han, format, inp_data, + width, height, stride, x, y, + cx, cy, quality, out_data, io_len); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_fastpath_send_surface(struct xrdp_session *session, + char* data_pad, int pad_bytes, + int data_bytes, + int destLeft, int destTop, + int destRight, int destBottom, int bpp, + int codecID, int width, int height) +{ + struct stream ls; + struct stream *s; + struct xrdp_rdp *rdp; + int rv; + int sec_bytes; + int rdp_bytes; + int max_bytes; + int cmd_bytes; + + LLOGLN(10, ("libxrdp_fastpath_init:")); + if ((session->client_info->use_fast_path & 1) == 0) + { + return 1; + } + max_bytes = session->client_info->max_fastpath_frag_bytes; + if (max_bytes < 32 * 1024) + { + max_bytes = 32 * 1024; + } + rdp = (struct xrdp_rdp *) (session->rdp); + rdp_bytes = xrdp_rdp_get_fastpath_bytes(rdp); + sec_bytes = xrdp_sec_get_fastpath_bytes(rdp->sec_layer); + cmd_bytes = 10 + 12; + if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes) + { + return 1; + } + if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes) + { + return 1; + } + g_memset(&ls, 0, sizeof(ls)); + s = &ls; + s->data = (data_pad + pad_bytes) - (rdp_bytes + sec_bytes + cmd_bytes); + s->sec_hdr = s->data; + s->rdp_hdr = s->sec_hdr + sec_bytes; + s->end = data_pad + pad_bytes + data_bytes; + s->p = s->data + (rdp_bytes + sec_bytes); + /* TS_SURFCMD_SET_SURF_BITS */ + out_uint16_le(s, 0x0001); /* CMDTYPE_SET_SURFACE_BITS */ + out_uint16_le(s, destLeft); + out_uint16_le(s, destTop); + out_uint16_le(s, destRight); + out_uint16_le(s, destBottom); + /* TS_ BITMAP_DATA_EX */ + out_uint8(s, bpp); + out_uint8(s, 0); + out_uint8(s, 0); + out_uint8(s, codecID); + out_uint16_le(s, width); + out_uint16_le(s, height); + out_uint32_le(s, data_bytes); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ + if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) + { + return 1; + } + return 0; +} |