From 347863ffa5d46cbaa1c2577316550237e8a6cc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 3 Jul 2011 15:34:15 -0400 Subject: [PATCH] libfreerdp-core: moving TCP out of transport module --- freerdp-ui/test/freerdp-test | Bin 13344 -> 13402 bytes libfreerdp-core/CMakeLists.txt | 2 + libfreerdp-core/nego.c | 14 +-- libfreerdp-core/nego.h | 19 ++-- libfreerdp-core/tcp.c | 145 ++++++++++++++++++++++++++++++ libfreerdp-core/tcp.h | 52 +++++++++++ libfreerdp-core/transport.c | 155 ++++++++++----------------------- libfreerdp-core/transport.h | 15 +++- 8 files changed, 278 insertions(+), 124 deletions(-) create mode 100644 libfreerdp-core/tcp.c create mode 100644 libfreerdp-core/tcp.h diff --git a/freerdp-ui/test/freerdp-test b/freerdp-ui/test/freerdp-test index 15e10dac6863386478c9e04f3d8d5ea5ef58a6c1..49e46d006570b4ca95ca461774edd7c83c7aadd2 100755 GIT binary patch delta 2352 zcmZ`)eN0nV6u-AEwI7sHgp@Ls7C|itr8+=Ol;=eE+z^ou1AdI6juoS^I^CRG0tPoh zvjlc@b8(57EHRKRku-5r$$*H%{WX_uiC|{x{%V(v;o`DCmf4+i-+jiQp5&f)f4_6? zz2|VOUGuwHV0d8ZNG*2&e$y`lcU>YQplEtZ63BO zZ|!wlIn`7Kw+yuq<0gIv#*A(#HJ0)+Xf?X|CBl4(=&M41B|Lf;nqb_R$yW((t0Z59qcQGdm%cC+$!(Qp%=}-jIBl*_ntkQ@)%^ynD{5^^g0e`%3CV|GGGzlSHkW#8>ozxR zUbnfrrGEXo#=4CS%`No}bsKA5u7|DW59S=*-@0$#f!)!&<{x=b2FW-+fCUKXx=9Xu z+O3QkSr1N5+>so@26i?&X*tL{c4c{4vS1HtXRd-h!eJVhh$T@9wh^Ye6SoDfBaBnA z#Hhfp5T>V>xGeBXgz4lH{Q|EdoI6%-Od?==w-4ta#>L=qu^a|mO^ zEKw_P24NdvMPM6YJK<7+4e)|}aUNZTIx$99u1-wQO~xzH{IIuI?fTuKo=#Z_d+dwT zkK$l<dU8^s{L%ZUNWqMis-ABn}*S`j}CuK4d)~6om=*L(_=m>+O@$vtXN%i#VMsifq z5&Ijlul7t|TkT*henzvGA$OIATqE@jsd%$y$`S7O;!_&5(@fLY-@Y?Ax^~A6XKp7t zvylic8ZRdvmOFAR%hSEA`on^y(CGMtpNszCIPZj8^OcU99xd>Mmv}CNX zDgx0{A@N$FFt>!yKyz*`AB3^Oxu7_AKs+}ayk6B)VpoLQ8u_h}-`Akk`?I62s+KiW z*Rz`HwHQRJFE85cdy~WMycpjHLkj~LdJGnsjF}PsT3F)JL$%0QFG4Us;2N}OYYoaD zS%HK30qcxpXJ8<|!seCXW7xmtm)rE+tiW9qlw0+T5`p%D3TwAbo39%N5b0?y0trO= z0XBhuQH51cbzx{n^hAw76vG!l5{o7lO>jOALrVeOOA6g)2ocob~39kabzmlJW zc7LTcyHE^bVHomPSUZCnnt})Z3)}*Ig>H|22AW0FMyxn=2X4HNvBIq7R=ghNNe9t4 zG8@x3{-n{!>?{JlA~)|won^$-4qFg4!Er>G(DCc$!veWj42FtExC#fC2KZ-iap~Kh zQF*ueoZGR(F~6!1EOzJA$}P*wVMozw!1P|43cHFo@CXbP2Mpdcm@1z3%+BCj@i~i9 z1NTdcvYu7QPJu7r=AR1vr6`9Zq7Zfl%+O}c@Fc_xPuGAyg>M?%54b(^FrPlFa21i2 zzbLdy1=G`ro)pjQQuex-=N+_CIh|cL-zRJEtXSpgs&he(nq7oH7o)y-&YV#>TgVp@ m$F865*CN`Rq&OezL597@4J#zeM)sFUdy z#xe(L1_v-oqLbhc^bfZ*7>9|>fKC!a(8OedF_pjC#1LjM@*`5ux$izSLr(I}y`S&B z=l*{8UThg`87T8b-5RhN9$?@=)kn@cuhgLKz|Rq9yVZaJ^oc%SXQ4rzg+@dto)DLo z9jf1PbI%td>3`l{wO{Wd)mTWuifrZDt>6qlSG@ z27{plPeYYHcnZX}x07fjM0Mq&4NJwmf71`n9aW`@?0?gKAW zs%5dMg1D-$c{Hi?D}BX1dRas|w;w7n>IaC~w$fJ&?oAMNY0P)5Ty=0kbwDVsR_cXN zrUqmNBuMu`0Q7J|N)A=fs`NPCurJSl>A8*DwzWNjOY&mapVynZFaJkT4IpSUZF1yB z)boL@P5>*kQ7~`kuBprx*qsVElcMWbX$W!^$H{wx8s(TKvce{2o^duI`AKFP zF=XSC*D$-7HOVWP-ON$ROR?EKXC^PTKK3XUMDRy76%d9hsR?6zXW-c1Ih+Dcs`R1o$qmAp&c!S+k z8BRy3)69IL-BQo zCW(&=TiSthgSBD^*9C*39e6{>?n^ohm<;m z!{zm^v?3bnALa91<_xYo@cxSVPIGCZn5?LG>S~NS4ilNzR}?3R%tb51*z9_zd4*MC zlIY)iewb)b-6n&niP>X9e1RjC5vO@mF2IS(2C)ERRSn{GOjb2Gi{=`GkK;&Hy)zLr zXcTW$y%)Q)8ipvn74pDbj{nHCVEMpXP-=C+5T$;RmgIu#GIc`~8>>sL1)x*v7g5|8 znqs#CU4NJ)rm0YA5p?4FM1xFtzWNgyYsb8ZSdS;>y(qddT;mUzb5X|(T4@-9u1gIc ztMOZ|y0NupIW<3A6S1T{c)8|EVDiQL1ck~M0<*Q%xGYj4y09_g7pPt^e%Vf9GBSP2 z-Iw!Evd%U30gJql?|xBy_ye^zRr*?f$pVY0Cigh`jakKY0vqJrJdrbJX0GeATpHUg zd%62L=v7fo;e;6=(|t1P;62)WTeTKfQR?i%yK=OjvJao6I{){=osv53WGWf!5-HaM Gaq$mm>DsUW diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 13ea4913b..0d86742b0 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 + tcp.c + tcp.h tpdu.c tpdu.h tpkt.c diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index 968241d05..7e29ef2d3 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -47,23 +47,21 @@ int nego_connect(rdpNego *nego) nego->state = NEGO_STATE_FAIL; } - DEBUG_NEGO("Negotiating protocol security"); - while (nego->state != NEGO_STATE_FINAL) { - nego_send(nego); - DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]); + nego_send(nego); + if (nego->state == NEGO_STATE_FAIL) { nego->state = NEGO_STATE_FINAL; return 0; } - - nego->state = NEGO_STATE_FINAL; } + DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]); + return 1; } @@ -215,6 +213,10 @@ int nego_recv(rdpTransport * transport, STREAM* s, void * extra) break; } } + else + { + nego->state = NEGO_STATE_FINAL; + } return 0; } diff --git a/libfreerdp-core/nego.h b/libfreerdp-core/nego.h index 30483ada5..cf1627a46 100644 --- a/libfreerdp-core/nego.h +++ b/libfreerdp-core/nego.h @@ -38,12 +38,12 @@ typedef enum _NEGO_STATE NEGO_STATE; char NEGO_STATE_STRINGS[6][25] = { - "NEGO_STATE_INITIAL", - "NEGO_STATE_NLA", - "NEGO_STATE_TLS", - "NEGO_STATE_RDP", - "NEGO_STATE_FAIL", - "NEGO_STATE_FINAL" + "NEGO_STATE_INITIAL", + "NEGO_STATE_NLA", + "NEGO_STATE_TLS", + "NEGO_STATE_RDP", + "NEGO_STATE_FAIL", + "NEGO_STATE_FINAL" }; /* RDP Negotiation Messages */ @@ -56,6 +56,13 @@ enum RDP_NEG_MSG TYPE_RDP_NEG_FAILURE = 0x3 }; +char PROTOCOL_SECURITY_STRINGS[3][4] = +{ + "RDP", + "TLS", + "NLA" +}; + struct rdp_nego { int port; diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c new file mode 100644 index 000000000..183464a30 --- /dev/null +++ b/libfreerdp-core/tcp.c @@ -0,0 +1,145 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Transmission Control Protocol (TCP) + * + * Copyright 2011 Vic Lee + * Copyright 2011 Marc-Andre Moreau + * + * 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 +#include + +#include +#include + +#include "tcp.h" + +FRDP_BOOL +tcp_connect(rdpTcp * tcp, const char * hostname, int port) +{ + int status; + int sockfd = -1; + char servname[10]; + struct addrinfo hints = { 0 }; + struct addrinfo * res, * ai; + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + snprintf(servname, sizeof(servname), "%d", port); + status = getaddrinfo(hostname, servname, &hints, &res); + + if (status != 0) + { + printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(status)); + return False; + } + + for (ai = res; ai; ai = ai->ai_next) + { + sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + + if (sockfd < 0) + continue; + + if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 0) + { + printf("connected to %s:%s\n", hostname, servname); + break; + } + + sockfd = -1; + } + freeaddrinfo(res); + + if (sockfd == -1) + { + printf("unable to connect to %s:%s\n", hostname, servname); + return False; + } + + tcp->sockfd = sockfd; + + return True; +} + +FRDP_BOOL +tcp_disconnect(rdpTcp * tcp) +{ + if (tcp->sockfd != -1) + { + close(tcp->sockfd); + tcp->sockfd = -1; + } + + return True; +} + +FRDP_BOOL +tcp_set_blocking_mode(rdpTcp * tcp, FRDP_BOOL blocking) +{ + int flags; + flags = fcntl(tcp->sockfd, F_GETFL); + + if (flags == -1) + { + printf("transport_configure_sockfd: fcntl failed.\n"); + return False; + } + + if (blocking == True) + { + /* blocking */ + fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK)); + } + else + { + /* non-blocking */ + fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK); + } + + return True; +} + +rdpTcp* +tcp_new() +{ + rdpTcp *tcp = (rdpTcp*) xzalloc(sizeof(rdpTcp)); + + if (tcp != NULL) + { + tcp->sockfd = -1; + tcp->connect = tcp_connect; + tcp->disconnect = tcp_disconnect; + tcp->set_blocking_mode = tcp_set_blocking_mode; + } + + return tcp; +} + +void +tcp_free(rdpTcp* tcp) +{ + if (tcp != NULL) + { + xfree(tcp); + } +} diff --git a/libfreerdp-core/tcp.h b/libfreerdp-core/tcp.h new file mode 100644 index 000000000..9033b8b76 --- /dev/null +++ b/libfreerdp-core/tcp.h @@ -0,0 +1,52 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Transmission Control Protocol (TCP) + * + * Copyright 2011 Vic Lee + * Copyright 2011 Marc-Andre Moreau + * + * 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 __TCP_H +#define __TCP_H + +#include +#include + +typedef struct rdp_tcp rdpTcp; +typedef FRDP_BOOL (*TcpConnect) (rdpTcp * tcp, const char * hostname, int port); +typedef FRDP_BOOL (*TcpDisconnect) (rdpTcp * tcp); +typedef FRDP_BOOL (*TcpSetBlockingMode) (rdpTcp * tcp, FRDP_BOOL blocking); + +struct rdp_tcp +{ + int sockfd; + TcpConnect connect; + TcpDisconnect disconnect; + TcpSetBlockingMode set_blocking_mode; +}; + +FRDP_BOOL +tcp_connect(rdpTcp * tcp, const char * hostname, int port); +FRDP_BOOL +tcp_disconnect(rdpTcp * tcp); +FRDP_BOOL +tcp_set_blocking_mode(rdpTcp * tcp, FRDP_BOOL blocking); + +rdpTcp* +tcp_new(); +void +tcp_free(rdpTcp* tcp); + +#endif /* __TCP_H */ diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 817625b15..6f9f8d2dc 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -34,122 +34,16 @@ #define BUFFER_SIZE 16384 -rdpTransport * -transport_new(void) -{ - rdpTransport * transport; - - transport = (rdpTransport *) xmalloc(sizeof(rdpTransport)); - memset(transport, 0, sizeof(rdpTransport)); - - transport->sockfd = -1; - - /* a small 0.1ms delay when transport is blocking. */ - 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); -} - -static FRDP_BOOL -transport_connect_sockfd(rdpTransport * transport, const char * server, int port) -{ - int status; - int sockfd = -1; - char servname[10]; - struct addrinfo hints = { 0 }; - struct addrinfo * res, * ai; - - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - snprintf(servname, sizeof(servname), "%d", port); - status = getaddrinfo(server, servname, &hints, &res); - - if (status != 0) - { - printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(status)); - return False; - } - - for (ai = res; ai; ai = ai->ai_next) - { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - - if (sockfd < 0) - continue; - - if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 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 False; - } - - transport->sockfd = sockfd; - - return True; -} - -static FRDP_BOOL -transport_configure_sockfd(rdpTransport * transport) -{ - int flags; - - flags = fcntl(transport->sockfd, F_GETFL); - - if (flags == -1) - { - printf("transport_configure_sockfd: fcntl failed.\n"); - return False; - } - - fcntl(transport->sockfd, F_SETFL, flags | O_NONBLOCK); - - return True; -} - FRDP_BOOL transport_connect(rdpTransport * transport, const char * server, int port) { - if (transport_connect_sockfd(transport, server, port) != True) - return False; - - if (transport_configure_sockfd(transport) != True) - return False; - - return True; + return transport->tcp->connect(transport->tcp, server, port); } -int +FRDP_BOOL transport_disconnect(rdpTransport * transport) { - if (transport->sockfd != -1) - { - close(transport->sockfd); - transport->sockfd = -1; - } - - return True; + return transport->tcp->disconnect(transport->tcp); } int @@ -183,7 +77,7 @@ transport_send_tcp(rdpTransport * transport, STREAM * stream) while (head < tail) { - bytes = send(transport->sockfd, head, tail - head, MSG_NOSIGNAL); + bytes = send(transport->tcp->sockfd, head, tail - head, MSG_NOSIGNAL); if (bytes < 0) { @@ -226,7 +120,7 @@ transport_recv_tcp(rdpTransport * transport) stream_check_capacity(transport->recv_buffer, BUFFER_SIZE); - bytes = recv(transport->sockfd, transport->recv_buffer->ptr, BUFFER_SIZE, 0); + bytes = recv(transport->tcp->sockfd, transport->recv_buffer->ptr, BUFFER_SIZE, 0); if (bytes == -1) { @@ -296,3 +190,42 @@ transport_check_fds(rdpTransport * transport) return bytes; } + +void +transport_init(rdpTransport * transport) +{ + transport->state = TRANSPORT_STATE_NEGO; +} + +rdpTransport * +transport_new(void) +{ + rdpTransport * transport; + + transport = (rdpTransport *) xzalloc(sizeof(rdpTransport)); + + if (transport != NULL) + { + transport->tcp = tcp_new(); + + /* a small 0.1ms delay when transport is blocking. */ + 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) +{ + if (transport != NULL) + { + stream_free(transport->recv_buffer); + tcp_free(transport->tcp); + xfree(transport); + } +} diff --git a/libfreerdp-core/transport.h b/libfreerdp-core/transport.h index 170a8fc15..76ef5e479 100644 --- a/libfreerdp-core/transport.h +++ b/libfreerdp-core/transport.h @@ -20,16 +20,29 @@ #ifndef __TRANSPORT_H #define __TRANSPORT_H +#include "tcp.h" + #include #include #include +enum _TRANSPORT_STATE +{ + TRANSPORT_STATE_INITIAL, + TRANSPORT_STATE_NEGO, + TRANSPORT_STATE_TLS, + TRANSPORT_STATE_NLA, + TRANSPORT_STATE_FINAL +}; +typedef enum _TRANSPORT_STATE TRANSPORT_STATE; + typedef struct rdp_transport rdpTransport; typedef int (* PacketReceivedCallback) (rdpTransport * transport, STREAM * stream, void* extra); struct rdp_transport { - int sockfd; + TRANSPORT_STATE state; + struct rdp_tcp * tcp; struct crypto_tls * tls; struct timespec ts; STREAM * recv_buffer;