2 * FreeRDP: A Remote Desktop Protocol Client
3 * Network Transport Layer
5 * Copyright 2011 Vic Lee
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
24 #include <freerdp/utils/sleep.h>
25 #include <freerdp/utils/stream.h>
26 #include <freerdp/utils/memory.h>
27 #include <freerdp/utils/hexdump.h>
35 #include <sys/socket.h>
41 #include "transport.h"
43 #define BUFFER_SIZE 16384
45 STREAM* transport_recv_stream_init(rdpTransport* transport, int size)
47 STREAM* s = transport->recv_stream;
48 stream_check_size(s, size);
53 STREAM* transport_send_stream_init(rdpTransport* transport, int size)
55 STREAM* s = transport->send_stream;
56 stream_check_size(s, size);
61 boolean transport_connect(rdpTransport* transport, const char* hostname, uint16 port)
63 return tcp_connect(transport->tcp, hostname, port);
66 void transport_attach(rdpTransport* transport, int sockfd)
68 transport->tcp->sockfd = sockfd;
71 boolean transport_disconnect(rdpTransport* transport)
73 if (transport->layer == TRANSPORT_LAYER_TLS)
74 tls_disconnect(transport->tls);
75 return tcp_disconnect(transport->tcp);
78 boolean transport_connect_rdp(rdpTransport* transport)
85 boolean transport_connect_tls(rdpTransport* transport)
87 if (transport->tls == NULL)
88 transport->tls = tls_new(transport->settings);
90 transport->layer = TRANSPORT_LAYER_TLS;
91 transport->tls->sockfd = transport->tcp->sockfd;
93 if (tls_connect(transport->tls) != true)
99 boolean transport_connect_nla(rdpTransport* transport)
101 if (transport->tls == NULL)
102 transport->tls = tls_new(transport->settings);
104 transport->layer = TRANSPORT_LAYER_TLS;
105 transport->tls->sockfd = transport->tcp->sockfd;
107 if (tls_connect(transport->tls) != true)
110 /* Network Level Authentication */
112 if (transport->settings->authentication != true)
115 if (transport->credssp == NULL)
116 transport->credssp = credssp_new(transport);
118 if (credssp_authenticate(transport->credssp) < 0)
120 printf("Authentication failure, check credentials.\n"
121 "If credentials are valid, the NTLMSSP implementation may be to blame.\n");
123 credssp_free(transport->credssp);
127 credssp_free(transport->credssp);
132 boolean transport_accept_rdp(rdpTransport* transport)
139 boolean transport_accept_tls(rdpTransport* transport)
141 if (transport->tls == NULL)
142 transport->tls = tls_new(transport->settings);
144 transport->layer = TRANSPORT_LAYER_TLS;
145 transport->tls->sockfd = transport->tcp->sockfd;
147 if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != true)
153 boolean transport_accept_nla(rdpTransport* transport)
155 if (transport->tls == NULL)
156 transport->tls = tls_new(transport->settings);
158 transport->layer = TRANSPORT_LAYER_TLS;
159 transport->tls->sockfd = transport->tcp->sockfd;
161 if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != true)
164 /* Network Level Authentication */
166 if (transport->settings->authentication != true)
169 /* Blocking here until NLA is complete */
174 int transport_read(rdpTransport* transport, STREAM* s)
180 if (transport->layer == TRANSPORT_LAYER_TLS)
181 status = tls_read(transport->tls, stream_get_tail(s), stream_get_left(s));
182 else if (transport->layer == TRANSPORT_LAYER_TCP)
183 status = tcp_read(transport->tcp, stream_get_tail(s), stream_get_left(s));
185 if (status == 0 && transport->blocking)
187 freerdp_usleep(transport->usleep_interval);
194 #ifdef WITH_DEBUG_TRANSPORT
197 printf("Local < Remote\n");
198 freerdp_hexdump(s->data, status);
205 static int transport_read_nonblocking(rdpTransport* transport)
209 stream_check_size(transport->recv_buffer, 4096);
210 status = transport_read(transport, transport->recv_buffer);
215 stream_seek(transport->recv_buffer, status);
220 int transport_write(rdpTransport* transport, STREAM* s)
225 length = stream_get_length(s);
226 stream_set_pos(s, 0);
228 #ifdef WITH_DEBUG_TRANSPORT
231 printf("Local > Remote\n");
232 freerdp_hexdump(s->data, length);
238 if (transport->layer == TRANSPORT_LAYER_TLS)
239 status = tls_write(transport->tls, stream_get_tail(s), length);
240 else if (transport->layer == TRANSPORT_LAYER_TCP)
241 status = tcp_write(transport->tcp, stream_get_tail(s), length);
244 break; /* error occurred */
248 /* blocking while sending */
249 freerdp_usleep(transport->usleep_interval);
251 /* when sending is blocked in nonblocking mode, the receiving buffer should be checked */
252 if (!transport->blocking)
254 /* and in case we do have buffered some data, we set the event so next loop will get it */
255 if (transport_read_nonblocking(transport) > 0)
256 wait_obj_set(transport->recv_event);
261 stream_seek(s, status);
266 /* A write error indicates that the peer has dropped the connection */
267 transport->layer = TRANSPORT_LAYER_CLOSED;
273 void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
275 rfds[*rcount] = (void*)(long)(transport->tcp->sockfd);
277 wait_obj_get_fds(transport->recv_event, rfds, rcount);
280 int transport_check_fds(rdpTransport* transport)
287 wait_obj_clear(transport->recv_event);
289 status = transport_read_nonblocking(transport);
294 while ((pos = stream_get_pos(transport->recv_buffer)) > 0)
296 stream_set_pos(transport->recv_buffer, 0);
297 if (tpkt_verify_header(transport->recv_buffer)) /* TPKT */
299 /* Ensure the TPKT header is available. */
302 stream_set_pos(transport->recv_buffer, pos);
305 length = tpkt_read_header(transport->recv_buffer);
309 /* Ensure the Fast Path header is available. */
312 stream_set_pos(transport->recv_buffer, pos);
315 /* Fastpath header can be two or three bytes long. */
316 length = fastpath_header_length(transport->recv_buffer);
319 stream_set_pos(transport->recv_buffer, pos);
322 length = fastpath_read_header(NULL, transport->recv_buffer);
327 printf("transport_check_fds: protocol error, not a TPKT or Fast Path header.\n");
328 freerdp_hexdump(stream_get_head(transport->recv_buffer), pos);
334 stream_set_pos(transport->recv_buffer, pos);
335 return 0; /* Packet is not yet completely received. */
339 * A complete packet has been received. In case there are trailing data
340 * for the next packet, we copy it to the new receive buffer.
342 received = transport->recv_buffer;
343 transport->recv_buffer = stream_new(BUFFER_SIZE);
347 stream_set_pos(received, length);
348 stream_check_size(transport->recv_buffer, pos - length);
349 stream_copy(transport->recv_buffer, received, pos - length);
352 stream_set_pos(received, length);
353 stream_seal(received);
354 stream_set_pos(received, 0);
356 if (transport->recv_callback(transport, received, transport->recv_extra) == false)
359 stream_free(received);
368 boolean transport_set_blocking_mode(rdpTransport* transport, boolean blocking)
370 transport->blocking = blocking;
371 return tcp_set_blocking_mode(transport->tcp, blocking);
374 rdpTransport* transport_new(rdpSettings* settings)
376 rdpTransport* transport;
378 transport = (rdpTransport*) xzalloc(sizeof(rdpTransport));
380 if (transport != NULL)
382 transport->tcp = tcp_new(settings);
383 transport->settings = settings;
385 /* a small 0.1ms delay when transport is blocking. */
386 transport->usleep_interval = 100;
388 /* receive buffer for non-blocking read. */
389 transport->recv_buffer = stream_new(BUFFER_SIZE);
390 transport->recv_event = wait_obj_new();
392 /* buffers for blocking read/write */
393 transport->recv_stream = stream_new(BUFFER_SIZE);
394 transport->send_stream = stream_new(BUFFER_SIZE);
396 transport->blocking = true;
398 transport->layer = TRANSPORT_LAYER_TCP;
404 void transport_free(rdpTransport* transport)
406 if (transport != NULL)
408 stream_free(transport->recv_buffer);
409 stream_free(transport->recv_stream);
410 stream_free(transport->send_stream);
411 wait_obj_free(transport->recv_event);
413 tls_free(transport->tls);
414 tcp_free(transport->tcp);