From 3bd924aa566c95154c797ebef88fbef636bf3370 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 09:50:11 +0800 Subject: [PATCH 1/9] libfreerdp-core: add network module prototype. --- libfreerdp-core/CMakeLists.txt | 2 + libfreerdp-core/network.c | 73 ++++++++++++++++++++++++++++++++++ libfreerdp-core/network.h | 50 +++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 libfreerdp-core/network.c create mode 100644 libfreerdp-core/network.h diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 96492be1b..86b164d3a 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -30,6 +30,8 @@ set(LIBFREERDP_CORE_SRCS # credssp.h # ntlmssp.c # ntlmssp.h + network.c + network.h tpdu.c tpdu.h tpkt.c diff --git a/libfreerdp-core/network.c b/libfreerdp-core/network.c new file mode 100644 index 000000000..2a244980b --- /dev/null +++ b/libfreerdp-core/network.c @@ -0,0 +1,73 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Network Transport Layer + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "network.h" + +rdpNetwork * +network_new(void) +{ + rdpNetwork * network; + + network = (rdpNetwork *) xmalloc(sizeof(rdpNetwork)); + memset(network, 0, sizeof(rdpNetwork)); + + return network; +} + +void +network_free(rdpNetwork * network) +{ + xfree(network); +} + +int +network_connect(rdpNetwork * network, const char * server, int port) +{ + return 0; +} + +int +network_disconnect(rdpNetwork * network) +{ + return 0; +} + +int +network_start_tls(rdpNetwork * network) +{ + return 0; +} + +int +network_send(rdpNetwork * network, STREAM * stream) +{ + return 0; +} + +int +network_check_fds(rdpNetwork * network) +{ + return 0; +} diff --git a/libfreerdp-core/network.h b/libfreerdp-core/network.h new file mode 100644 index 000000000..71530668f --- /dev/null +++ b/libfreerdp-core/network.h @@ -0,0 +1,50 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Network Transport Layer + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NETWORK_H +#define __NETWORK_H + +#include + +typedef int (* PacketReceivedCallback) (STREAM * stream); + +struct rdp_network +{ + int sockfd; + struct crypto_tls * tls; + PacketReceivedCallback * recv_callback; +}; +typedef struct rdp_network rdpNetwork; + +rdpNetwork * +network_new(void); +void +network_free(rdpNetwork * network); +int +network_connect(rdpNetwork * network, const char * server, int port); +int +network_disconnect(rdpNetwork * network); +int +network_start_tls(rdpNetwork * network); +int +network_send(rdpNetwork * network, STREAM * stream); +int +network_check_fds(rdpNetwork * network); + +#endif From c65ac150ce52216714b01386eaaf0b047867fbb1 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 10:59:07 +0800 Subject: [PATCH 2/9] libfreerdp-core: rename 'network' module to 'transport' --- libfreerdp-core/CMakeLists.txt | 4 ++-- libfreerdp-core/{network.c => transport.c} | 28 +++++++++++----------- libfreerdp-core/{network.h => transport.h} | 24 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) rename libfreerdp-core/{network.c => transport.c} (62%) rename libfreerdp-core/{network.h => transport.h} (65%) diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 86b164d3a..9f25c5df3 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -30,12 +30,12 @@ set(LIBFREERDP_CORE_SRCS # credssp.h # ntlmssp.c # ntlmssp.h - network.c - network.h tpdu.c tpdu.h tpkt.c tpkt.h + transport.c + transport.h ) add_library(freerdp-core SHARED ${LIBFREERDP_CORE_SRCS}) diff --git a/libfreerdp-core/network.c b/libfreerdp-core/transport.c similarity index 62% rename from libfreerdp-core/network.c rename to libfreerdp-core/transport.c index 2a244980b..1cd116eef 100644 --- a/libfreerdp-core/network.c +++ b/libfreerdp-core/transport.c @@ -23,51 +23,51 @@ #include #include -#include "network.h" +#include "transport.h" -rdpNetwork * -network_new(void) +rdpTransport * +transport_new(void) { - rdpNetwork * network; + rdpTransport * transport; - network = (rdpNetwork *) xmalloc(sizeof(rdpNetwork)); - memset(network, 0, sizeof(rdpNetwork)); + transport = (rdpTransport *) xmalloc(sizeof(rdpTransport)); + memset(transport, 0, sizeof(rdpTransport)); - return network; + return transport; } void -network_free(rdpNetwork * network) +transport_free(rdpTransport * transport) { - xfree(network); + xfree(transport); } int -network_connect(rdpNetwork * network, const char * server, int port) +transport_connect(rdpTransport * transport, const char * server, int port) { return 0; } int -network_disconnect(rdpNetwork * network) +transport_disconnect(rdpTransport * transport) { return 0; } int -network_start_tls(rdpNetwork * network) +transport_start_tls(rdpTransport * transport) { return 0; } int -network_send(rdpNetwork * network, STREAM * stream) +transport_send(rdpTransport * transport, STREAM * stream) { return 0; } int -network_check_fds(rdpNetwork * network) +transport_check_fds(rdpTransport * transport) { return 0; } diff --git a/libfreerdp-core/network.h b/libfreerdp-core/transport.h similarity index 65% rename from libfreerdp-core/network.h rename to libfreerdp-core/transport.h index 71530668f..6fa02cd4d 100644 --- a/libfreerdp-core/network.h +++ b/libfreerdp-core/transport.h @@ -17,34 +17,34 @@ * limitations under the License. */ -#ifndef __NETWORK_H -#define __NETWORK_H +#ifndef __TRANSPORT_H +#define __TRANSPORT_H #include typedef int (* PacketReceivedCallback) (STREAM * stream); -struct rdp_network +struct rdp_transport { int sockfd; struct crypto_tls * tls; PacketReceivedCallback * recv_callback; }; -typedef struct rdp_network rdpNetwork; +typedef struct rdp_transport rdpTransport; -rdpNetwork * -network_new(void); +rdpTransport * +transport_new(void); void -network_free(rdpNetwork * network); +transport_free(rdpTransport * transport); int -network_connect(rdpNetwork * network, const char * server, int port); +transport_connect(rdpTransport * transport, const char * server, int port); int -network_disconnect(rdpNetwork * network); +transport_disconnect(rdpTransport * transport); int -network_start_tls(rdpNetwork * network); +transport_start_tls(rdpTransport * transport); int -network_send(rdpNetwork * network, STREAM * stream); +transport_send(rdpTransport * transport, STREAM * stream); int -network_check_fds(rdpNetwork * network); +transport_check_fds(rdpTransport * transport); #endif From 5c98e983870e071cfb5ef8e87c1be8223ccfc80b Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 15:53:55 +0800 Subject: [PATCH 3/9] libfreerdp-core/transport: add connect and disconnect code. --- libfreerdp-core/transport.c | 85 +++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 1cd116eef..ac1b44601 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -23,6 +23,10 @@ #include #include +#include +#include +#include + #include "transport.h" rdpTransport * @@ -33,6 +37,8 @@ transport_new(void) transport = (rdpTransport *) xmalloc(sizeof(rdpTransport)); memset(transport, 0, sizeof(rdpTransport)); + transport->sockfd = -1; + return transport; } @@ -42,15 +48,94 @@ transport_free(rdpTransport * transport) xfree(transport); } +static int +transport_connect_sockfd(rdpTransport * transport, const char * server, int port) +{ + struct addrinfo hints = { 0 }; + struct addrinfo * res, * ai; + int r; + char servname[10]; + int sockfd = -1; + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + snprintf(servname, sizeof(servname), "%d", port); + r = getaddrinfo(server, servname, &hints, &res); + if (r != 0) + { + printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(r)); + return -1; + } + + for (ai = res; ai; ai = ai->ai_next) + { + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sockfd < 0) + continue; + + r = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + if (r == 0) + { + printf("connected to %s:%s\n", server, servname); + break; + } + + sockfd = -1; + } + freeaddrinfo(res); + + if (sockfd == -1) + { + printf("unable to connect to %s:%s\n", server, servname); + return -1; + } + + transport->sockfd = sockfd; + + return 0; +} + +static int +transport_configure_sockfd(rdpTransport * transport) +{ + int flags; + + flags = fcntl(transport->sockfd, F_GETFL); + if (flags == -1) + { + printf("transport_configure_sockfd: fcntl failed.\n"); + return -1; + } + fcntl(transport->sockfd, F_SETFL, flags | O_NONBLOCK); + + return 0; +} + int transport_connect(rdpTransport * transport, const char * server, int port) { + int r; + + r = transport_connect_sockfd(transport, server, port); + if (r != 0) + return r; + + r = transport_configure_sockfd(transport); + if (r != 0) + return r; + return 0; } int transport_disconnect(rdpTransport * transport) { + if (transport->sockfd != -1) + { + close(transport->sockfd); + transport->sockfd = -1; + } return 0; } From c07694a8759375fc2824c60494499e56b6910f95 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 15:54:32 +0800 Subject: [PATCH 4/9] cunit: add transport unit test. --- cunit/CMakeLists.txt | 4 +++ cunit/test_freerdp.c | 6 ++++ cunit/test_transport.c | 65 ++++++++++++++++++++++++++++++++++++++++++ cunit/test_transport.h | 26 +++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 cunit/test_transport.c create mode 100644 cunit/test_transport.h diff --git a/cunit/CMakeLists.txt b/cunit/CMakeLists.txt index 44d11ba0c..757416e02 100644 --- a/cunit/CMakeLists.txt +++ b/cunit/CMakeLists.txt @@ -21,6 +21,7 @@ include_directories(${CUNIT_INCLUDE_DIRS}) include_directories(.) include_directories(../include) +include_directories(../libfreerdp-core) include_directories(../libfreerdp-gdi) add_executable(test_freerdp @@ -30,11 +31,14 @@ add_executable(test_freerdp test_libgdi.h test_stream.c test_stream.h + test_transport.c + test_transport.h test_freerdp.c test_freerdp.h) target_link_libraries(test_freerdp ${CUNIT_LIBRARIES}) +target_link_libraries(test_freerdp freerdp-core) target_link_libraries(test_freerdp freerdp-gdi) target_link_libraries(test_freerdp freerdp-asn1) target_link_libraries(test_freerdp freerdp-utils) diff --git a/cunit/test_freerdp.c b/cunit/test_freerdp.c index ecc5aa81d..23ba54c3d 100644 --- a/cunit/test_freerdp.c +++ b/cunit/test_freerdp.c @@ -22,6 +22,7 @@ #include "test_color.h" #include "test_libgdi.h" #include "test_stream.h" +#include "test_transport.h" #include "test_freerdp.h" void dump_data(unsigned char * p, int len, int width, char* name) @@ -63,6 +64,7 @@ int main(int argc, char* argv[]) add_color_suite(); add_libgdi_suite(); add_stream_suite(); + add_transport_suite(); } else { @@ -80,6 +82,10 @@ int main(int argc, char* argv[]) { add_stream_suite(); } + else if (strcmp("transport", argv[*pindex]) == 0) + { + add_transport_suite(); + } *pindex = *pindex + 1; } diff --git a/cunit/test_transport.c b/cunit/test_transport.c new file mode 100644 index 000000000..b0473ca5d --- /dev/null +++ b/cunit/test_transport.c @@ -0,0 +1,65 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Transport Unit Tests + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "transport.h" +#include "test_transport.h" + +static const char test_server[] = "192.168.0.1"; + +int init_transport_suite(void) +{ + return 0; +} + +int clean_transport_suite(void) +{ + return 0; +} + +int add_transport_suite(void) +{ + add_test_suite(transport); + + add_test_function(transport); + + return 0; +} + +void test_transport(void) +{ + rdpTransport * transport; + int r; + + transport = transport_new(); + + r = transport_connect(transport, test_server, 3389); + CU_ASSERT(r == 0); + + transport_disconnect(transport); + CU_ASSERT(r == 0); + + transport_free(transport); +} diff --git a/cunit/test_transport.h b/cunit/test_transport.h new file mode 100644 index 000000000..5c5488e0c --- /dev/null +++ b/cunit/test_transport.h @@ -0,0 +1,26 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Transport Unit Tests + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test_freerdp.h" + +int init_transport_suite(void); +int clean_transport_suite(void); +int add_transport_suite(void); + +void test_transport(void); From 28ebc94f1f9fbfb982aca287a11d4b3ad7d10b46 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 16:37:36 +0800 Subject: [PATCH 5/9] libfreerdp-core/transport: implement sending. --- include/freerdp/utils/stream.h | 2 ++ libfreerdp-core/transport.c | 52 +++++++++++++++++++++++++++++++++- libfreerdp-core/transport.h | 1 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/freerdp/utils/stream.h b/include/freerdp/utils/stream.h index 167f9b027..3e636e5aa 100644 --- a/include/freerdp/utils/stream.h +++ b/include/freerdp/utils/stream.h @@ -45,6 +45,8 @@ stream_extend(STREAM * stream); #define stream_get_pos(_s) (_s->ptr - _s->buffer) #define stream_set_pos(_s,_m) _s->ptr = _s->buffer + (_m) #define stream_seek(_s,_offset) _s->ptr += (_offset) +#define stream_get_head(_s) _s->buffer +#define stream_get_tail(_s) _s->ptr #define stream_read_uint8(_s, _v) do { _v = *_s->ptr++; } while (0) #define stream_read_uint16(_s, _v) do { _v = \ diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index ac1b44601..a1e14c6fc 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include #include @@ -39,6 +41,10 @@ transport_new(void) transport->sockfd = -1; + /* a small 0.1ms delay when transport is blocking. */ + transport->ts.tv_sec = 0; + transport->ts.tv_nsec = 100000; + return transport; } @@ -145,10 +151,54 @@ transport_start_tls(rdpTransport * transport) return 0; } +static int +transport_delay(rdpTransport * transport) +{ + nanosleep(&transport->ts, NULL); + return 0; +} + +static int +transport_send_tls(rdpTransport * transport, STREAM * stream) +{ + return 0; +} + +static int +transport_send_tcp(rdpTransport * transport, STREAM * stream) +{ + uint8 * head; + uint8 * tail; + int r; + + head = stream_get_head(stream); + tail = stream_get_tail(stream); + while (head < tail) + { + r = send(transport->sockfd, head, tail - head, MSG_NOSIGNAL); + if (r < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { + if (transport_delay(transport) != 0) + return -1; + continue; + } + printf("transport_send_tcp: send (%d)\n", errno); + return -1; + } + head += r; + } + return 0; +} + int transport_send(rdpTransport * transport, STREAM * stream) { - return 0; + if (transport->tls) + return transport_send_tls(transport, stream); + else + return transport_send_tcp(transport, stream); } int diff --git a/libfreerdp-core/transport.h b/libfreerdp-core/transport.h index 6fa02cd4d..8fe62aef1 100644 --- a/libfreerdp-core/transport.h +++ b/libfreerdp-core/transport.h @@ -29,6 +29,7 @@ struct rdp_transport int sockfd; struct crypto_tls * tls; PacketReceivedCallback * recv_callback; + struct timespec ts; }; typedef struct rdp_transport rdpTransport; From 5036f150e423fd11b088097564d95f5f73bfc730 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 17:07:32 +0800 Subject: [PATCH 6/9] libfreerdp-core/stream: add stream_write_buffer. --- include/freerdp/utils/stream.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/freerdp/utils/stream.h b/include/freerdp/utils/stream.h index 3e636e5aa..9f6c1d372 100644 --- a/include/freerdp/utils/stream.h +++ b/include/freerdp/utils/stream.h @@ -89,6 +89,10 @@ stream_extend(STREAM * stream); *_s->ptr++ = ((_v) >> 40) & 0xFF; \ *_s->ptr++ = ((_v) >> 48) & 0xFF; \ *_s->ptr++ = ((_v) >> 56) & 0xFF; } while (0) +#define stream_write_buffer(_s, _b, _n) do { \ + memcpy(_s->ptr, (_b), (_n)); \ + _s->ptr += (_n); \ + } while (0) #define stream_peek_uint8(_s, _v) do { _v = *_s->ptr; } while (0) #define stream_peek_uint16(_s, _v) do { _v = \ From addc19296541faf5bbbb0c17bdeb2dc599423d0d Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 18:01:37 +0800 Subject: [PATCH 7/9] libfreerdp-core: TPKT length is big-endian. --- include/freerdp/utils/stream.h | 9 +++++++++ libfreerdp-core/tpkt.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/freerdp/utils/stream.h b/include/freerdp/utils/stream.h index 9f6c1d372..ebcced2d3 100644 --- a/include/freerdp/utils/stream.h +++ b/include/freerdp/utils/stream.h @@ -116,5 +116,14 @@ stream_extend(STREAM * stream); (((uint64)(*(_s->ptr + 7))) << 56); \ } while (0) +#define stream_read_uint16_be(_s, _v) do { _v = \ + (((uint16)(*_s->ptr)) << 8) + \ + (uint16)(*(_s->ptr + 1)); \ + _s->ptr += 2; } while (0) + +#define stream_write_uint16_be(_s, _v) do { \ + *_s->ptr++ = ((_v) >> 8) & 0xFF; \ + *_s->ptr++ = (_v) & 0xFF; } while (0) + #endif /* __STREAM_UTILS_H */ diff --git a/libfreerdp-core/tpkt.c b/libfreerdp-core/tpkt.c index ad6bf61fd..0bc5814ff 100644 --- a/libfreerdp-core/tpkt.c +++ b/libfreerdp-core/tpkt.c @@ -64,7 +64,7 @@ tpkt_read_header(STREAM* s) if (version == 3) { stream_seek(s, 2); - stream_read_uint16(s, length); + stream_read_uint16_be(s, length); } else { @@ -80,5 +80,5 @@ tpkt_write_header(STREAM* s, int length) { stream_write_uint8(s, 3); /* version */ stream_write_uint8(s, 8); /* reserved */ - stream_write_uint16(s, length); /* length */ + stream_write_uint16_be(s, length); /* length */ } From 6a3db6363dbd5fa1297b87b7af48a212ebe0bf88 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 18:30:43 +0800 Subject: [PATCH 8/9] libfreerdp-core: implement tcp receiving. --- include/freerdp/utils/stream.h | 6 +++ libfreerdp-core/transport.c | 81 +++++++++++++++++++++++++++++++++- libfreerdp-core/transport.h | 7 ++- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/include/freerdp/utils/stream.h b/include/freerdp/utils/stream.h index ebcced2d3..3c8376661 100644 --- a/include/freerdp/utils/stream.h +++ b/include/freerdp/utils/stream.h @@ -125,5 +125,11 @@ stream_extend(STREAM * stream); *_s->ptr++ = ((_v) >> 8) & 0xFF; \ *_s->ptr++ = (_v) & 0xFF; } while (0) +#define stream_copy(_dst, _src, _n) do { \ + memcpy(_dst->ptr, _src->ptr, _n); \ + _dst->ptr += _n; \ + _src->ptr += _n; \ + } while (0) + #endif /* __STREAM_UTILS_H */ diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index a1e14c6fc..62d9900ad 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -29,8 +29,11 @@ #include #include +#include "tpkt.h" #include "transport.h" +#define BUFFER_SIZE 16384 + rdpTransport * transport_new(void) { @@ -45,12 +48,16 @@ transport_new(void) transport->ts.tv_sec = 0; transport->ts.tv_nsec = 100000; + /* receive buffer for non-blocking read. */ + transport->recv_buffer = stream_new(BUFFER_SIZE); + return transport; } void transport_free(rdpTransport * transport) { + stream_free(transport->recv_buffer); xfree(transport); } @@ -201,8 +208,78 @@ transport_send(rdpTransport * transport, STREAM * stream) return transport_send_tcp(transport, stream); } -int -transport_check_fds(rdpTransport * transport) +static int +transport_recv_tls(rdpTransport * transport) { return 0; } + +static int +transport_recv_tcp(rdpTransport * transport) +{ + int r; + + stream_check_capacity(transport->recv_buffer, BUFFER_SIZE); + + r = recv(transport->sockfd, transport->recv_buffer->ptr, BUFFER_SIZE, 0); + if (r == -1) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + return 0; + printf("transport_recv_tcp: recv failed (%d).\n", errno); + return -1; + } + stream_seek(transport->recv_buffer, r); + + return r; +} + +int +transport_check_fds(rdpTransport * transport) +{ + int r; + int pos; + uint16 len; + STREAM * received; + + if (transport->tls) + r = transport_recv_tls(transport); + else + r = transport_recv_tcp(transport); + + if (r <= 0) + return r; + + 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); + len = tpkt_read_header(transport->recv_buffer); + if (len == 0) + { + printf("transport_check_fds: protocol error, not a TPKT header.\n"); + return -1; + } + if (pos < len) + 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 > len) + { + stream_set_pos(received, len); + stream_check_capacity(transport->recv_buffer, pos - len); + stream_copy(transport->recv_buffer, received, pos - len); + } + + stream_set_pos(received, 0); + r = transport->recv_callback(received, transport->recv_callback_data); + stream_free(received); + + return r; +} diff --git a/libfreerdp-core/transport.h b/libfreerdp-core/transport.h index 8fe62aef1..316f6d912 100644 --- a/libfreerdp-core/transport.h +++ b/libfreerdp-core/transport.h @@ -22,14 +22,17 @@ #include -typedef int (* PacketReceivedCallback) (STREAM * stream); +typedef int (* PacketReceivedCallback) (STREAM * stream, void * callback_data); struct rdp_transport { int sockfd; struct crypto_tls * tls; - PacketReceivedCallback * recv_callback; struct timespec ts; + STREAM * recv_buffer; + + PacketReceivedCallback recv_callback; + void * recv_callback_data; }; typedef struct rdp_transport rdpTransport; From 4bbb71251ba3ae8b74e88333dfb2013033fb8c0d Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 3 Jul 2011 18:35:25 +0800 Subject: [PATCH 9/9] cunit/transport: and send/receive unit tests. --- cunit/test_transport.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/cunit/test_transport.c b/cunit/test_transport.c index b0473ca5d..1d3ec9ed4 100644 --- a/cunit/test_transport.c +++ b/cunit/test_transport.c @@ -24,10 +24,17 @@ #include #include +#include "tpkt.h" #include "transport.h" #include "test_transport.h" static const char test_server[] = "192.168.0.1"; +static const uint8 test_x224_req[] = +{ + "\x03\x00\x00\x2C\x27\xE0\x00\x00\x00\x00\x00\x43\x6F\x6F\x6B\x69" + "\x65\x3A\x20\x6D\x73\x74\x73\x68\x61\x73\x68\x3D\x65\x6C\x74\x6F" + "\x6e\x73\x0D\x0A\x01\x00\x08\x00\x00\x00\x00\x00" +}; int init_transport_suite(void) { @@ -48,17 +55,44 @@ int add_transport_suite(void) return 0; } +static int test_finished = 0; + +static int +packet_received(STREAM * stream, void * callback_data) +{ + uint16 len; + + len = tpkt_read_header(stream); + CU_ASSERT(len == 19); + freerdp_hexdump(stream->buffer, len); + test_finished = 1; +} + void test_transport(void) { rdpTransport * transport; + STREAM * stream; int r; transport = transport_new(); + transport->recv_callback = packet_received; + transport->recv_callback_data = NULL; r = transport_connect(transport, test_server, 3389); CU_ASSERT(r == 0); - transport_disconnect(transport); + stream = stream_new(sizeof(test_x224_req)); + stream_write_buffer(stream, test_x224_req, sizeof(test_x224_req)); + r = transport_send(transport, stream); + CU_ASSERT(r == 0); + + while (!test_finished) + { + transport_check_fds(transport); + sleep(1); + } + + r = transport_disconnect(transport); CU_ASSERT(r == 0); transport_free(transport);