FreeRDP
tcp.c
1 
21 #include <freerdp/config.h>
22 
23 #include "settings.h"
24 
25 #include <time.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 
29 #include <winpr/crt.h>
30 #include <winpr/platform.h>
31 #include <winpr/winsock.h>
32 
33 #include "rdp.h"
34 #include "utils.h"
35 
36 #if !defined(_WIN32)
37 
38 #include <netdb.h>
39 #include <unistd.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <net/if.h>
45 #include <sys/types.h>
46 #include <arpa/inet.h>
47 
48 #ifdef WINPR_HAVE_POLL_H
49 #include <poll.h>
50 #else
51 #include <time.h>
52 #include <sys/select.h>
53 #endif
54 
55 #if defined(__FreeBSD__) || defined(__OpenBSD__)
56 #ifndef SOL_TCP
57 #define SOL_TCP IPPROTO_TCP
58 #endif
59 #endif
60 
61 #ifdef __APPLE__
62 #ifndef SOL_TCP
63 #define SOL_TCP IPPROTO_TCP
64 #endif
65 #ifndef TCP_KEEPIDLE
66 #define TCP_KEEPIDLE TCP_KEEPALIVE
67 #endif
68 #endif
69 
70 #else
71 
72 #include <winpr/windows.h>
73 
74 #include <winpr/crt.h>
75 
76 #define SHUT_RDWR SD_BOTH
77 #define close(_fd) closesocket(_fd)
78 
79 #endif
80 
81 #include <freerdp/log.h>
82 
83 #include <winpr/stream.h>
84 
85 #include "tcp.h"
86 #include "../crypto/opensslcompat.h"
87 
88 #if defined(HAVE_AF_VSOCK_H)
89 #include <ctype.h>
90 #include <linux/vm_sockets.h>
91 #endif
92 
93 #define TAG FREERDP_TAG("core")
94 
95 /* Simple Socket BIO */
96 
97 typedef struct
98 {
99  SOCKET socket;
100  HANDLE hEvent;
101 } WINPR_BIO_SIMPLE_SOCKET;
102 
103 static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
104 static int transport_bio_simple_uninit(BIO* bio);
105 
106 static long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl,
107  long ret)
108 {
109  return 1;
110 }
111 
112 static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
113 {
114  int error = 0;
115  int status = 0;
116  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
117 
118  if (!buf)
119  return 0;
120 
121  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
122  status = _send(ptr->socket, buf, size, 0);
123 
124  if (status <= 0)
125  {
126  error = WSAGetLastError();
127 
128  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
129  (error == WSAEALREADY))
130  {
131  BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
132  }
133  else
134  {
135  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
136  }
137  }
138 
139  return status;
140 }
141 
142 static int transport_bio_simple_read(BIO* bio, char* buf, int size)
143 {
144  int error = 0;
145  int status = 0;
146  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
147 
148  if (!buf)
149  return 0;
150 
151  BIO_clear_flags(bio, BIO_FLAGS_READ);
152  (void)WSAResetEvent(ptr->hEvent);
153  status = _recv(ptr->socket, buf, size, 0);
154 
155  if (status > 0)
156  {
157  return status;
158  }
159 
160  if (status == 0)
161  {
162  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
163  return 0;
164  }
165 
166  error = WSAGetLastError();
167 
168  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
169  (error == WSAEALREADY))
170  {
171  BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
172  }
173  else
174  {
175  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
176  }
177 
178  return -1;
179 }
180 
181 static int transport_bio_simple_puts(BIO* bio, const char* str)
182 {
183  return 1;
184 }
185 
186 static int transport_bio_simple_gets(BIO* bio, char* str, int size)
187 {
188  return 1;
189 }
190 
191 static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
192 {
193  int status = -1;
194  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
195 
196  switch (cmd)
197  {
198  case BIO_C_SET_SOCKET:
199  transport_bio_simple_uninit(bio);
200  transport_bio_simple_init(bio, (SOCKET)arg2, (int)arg1);
201  return 1;
202  case BIO_C_GET_SOCKET:
203  if (!BIO_get_init(bio) || !arg2)
204  return 0;
205 
206  *((SOCKET*)arg2) = ptr->socket;
207  return 1;
208  case BIO_C_GET_EVENT:
209  if (!BIO_get_init(bio) || !arg2)
210  return 0;
211 
212  *((HANDLE*)arg2) = ptr->hEvent;
213  return 1;
214  case BIO_C_SET_NONBLOCK:
215  {
216 #ifndef _WIN32
217  int flags = 0;
218  flags = fcntl((int)ptr->socket, F_GETFL);
219 
220  if (flags == -1)
221  return 0;
222 
223  if (arg1)
224  (void)fcntl((int)ptr->socket, F_SETFL, flags | O_NONBLOCK);
225  else
226  (void)fcntl((int)ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
227 
228 #else
229  /* the internal socket is always non-blocking */
230 #endif
231  return 1;
232  }
233  case BIO_C_WAIT_READ:
234  {
235  int timeout = (int)arg1;
236  int sockfd = (int)ptr->socket;
237 #ifdef WINPR_HAVE_POLL_H
238  struct pollfd pollset;
239  pollset.fd = sockfd;
240  pollset.events = POLLIN;
241  pollset.revents = 0;
242 
243  do
244  {
245  status = poll(&pollset, 1, timeout);
246  } while ((status < 0) && (errno == EINTR));
247 
248 #else
249  fd_set rset = { 0 };
250  struct timeval tv = { 0 };
251  FD_ZERO(&rset);
252  FD_SET(sockfd, &rset);
253 
254  if (timeout)
255  {
256  tv.tv_sec = timeout / 1000;
257  tv.tv_usec = (timeout % 1000) * 1000;
258  }
259 
260  do
261  {
262  status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
263  } while ((status < 0) && (errno == EINTR));
264 
265 #endif
266  /* Convert timeout to error return */
267  if (status == 0)
268  errno = ETIMEDOUT;
269  }
270  break;
271 
272  case BIO_C_WAIT_WRITE:
273  {
274  int timeout = (int)arg1;
275  int sockfd = (int)ptr->socket;
276 #ifdef WINPR_HAVE_POLL_H
277  struct pollfd pollset;
278  pollset.fd = sockfd;
279  pollset.events = POLLOUT;
280  pollset.revents = 0;
281 
282  do
283  {
284  status = poll(&pollset, 1, timeout);
285  } while ((status < 0) && (errno == EINTR));
286 
287 #else
288  fd_set rset = { 0 };
289  struct timeval tv = { 0 };
290  FD_ZERO(&rset);
291  FD_SET(sockfd, &rset);
292 
293  if (timeout)
294  {
295  tv.tv_sec = timeout / 1000;
296  tv.tv_usec = (timeout % 1000) * 1000;
297  }
298 
299  do
300  {
301  status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
302  } while ((status < 0) && (errno == EINTR));
303 
304 #endif
305  /* Convert timeout to error return */
306  if (status == 0)
307  errno = ETIMEDOUT;
308  }
309  break;
310 
311  case BIO_C_SET_FD:
312  if (arg2)
313  {
314  transport_bio_simple_uninit(bio);
315  transport_bio_simple_init(bio, (SOCKET) * ((int*)arg2), (int)arg1);
316  status = 1;
317  }
318 
319  break;
320 
321  case BIO_C_GET_FD:
322  if (BIO_get_init(bio))
323  {
324  if (arg2)
325  *((int*)arg2) = (int)ptr->socket;
326 
327  status = (int)ptr->socket;
328  }
329 
330  break;
331 
332  case BIO_CTRL_GET_CLOSE:
333  status = BIO_get_shutdown(bio);
334  break;
335 
336  case BIO_CTRL_SET_CLOSE:
337  BIO_set_shutdown(bio, (int)arg1);
338  status = 1;
339  break;
340 
341  case BIO_CTRL_FLUSH:
342  case BIO_CTRL_DUP:
343  status = 1;
344  break;
345 
346  default:
347  status = 0;
348  break;
349  }
350 
351  return status;
352 }
353 
354 static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
355 {
356  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
357  ptr->socket = socket;
358  BIO_set_shutdown(bio, shutdown);
359  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
360  BIO_set_init(bio, 1);
361  ptr->hEvent = WSACreateEvent();
362 
363  if (!ptr->hEvent)
364  return 0;
365 
366  /* WSAEventSelect automatically sets the socket in non-blocking mode */
367  if (WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
368  {
369  WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
370  return 0;
371  }
372 
373  return 1;
374 }
375 
376 static int transport_bio_simple_uninit(BIO* bio)
377 {
378  WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
379 
380  if (BIO_get_shutdown(bio))
381  {
382  if (BIO_get_init(bio) && ptr)
383  {
384  _shutdown(ptr->socket, SD_BOTH);
385  closesocket(ptr->socket);
386  ptr->socket = 0;
387  }
388  }
389 
390  if (ptr && ptr->hEvent)
391  {
392  (void)CloseHandle(ptr->hEvent);
393  ptr->hEvent = NULL;
394  }
395 
396  BIO_set_init(bio, 0);
397  BIO_set_flags(bio, 0);
398  return 1;
399 }
400 
401 static int transport_bio_simple_new(BIO* bio)
402 {
403  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
404  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
405  ptr = (WINPR_BIO_SIMPLE_SOCKET*)calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
406 
407  if (!ptr)
408  return 0;
409 
410  BIO_set_data(bio, ptr);
411  return 1;
412 }
413 
414 static int transport_bio_simple_free(BIO* bio)
415 {
416  WINPR_BIO_SIMPLE_SOCKET* ptr = NULL;
417 
418  if (!bio)
419  return 0;
420 
421  transport_bio_simple_uninit(bio);
422  ptr = (WINPR_BIO_SIMPLE_SOCKET*)BIO_get_data(bio);
423 
424  if (ptr)
425  {
426  BIO_set_data(bio, NULL);
427  free(ptr);
428  }
429 
430  return 1;
431 }
432 
433 BIO_METHOD* BIO_s_simple_socket(void)
434 {
435  static BIO_METHOD* bio_methods = NULL;
436 
437  if (bio_methods == NULL)
438  {
439  if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "SimpleSocket")))
440  return NULL;
441 
442  BIO_meth_set_write(bio_methods, transport_bio_simple_write);
443  BIO_meth_set_read(bio_methods, transport_bio_simple_read);
444  BIO_meth_set_puts(bio_methods, transport_bio_simple_puts);
445  BIO_meth_set_gets(bio_methods, transport_bio_simple_gets);
446  BIO_meth_set_ctrl(bio_methods, transport_bio_simple_ctrl);
447  BIO_meth_set_create(bio_methods, transport_bio_simple_new);
448  BIO_meth_set_destroy(bio_methods, transport_bio_simple_free);
449  }
450 
451  return bio_methods;
452 }
453 
454 /* Buffered Socket BIO */
455 
456 typedef struct
457 {
458  BIO* bufferedBio;
459  BOOL readBlocked;
460  BOOL writeBlocked;
461  RingBuffer xmitBuffer;
462 } WINPR_BIO_BUFFERED_SOCKET;
463 
464 static long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi,
465  long argl, long ret)
466 {
467  return 1;
468 }
469 
470 static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
471 {
472  int ret = num;
473  int nchunks = 0;
474  size_t committedBytes = 0;
475  DataChunk chunks[2] = { 0 };
476  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
477  BIO* next_bio = NULL;
478 
479  WINPR_ASSERT(bio);
480  WINPR_ASSERT(ptr);
481 
482  ptr->writeBlocked = FALSE;
483  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
484 
485  /* we directly append extra bytes in the xmit buffer, this could be prevented
486  * but for now it makes the code more simple.
487  */
488  if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*)buf, num))
489  {
490  WLog_ERR(TAG, "an error occurred when writing (num: %d)", num);
491  return -1;
492  }
493 
494  nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
495  next_bio = BIO_next(bio);
496 
497  for (int i = 0; i < nchunks; i++)
498  {
499  while (chunks[i].size)
500  {
501  ERR_clear_error();
502 
503  const size_t wr = MIN(INT32_MAX, chunks[i].size);
504  const int status = BIO_write(next_bio, chunks[i].data, (int)wr);
505 
506  if (status <= 0)
507  {
508  if (!BIO_should_retry(next_bio))
509  {
510  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
511  ret = -1; /* fatal error */
512  goto out;
513  }
514 
515  if (BIO_should_write(next_bio))
516  {
517  BIO_set_flags(bio, BIO_FLAGS_WRITE);
518  ptr->writeBlocked = TRUE;
519  goto out; /* EWOULDBLOCK */
520  }
521  }
522  else
523  {
524  committedBytes += (size_t)status;
525  chunks[i].size -= (size_t)status;
526  chunks[i].data += status;
527  }
528  }
529  }
530 
531 out:
532  ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);
533  return ret;
534 }
535 
536 static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
537 {
538  int status = 0;
539  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
540  BIO* next_bio = BIO_next(bio);
541  ptr->readBlocked = FALSE;
542  BIO_clear_flags(bio, BIO_FLAGS_READ);
543  ERR_clear_error();
544  status = BIO_read(next_bio, buf, size);
545 
546  if (status <= 0)
547  {
548  if (!BIO_should_retry(next_bio))
549  {
550  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
551  goto out;
552  }
553 
554  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
555 
556  if (BIO_should_read(next_bio))
557  {
558  BIO_set_flags(bio, BIO_FLAGS_READ);
559  ptr->readBlocked = TRUE;
560  goto out;
561  }
562  }
563 
564 out:
565  return status;
566 }
567 
568 static int transport_bio_buffered_puts(BIO* bio, const char* str)
569 {
570  return 1;
571 }
572 
573 static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
574 {
575  return 1;
576 }
577 
578 static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
579 {
580  long status = -1;
581  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
582 
583  switch (cmd)
584  {
585  case BIO_CTRL_FLUSH:
586  if (!ringbuffer_used(&ptr->xmitBuffer))
587  status = 1;
588  else
589  status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;
590 
591  break;
592 
593  case BIO_CTRL_WPENDING:
594  status = ringbuffer_used(&ptr->xmitBuffer);
595  break;
596 
597  case BIO_CTRL_PENDING:
598  status = 0;
599  break;
600 
601  case BIO_C_READ_BLOCKED:
602  status = (int)ptr->readBlocked;
603  break;
604 
605  case BIO_C_WRITE_BLOCKED:
606  status = (int)ptr->writeBlocked;
607  break;
608 
609  default:
610  status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
611  break;
612  }
613 
614  return status;
615 }
616 
617 static int transport_bio_buffered_new(BIO* bio)
618 {
619  WINPR_BIO_BUFFERED_SOCKET* ptr = NULL;
620  BIO_set_init(bio, 1);
621  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
622  ptr = (WINPR_BIO_BUFFERED_SOCKET*)calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
623 
624  if (!ptr)
625  return -1;
626 
627  BIO_set_data(bio, (void*)ptr);
628 
629  if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
630  return -1;
631 
632  return 1;
633 }
634 
635 /* Free the buffered BIO.
636  * Do not free other elements in the BIO stack,
637  * let BIO_free_all handle that. */
638 static int transport_bio_buffered_free(BIO* bio)
639 {
640  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
641 
642  if (!ptr)
643  return 0;
644 
645  ringbuffer_destroy(&ptr->xmitBuffer);
646  free(ptr);
647  return 1;
648 }
649 
650 BIO_METHOD* BIO_s_buffered_socket(void)
651 {
652  static BIO_METHOD* bio_methods = NULL;
653 
654  if (bio_methods == NULL)
655  {
656  if (!(bio_methods = BIO_meth_new(BIO_TYPE_BUFFERED, "BufferedSocket")))
657  return NULL;
658 
659  BIO_meth_set_write(bio_methods, transport_bio_buffered_write);
660  BIO_meth_set_read(bio_methods, transport_bio_buffered_read);
661  BIO_meth_set_puts(bio_methods, transport_bio_buffered_puts);
662  BIO_meth_set_gets(bio_methods, transport_bio_buffered_gets);
663  BIO_meth_set_ctrl(bio_methods, transport_bio_buffered_ctrl);
664  BIO_meth_set_create(bio_methods, transport_bio_buffered_new);
665  BIO_meth_set_destroy(bio_methods, transport_bio_buffered_free);
666  }
667 
668  return bio_methods;
669 }
670 
671 char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
672 {
673  char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
674  const struct sockaddr_in6* sockaddr_ipv6 = (const struct sockaddr_in6*)addr;
675  const struct sockaddr_in* sockaddr_ipv4 = (const struct sockaddr_in*)addr;
676 
677  if (addr == NULL)
678  {
679  return NULL;
680  }
681 
682  switch (sockaddr_ipv4->sin_family)
683  {
684  case AF_INET:
685  if (!inet_ntop(sockaddr_ipv4->sin_family, &sockaddr_ipv4->sin_addr, ipAddress,
686  sizeof(ipAddress)))
687  return NULL;
688 
689  break;
690 
691  case AF_INET6:
692  if (!inet_ntop(sockaddr_ipv6->sin6_family, &sockaddr_ipv6->sin6_addr, ipAddress,
693  sizeof(ipAddress)))
694  return NULL;
695 
696  break;
697 
698  case AF_UNIX:
699  (void)sprintf_s(ipAddress, ARRAYSIZE(ipAddress), "127.0.0.1");
700  break;
701 
702  default:
703  return NULL;
704  }
705 
706  if (pIPv6 != NULL)
707  {
708  *pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
709  }
710 
711  return _strdup(ipAddress);
712 }
713 
714 static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
715 {
716  struct sockaddr_storage saddr = { 0 };
717  socklen_t length = sizeof(struct sockaddr_storage);
718 
719  if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
720  {
721  return NULL;
722  }
723 
724  return freerdp_tcp_address_to_string(&saddr, pIPv6);
725 }
726 
727 char* freerdp_tcp_get_peer_address(SOCKET sockfd)
728 {
729  struct sockaddr_storage saddr = { 0 };
730  socklen_t length = sizeof(struct sockaddr_storage);
731 
732  if (getpeername((int)sockfd, (struct sockaddr*)&saddr, &length) != 0)
733  {
734  return NULL;
735  }
736 
737  return freerdp_tcp_address_to_string(&saddr, NULL);
738 }
739 
740 static int freerdp_uds_connect(const char* path)
741 {
742 #ifndef _WIN32
743  int status = 0;
744  int sockfd = 0;
745  struct sockaddr_un addr = { 0 };
746  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
747 
748  if (sockfd == -1)
749  {
750  WLog_ERR(TAG, "socket");
751  return -1;
752  }
753 
754  addr.sun_family = AF_UNIX;
755  strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
756  status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
757 
758  if (status < 0)
759  {
760  WLog_ERR(TAG, "connect");
761  close(sockfd);
762  return -1;
763  }
764 
765  return sockfd;
766 #else /* ifndef _WIN32 */
767  return -1;
768 #endif
769 }
770 
771 struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port, int ai_flags)
772 {
773  char* service = NULL;
774  char port_str[16];
775  int status = 0;
776  struct addrinfo hints = { 0 };
777  struct addrinfo* result = NULL;
778  hints.ai_family = AF_UNSPEC;
779  hints.ai_socktype = SOCK_STREAM;
780  hints.ai_flags = ai_flags;
781 
782  if (port >= 0)
783  {
784  (void)sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
785  service = port_str;
786  }
787 
788  status = getaddrinfo(hostname, service, &hints, &result);
789 
790  if (status)
791  return NULL;
792 
793  return result;
794 }
795 
796 static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char* hostname)
797 {
798  struct addrinfo* result = freerdp_tcp_resolve_host(hostname, -1, 0);
799 
800  if (!result)
801  {
802  freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
803 
804  return FALSE;
805  }
806 
807  freerdp_set_last_error_log(context, 0);
808  freeaddrinfo(result);
809  return TRUE;
810 }
811 
812 static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr,
813  socklen_t addrlen, UINT32 timeout)
814 {
815  BOOL rc = FALSE;
816  HANDLE handles[2];
817  int status = 0;
818  int count = 0;
819  u_long arg = 0;
820  DWORD tout = (timeout > 0) ? timeout : INFINITE;
821 
822  handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
823 
824  if (!handles[count])
825  return FALSE;
826 
827  status = WSAEventSelect(sockfd, handles[count++], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
828 
829  if (status < 0)
830  {
831  WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
832  goto fail;
833  }
834 
835  handles[count++] = utils_get_abort_event(context->rdp);
836  status = _connect(sockfd, addr, addrlen);
837 
838  if (status < 0)
839  {
840  status = WSAGetLastError();
841 
842  switch (status)
843  {
844  case WSAEINPROGRESS:
845  case WSAEWOULDBLOCK:
846  break;
847 
848  default:
849  goto fail;
850  }
851  }
852 
853  status = WaitForMultipleObjects(count, handles, FALSE, tout);
854 
855  if (WAIT_OBJECT_0 != status)
856  goto fail;
857 
858  const SSIZE_T res = recv(sockfd, NULL, 0, 0);
859 
860  if (res == SOCKET_ERROR)
861  {
862  if (WSAGetLastError() == WSAECONNRESET)
863  goto fail;
864  }
865 
866  status = WSAEventSelect(sockfd, handles[0], 0);
867 
868  if (status < 0)
869  {
870  WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
871  goto fail;
872  }
873 
874  if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0)
875  goto fail;
876 
877  rc = TRUE;
878 fail:
879  (void)CloseHandle(handles[0]);
880  return rc;
881 }
882 
883 typedef struct
884 {
885  SOCKET s;
886  struct addrinfo* addr;
887  struct addrinfo* result;
888 } t_peer;
889 
890 static void peer_free(t_peer* peer)
891 {
892  if (peer->s != INVALID_SOCKET)
893  closesocket(peer->s);
894 
895  freeaddrinfo(peer->addr);
896  memset(peer, 0, sizeof(t_peer));
897  peer->s = INVALID_SOCKET;
898 }
899 
900 static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, const UINT32* ports,
901  UINT32 count, UINT16 port, UINT32 timeout)
902 {
903  UINT32 sindex = count;
904  int status = -1;
905  SOCKET sockfd = INVALID_SOCKET;
906  struct addrinfo* addr = NULL;
907  struct addrinfo* result = NULL;
908 
909  HANDLE* events = (HANDLE*)calloc(count + 1, sizeof(HANDLE));
910  t_peer* peers = (t_peer*)calloc(count, sizeof(t_peer));
911 
912  if (!peers || !events || (count < 1))
913  {
914  free(peers);
915  free(events);
916  return -1;
917  }
918 
919  for (UINT32 index = 0; index < count; index++)
920  {
921  int curPort = port;
922 
923  if (ports)
924  curPort = ports[index];
925 
926  result = freerdp_tcp_resolve_host(hostnames[index], curPort, 0);
927 
928  if (!result)
929  continue;
930 
931  addr = result;
932 
933  if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
934  {
935  while ((addr = addr->ai_next))
936  {
937  if (addr->ai_family == AF_INET)
938  break;
939  }
940 
941  if (!addr)
942  addr = result;
943  }
944 
945  peers[index].s = _socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
946 
947  if (peers[index].s == INVALID_SOCKET)
948  {
949  freeaddrinfo(result);
950  continue;
951  }
952 
953  peers[index].addr = addr;
954  peers[index].result = result;
955  }
956 
957  for (UINT32 index = 0; index < count; index++)
958  {
959  sockfd = peers[index].s;
960  addr = peers[index].addr;
961 
962  if ((sockfd == INVALID_SOCKET) || (!addr))
963  continue;
964 
965  /* blocking tcp connect */
966  status = _connect(sockfd, addr->ai_addr, addr->ai_addrlen);
967 
968  if (status >= 0)
969  {
970  /* connection success */
971  sindex = index;
972  break;
973  }
974  }
975 
976  if (sindex < count)
977  {
978  sockfd = peers[sindex].s;
979  peers[sindex].s = INVALID_SOCKET;
980  }
981  else
982  freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED);
983 
984  for (UINT32 index = 0; index < count; index++)
985  peer_free(&peers[index]);
986 
987  free(peers);
988  free(events);
989  return (int)sockfd;
990 }
991 
992 BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int sockfd)
993 {
994  const BOOL keepalive = (freerdp_settings_get_bool(settings, FreeRDP_TcpKeepAlive));
995  UINT32 optval = 0;
996  socklen_t optlen = 0;
997  optval = keepalive ? 1 : 0;
998  optlen = sizeof(optval);
999 
1000  if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, optlen) < 0)
1001  {
1002  WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
1003  }
1004 
1005 #ifndef _WIN32
1006 #ifdef TCP_KEEPIDLE
1007  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveDelay) : 0;
1008  optlen = sizeof(optval);
1009 
1010  if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&optval, optlen) < 0)
1011  {
1012  WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
1013  }
1014 
1015 #endif
1016 #ifndef SOL_TCP
1017  /* "tcp" from /etc/protocols as getprotobyname(3C) */
1018 #define SOL_TCP 6
1019 #endif
1020 #ifdef TCP_KEEPCNT
1021  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveRetries) : 0;
1022  optlen = sizeof(optval);
1023 
1024  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void*)&optval, optlen) < 0)
1025  {
1026  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
1027  }
1028 
1029 #endif
1030 #ifdef TCP_KEEPINTVL
1031  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveInterval) : 0;
1032  optlen = sizeof(optval);
1033 
1034  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void*)&optval, optlen) < 0)
1035  {
1036  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
1037  }
1038 
1039 #endif
1040 #endif
1041 #if defined(__MACOSX__) || defined(__IOS__)
1042  optval = 1;
1043  optlen = sizeof(optval);
1044 
1045  if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&optval, optlen) < 0)
1046  {
1047  WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
1048  }
1049 
1050 #endif
1051 #ifdef TCP_USER_TIMEOUT
1052  optval = freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
1053  optlen = sizeof(optval);
1054 
1055  if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*)&optval, optlen) < 0)
1056  {
1057  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_USER_TIMEOUT");
1058  }
1059 
1060 #endif
1061  return TRUE;
1062 }
1063 
1064 int freerdp_tcp_connect(rdpContext* context, const char* hostname, int port, DWORD timeout)
1065 {
1066  rdpTransport* transport = NULL;
1067  if (!context || !context->rdp)
1068  return -1;
1069  transport = context->rdp->transport;
1070  if (!transport)
1071  return -1;
1072  return transport_tcp_connect(context->rdp->transport, hostname, port, timeout);
1073 }
1074 
1075 static int get_next_addrinfo(rdpContext* context, struct addrinfo* input, struct addrinfo** result,
1076  UINT32 errorCode)
1077 {
1078  WINPR_ASSERT(context);
1079  WINPR_ASSERT(result);
1080 
1081  struct addrinfo* addr = input;
1082  if (!addr)
1083  goto fail;
1084 
1085  if (freerdp_settings_get_bool(context->settings, FreeRDP_PreferIPv6OverIPv4))
1086  {
1087  while (addr && (addr->ai_family != AF_INET6))
1088  addr = addr->ai_next;
1089  if (!addr)
1090  addr = input;
1091  }
1092 
1093  /* We want to force IPvX, abort if not detected */
1094  const UINT32 IPvX = freerdp_settings_get_uint32(context->settings, FreeRDP_ForceIPvX);
1095  switch (IPvX)
1096  {
1097  case 4:
1098  case 6:
1099  {
1100  const int family = (IPvX == 4) ? AF_INET : AF_INET6;
1101  while (addr && (addr->ai_family != family))
1102  addr = addr->ai_next;
1103  if (!addr)
1104  goto fail;
1105  }
1106  break;
1107  default:
1108  break;
1109  }
1110 
1111  if (!addr)
1112  goto fail;
1113 
1114  *result = addr;
1115  return 0;
1116 
1117 fail:
1118  freerdp_set_last_error_if_not(context, errorCode);
1119  freeaddrinfo(input);
1120  return -1;
1121 }
1122 
1123 int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, const char* hostname,
1124  int port, DWORD timeout)
1125 {
1126  int sockfd = 0;
1127  UINT32 optval = 0;
1128  socklen_t optlen = 0;
1129  BOOL ipcSocket = FALSE;
1130  BOOL useExternalDefinedSocket = FALSE;
1131 
1132  if (!hostname)
1133  {
1134  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1135 
1136  return -1;
1137  }
1138 
1139  if (hostname[0] == '/')
1140  ipcSocket = TRUE;
1141 
1142  if (hostname[0] == '|')
1143  useExternalDefinedSocket = TRUE;
1144 
1145  const char* vsock = utils_is_vsock(hostname);
1146  if (ipcSocket)
1147  {
1148  sockfd = freerdp_uds_connect(hostname);
1149 
1150  if (sockfd < 0)
1151  {
1152  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1153 
1154  return -1;
1155  }
1156  }
1157  else if (useExternalDefinedSocket)
1158  sockfd = port;
1159  else if (vsock)
1160  {
1161 #if defined(HAVE_AF_VSOCK_H)
1162  hostname = vsock;
1163  sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
1164  struct sockaddr_vm addr = { 0 };
1165 
1166  addr.svm_family = AF_VSOCK;
1167  addr.svm_port = port;
1168 
1169  errno = 0;
1170  char* ptr = NULL;
1171  unsigned long val = strtoul(hostname, &ptr, 10);
1172  if (errno || (val > UINT32_MAX))
1173  {
1174  char ebuffer[256] = { 0 };
1175  WLog_ERR(TAG, "could not extract port from '%s', value=%ul, error=%s", hostname, val,
1176  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
1177  return -1;
1178  }
1179  addr.svm_cid = val;
1180  if (addr.svm_cid == 2)
1181  {
1182  addr.svm_flags = VMADDR_FLAG_TO_HOST;
1183  }
1184  if ((connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm))) == -1)
1185  {
1186  WLog_ERR(TAG, "failed to connect to %s", hostname);
1187  return -1;
1188  }
1189 #else
1190  WLog_ERR(TAG, "Compiled without AF_VSOCK, '%s' not supported", hostname);
1191  return -1;
1192 #endif
1193  }
1194  else
1195  {
1196  sockfd = -1;
1197 
1198  if (!settings->GatewayEnabled)
1199  {
1200  if (!freerdp_tcp_is_hostname_resolvable(context, hostname) ||
1201  settings->RemoteAssistanceMode)
1202  {
1203  if (settings->TargetNetAddressCount > 0)
1204  {
1205  WINPR_ASSERT(port <= UINT16_MAX);
1206  sockfd = freerdp_tcp_connect_multi(
1207  context, settings->TargetNetAddresses, settings->TargetNetPorts,
1208  settings->TargetNetAddressCount, (UINT16)port, timeout);
1209  }
1210  }
1211  }
1212 
1213  if (sockfd <= 0)
1214  {
1215  char* peerAddress = NULL;
1216  struct addrinfo* addr = NULL;
1217  struct addrinfo* result = NULL;
1218 
1219  result = freerdp_tcp_resolve_host(hostname, port, 0);
1220 
1221  if (!result)
1222  {
1223  freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1224 
1225  return -1;
1226  }
1227  freerdp_set_last_error_log(context, 0);
1228 
1229  /* By default we take the first returned entry.
1230  *
1231  * If PreferIPv6OverIPv4 = TRUE we force to IPv6 if there
1232  * is such an address available, but fall back to first if not found
1233  */
1234  const int rc =
1235  get_next_addrinfo(context, result, &addr, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1236  if (rc < 0)
1237  return rc;
1238 
1239  do
1240  {
1241  sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1242  if (sockfd < 0)
1243  {
1244  const int lrc = get_next_addrinfo(context, addr->ai_next, &addr,
1245  FREERDP_ERROR_CONNECT_FAILED);
1246  if (lrc < 0)
1247  return lrc;
1248  }
1249  } while (sockfd < 0);
1250 
1251  if ((peerAddress = freerdp_tcp_address_to_string(
1252  (const struct sockaddr_storage*)addr->ai_addr, NULL)) != NULL)
1253  {
1254  WLog_DBG(TAG, "connecting to peer %s", peerAddress);
1255  free(peerAddress);
1256  }
1257 
1258  if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr, addr->ai_addrlen,
1259  timeout))
1260  {
1261  freeaddrinfo(result);
1262  close(sockfd);
1263 
1264  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1265 
1266  WLog_ERR(TAG, "failed to connect to %s", hostname);
1267  return -1;
1268  }
1269 
1270  freeaddrinfo(result);
1271  }
1272  }
1273 
1274  if (!vsock)
1275  {
1276  free(settings->ClientAddress);
1277  settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled);
1278 
1279  if (!settings->ClientAddress)
1280  {
1281  if (!useExternalDefinedSocket)
1282  close(sockfd);
1283 
1284  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1285 
1286  WLog_ERR(TAG, "Couldn't get socket ip address");
1287  return -1;
1288  }
1289  }
1290 
1291  optval = 1;
1292  optlen = sizeof(optval);
1293 
1294  if (!ipcSocket && !useExternalDefinedSocket)
1295  {
1296  if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, optlen) < 0)
1297  WLog_ERR(TAG, "unable to set TCP_NODELAY");
1298  }
1299 
1300  /* receive buffer must be a least 32 K */
1301  if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, &optlen) == 0)
1302  {
1303  if (optval < (1024 * 32))
1304  {
1305  optval = 1024 * 32;
1306  optlen = sizeof(optval);
1307 
1308  if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, optlen) < 0)
1309  {
1310  close(sockfd);
1311 
1312  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1313 
1314  WLog_ERR(TAG, "unable to set receive buffer len");
1315  return -1;
1316  }
1317  }
1318  }
1319 
1320  if (!ipcSocket && !useExternalDefinedSocket)
1321  {
1322  if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1323  {
1324  close(sockfd);
1325 
1326  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1327 
1328  WLog_ERR(TAG, "Couldn't set keep alive mode.");
1329  return -1;
1330  }
1331  }
1332 
1333  if (WaitForSingleObject(utils_get_abort_event(context->rdp), 0) == WAIT_OBJECT_0)
1334  {
1335  close(sockfd);
1336  return -1;
1337  }
1338 
1339  return sockfd;
1340 }
1341 
1342 struct rdp_tcp_layer
1343 {
1344  int sockfd;
1345  HANDLE hEvent;
1346 };
1347 typedef struct rdp_tcp_layer rdpTcpLayer;
1348 
1349 static int freerdp_tcp_layer_read(void* userContext, void* data, int bytes)
1350 {
1351  if (!userContext)
1352  return -1;
1353  if (!data || !bytes)
1354  return 0;
1355 
1356  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1357 
1358  int error = 0;
1359  int status = 0;
1360 
1361  (void)WSAResetEvent(tcpLayer->hEvent);
1362  status = _recv(tcpLayer->sockfd, data, bytes, 0);
1363 
1364  if (status > 0)
1365  return status;
1366 
1367  if (status == 0)
1368  return -1; /* socket closed */
1369 
1370  error = WSAGetLastError();
1371 
1372  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1373  (error == WSAEALREADY))
1374  {
1375  status = 0;
1376  }
1377  else
1378  {
1379  status = -1;
1380  }
1381 
1382  return status;
1383 }
1384 
1385 static int freerdp_tcp_layer_write(void* userContext, const void* data, int bytes)
1386 {
1387  if (!userContext)
1388  return -1;
1389  if (!data || !bytes)
1390  return 0;
1391 
1392  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1393 
1394  int error = 0;
1395  int status = 0;
1396 
1397  status = _send(tcpLayer->sockfd, data, bytes, 0);
1398 
1399  if (status <= 0)
1400  {
1401  error = WSAGetLastError();
1402 
1403  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1404  (error == WSAEALREADY))
1405  {
1406  status = 0;
1407  }
1408  else
1409  {
1410  status = -1;
1411  }
1412  }
1413 
1414  return status;
1415 }
1416 
1417 static BOOL freerdp_tcp_layer_close(void* userContext)
1418 {
1419  if (!userContext)
1420  return FALSE;
1421 
1422  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1423 
1424  if (tcpLayer->sockfd >= 0)
1425  closesocket(tcpLayer->sockfd);
1426  if (tcpLayer->hEvent)
1427  (void)CloseHandle(tcpLayer->hEvent);
1428 
1429  return TRUE;
1430 }
1431 
1432 static BOOL freerdp_tcp_layer_wait(void* userContext, BOOL waitWrite, DWORD timeout)
1433 {
1434  if (!userContext)
1435  return FALSE;
1436 
1437  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1438 
1439  int status = -1;
1440  int sockfd = tcpLayer->sockfd;
1441 #ifdef WINPR_HAVE_POLL_H
1442  struct pollfd pollset = { 0 };
1443  pollset.fd = sockfd;
1444  pollset.events = waitWrite ? POLLOUT : POLLIN;
1445 
1446  do
1447  {
1448  status = poll(&pollset, 1, (int)timeout);
1449  } while ((status < 0) && (errno == EINTR));
1450 
1451 #else
1452  fd_set rset = { 0 };
1453  struct timeval tv = { 0 };
1454  FD_ZERO(&rset);
1455  FD_SET(sockfd, &rset);
1456 
1457  if (timeout)
1458  {
1459  tv.tv_sec = timeout / 1000;
1460  tv.tv_usec = (timeout % 1000) * 1000;
1461  }
1462 
1463  do
1464  {
1465  if (waitWrite)
1466  status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
1467  else
1468  status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
1469  } while ((status < 0) && (errno == EINTR));
1470 
1471 #endif
1472 
1473  return status != 0;
1474 }
1475 
1476 static HANDLE freerdp_tcp_layer_get_event(void* userContext)
1477 {
1478  if (!userContext)
1479  return NULL;
1480 
1481  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1482 
1483  return tcpLayer->hEvent;
1484 }
1485 
1486 rdpTransportLayer* freerdp_tcp_connect_layer(rdpContext* context, const char* hostname, int port,
1487  DWORD timeout)
1488 {
1489  WINPR_ASSERT(context);
1490 
1491  const rdpSettings* settings = context->settings;
1492  WINPR_ASSERT(settings);
1493 
1494  rdpTransportLayer* layer = NULL;
1495  rdpTcpLayer* tcpLayer = NULL;
1496 
1497  int sockfd = freerdp_tcp_connect(context, hostname, port, timeout);
1498  if (sockfd < 0)
1499  goto fail;
1500  if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1501  goto fail;
1502 
1503  layer = transport_layer_new(freerdp_get_transport(context), sizeof(rdpTcpLayer));
1504  if (!layer)
1505  goto fail;
1506 
1507  layer->Read = freerdp_tcp_layer_read;
1508  layer->Write = freerdp_tcp_layer_write;
1509  layer->Close = freerdp_tcp_layer_close;
1510  layer->Wait = freerdp_tcp_layer_wait;
1511  layer->GetEvent = freerdp_tcp_layer_get_event;
1512 
1513  tcpLayer = (rdpTcpLayer*)layer->userContext;
1514  WINPR_ASSERT(tcpLayer);
1515 
1516  tcpLayer->sockfd = -1;
1517  tcpLayer->hEvent = WSACreateEvent();
1518  if (!tcpLayer->hEvent)
1519  goto fail;
1520 
1521  /* WSAEventSelect automatically sets the socket in non-blocking mode */
1522  if (WSAEventSelect(sockfd, tcpLayer->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
1523  {
1524  WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
1525  goto fail;
1526  }
1527 
1528  tcpLayer->sockfd = sockfd;
1529 
1530  return layer;
1531 
1532 fail:
1533  if (sockfd >= 0)
1534  closesocket(sockfd);
1535  transport_layer_free(layer);
1536  return NULL;
1537 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
a piece of data in the ring buffer, exactly like a glibc iovec
Definition: ringbuffer.h:44
ring buffer meta data
Definition: ringbuffer.h:33