From fb687f2f9e388edb706a1c5dc4886fb8b2031297 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Mon, 4 Jul 2011 09:07:34 +0800 Subject: [PATCH 1/3] libfreerdp-core/transport: enable receiving more PDU in receiving buffer. --- libfreerdp-core/transport.c | 75 ++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 1f3c60dc4..5dd8f04a8 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -190,43 +190,50 @@ transport_check_fds(rdpTransport * transport) if (bytes <= 0) return bytes; - pos = stream_get_pos(transport->recv_buffer); - - /* Ensure the TPKT header is available. */ - if (pos <= 4) - return 0; - - stream_set_pos(transport->recv_buffer, 0); - length = tpkt_read_header(transport->recv_buffer); - - if (length == 0) + while ((pos = stream_get_pos(transport->recv_buffer)) > 0) { - printf("transport_check_fds: protocol error, not a TPKT header.\n"); - return -1; + /* Ensure the TPKT header is available. */ + if (pos <= 4) + return 0; + + stream_set_pos(transport->recv_buffer, 0); + length = tpkt_read_header(transport->recv_buffer); + + if (length == 0) + { + printf("transport_check_fds: protocol error, not a TPKT header.\n"); + return -1; + } + + if (pos < length) + { + stream_set_pos(transport->recv_buffer, pos); + return 0; /* Packet is not yet completely received. */ + } + + /* + * A complete packet has been received. In case there are trailing data + * for the next packet, we copy it to the new receive buffer. + */ + received = transport->recv_buffer; + transport->recv_buffer = stream_new(BUFFER_SIZE); + + if (pos > length) + { + stream_set_pos(received, length); + stream_check_capacity(transport->recv_buffer, pos - length); + stream_copy(transport->recv_buffer, received, pos - length); + } + + stream_set_pos(received, 0); + bytes = transport->recv_callback(transport, received, transport->recv_extra); + stream_free(received); + + if (bytes < 0) + return bytes; } - if (pos < length) - return 0; /* Packet is not yet completely received. */ - - /* - * A complete packet has been received. In case there are trailing data - * for the next packet, we copy it to the new receive buffer. - */ - received = transport->recv_buffer; - transport->recv_buffer = stream_new(BUFFER_SIZE); - - if (pos > length) - { - stream_set_pos(received, length); - stream_check_capacity(transport->recv_buffer, pos - length); - stream_copy(transport->recv_buffer, received, pos - length); - } - - stream_set_pos(received, 0); - bytes = transport->recv_callback(transport, received, transport->recv_extra); - stream_free(received); - - return bytes; + return 0; } void From 2fe93a9799f0e431fd685d225e4cc51029f4418f Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Mon, 4 Jul 2011 09:24:23 +0800 Subject: [PATCH 2/3] libfreerdp-core/transport: check receiving data during send blocking. When sending is blocking, it's necessary to check if there's any data available for receiving to avoid infinite lock. --- libfreerdp-core/transport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 5dd8f04a8..5e54e656b 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -93,6 +93,7 @@ transport_connect_nla(rdpTransport * transport) static int transport_delay(rdpTransport * transport) { + transport_check_fds(transport); nanosleep(&transport->ts, NULL); return 0; } From 8afa7cf22720e8d5a514473c733a15b965c7f77d Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Mon, 4 Jul 2011 10:11:14 +0800 Subject: [PATCH 3/3] libfreerdp-core/transport: process PDU (if any) only after sending has completed. --- libfreerdp-core/transport.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 5e54e656b..5593cc653 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -90,10 +90,13 @@ transport_connect_nla(rdpTransport * transport) return True; } +static int +transport_recv(rdpTransport * transport); + static int transport_delay(rdpTransport * transport) { - transport_check_fds(transport); + transport_recv(transport); nanosleep(&transport->ts, NULL); return 0; } @@ -140,10 +143,17 @@ transport_send_tcp(rdpTransport * transport, STREAM * stream) int transport_send(rdpTransport * transport, STREAM * stream) { + int r; + if (transport->state == TRANSPORT_STATE_TLS) - return transport_send_tls(transport, stream); + r = transport_send_tls(transport, stream); else - return transport_send_tcp(transport, stream); + r = transport_send_tcp(transport, stream); + + if (r == 0) + r = transport_check_fds(transport); + + return r; } static int @@ -175,6 +185,15 @@ transport_recv_tcp(rdpTransport * transport) return bytes; } +static int +transport_recv(rdpTransport * transport) +{ + if (transport->state == TRANSPORT_STATE_TLS) + return transport_recv_tls(transport); + else + return transport_recv_tcp(transport); +} + int transport_check_fds(rdpTransport * transport) { @@ -183,10 +202,7 @@ transport_check_fds(rdpTransport * transport) uint16 length; STREAM * received; - if (transport->state == TRANSPORT_STATE_TLS) - bytes = transport_recv_tls(transport); - else - bytes = transport_recv_tcp(transport); + bytes = transport_recv(transport); if (bytes <= 0) return bytes;