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  if (num < 0)
482  return num;
483 
484  ptr->writeBlocked = FALSE;
485  BIO_clear_flags(bio, BIO_FLAGS_WRITE);
486 
487  /* we directly append extra bytes in the xmit buffer, this could be prevented
488  * but for now it makes the code more simple.
489  */
490  if (buf && (num > 0) && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*)buf, (size_t)num))
491  {
492  WLog_ERR(TAG, "an error occurred when writing (num: %d)", num);
493  return -1;
494  }
495 
496  nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
497  next_bio = BIO_next(bio);
498 
499  for (int i = 0; i < nchunks; i++)
500  {
501  while (chunks[i].size)
502  {
503  ERR_clear_error();
504 
505  const size_t wr = MIN(INT32_MAX, chunks[i].size);
506  const int status = BIO_write(next_bio, chunks[i].data, (int)wr);
507 
508  if (status <= 0)
509  {
510  if (!BIO_should_retry(next_bio))
511  {
512  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
513  ret = -1; /* fatal error */
514  goto out;
515  }
516 
517  if (BIO_should_write(next_bio))
518  {
519  BIO_set_flags(bio, BIO_FLAGS_WRITE);
520  ptr->writeBlocked = TRUE;
521  goto out; /* EWOULDBLOCK */
522  }
523  }
524  else
525  {
526  committedBytes += (size_t)status;
527  chunks[i].size -= (size_t)status;
528  chunks[i].data += status;
529  }
530  }
531  }
532 
533 out:
534  ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);
535  return ret;
536 }
537 
538 static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
539 {
540  int status = 0;
541  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
542  BIO* next_bio = BIO_next(bio);
543  ptr->readBlocked = FALSE;
544  BIO_clear_flags(bio, BIO_FLAGS_READ);
545  ERR_clear_error();
546  status = BIO_read(next_bio, buf, size);
547 
548  if (status <= 0)
549  {
550  if (!BIO_should_retry(next_bio))
551  {
552  BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
553  goto out;
554  }
555 
556  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
557 
558  if (BIO_should_read(next_bio))
559  {
560  BIO_set_flags(bio, BIO_FLAGS_READ);
561  ptr->readBlocked = TRUE;
562  goto out;
563  }
564  }
565 
566 out:
567  return status;
568 }
569 
570 static int transport_bio_buffered_puts(BIO* bio, const char* str)
571 {
572  return 1;
573 }
574 
575 static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
576 {
577  return 1;
578 }
579 
580 static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
581 {
582  long status = -1;
583  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
584 
585  switch (cmd)
586  {
587  case BIO_CTRL_FLUSH:
588  if (!ringbuffer_used(&ptr->xmitBuffer))
589  status = 1;
590  else
591  status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;
592 
593  break;
594 
595  case BIO_CTRL_WPENDING:
596  status = WINPR_ASSERTING_INT_CAST(long, ringbuffer_used(&ptr->xmitBuffer));
597  break;
598 
599  case BIO_CTRL_PENDING:
600  status = 0;
601  break;
602 
603  case BIO_C_READ_BLOCKED:
604  status = (int)ptr->readBlocked;
605  break;
606 
607  case BIO_C_WRITE_BLOCKED:
608  status = (int)ptr->writeBlocked;
609  break;
610 
611  default:
612  status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
613  break;
614  }
615 
616  return status;
617 }
618 
619 static int transport_bio_buffered_new(BIO* bio)
620 {
621  WINPR_BIO_BUFFERED_SOCKET* ptr = NULL;
622  BIO_set_init(bio, 1);
623  BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
624  ptr = (WINPR_BIO_BUFFERED_SOCKET*)calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
625 
626  if (!ptr)
627  return -1;
628 
629  BIO_set_data(bio, (void*)ptr);
630 
631  if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
632  return -1;
633 
634  return 1;
635 }
636 
637 /* Free the buffered BIO.
638  * Do not free other elements in the BIO stack,
639  * let BIO_free_all handle that. */
640 static int transport_bio_buffered_free(BIO* bio)
641 {
642  WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*)BIO_get_data(bio);
643 
644  if (!ptr)
645  return 0;
646 
647  ringbuffer_destroy(&ptr->xmitBuffer);
648  free(ptr);
649  return 1;
650 }
651 
652 BIO_METHOD* BIO_s_buffered_socket(void)
653 {
654  static BIO_METHOD* bio_methods = NULL;
655 
656  if (bio_methods == NULL)
657  {
658  if (!(bio_methods = BIO_meth_new(BIO_TYPE_BUFFERED, "BufferedSocket")))
659  return NULL;
660 
661  BIO_meth_set_write(bio_methods, transport_bio_buffered_write);
662  BIO_meth_set_read(bio_methods, transport_bio_buffered_read);
663  BIO_meth_set_puts(bio_methods, transport_bio_buffered_puts);
664  BIO_meth_set_gets(bio_methods, transport_bio_buffered_gets);
665  BIO_meth_set_ctrl(bio_methods, transport_bio_buffered_ctrl);
666  BIO_meth_set_create(bio_methods, transport_bio_buffered_new);
667  BIO_meth_set_destroy(bio_methods, transport_bio_buffered_free);
668  }
669 
670  return bio_methods;
671 }
672 
673 char* freerdp_tcp_address_to_string(const struct sockaddr_storage* addr, BOOL* pIPv6)
674 {
675  char ipAddress[INET6_ADDRSTRLEN + 1] = { 0 };
676  const struct sockaddr_in6* sockaddr_ipv6 = (const struct sockaddr_in6*)addr;
677  const struct sockaddr_in* sockaddr_ipv4 = (const struct sockaddr_in*)addr;
678 
679  if (addr == NULL)
680  {
681  return NULL;
682  }
683 
684  switch (sockaddr_ipv4->sin_family)
685  {
686  case AF_INET:
687  if (!inet_ntop(sockaddr_ipv4->sin_family, &sockaddr_ipv4->sin_addr, ipAddress,
688  sizeof(ipAddress)))
689  return NULL;
690 
691  break;
692 
693  case AF_INET6:
694  if (!inet_ntop(sockaddr_ipv6->sin6_family, &sockaddr_ipv6->sin6_addr, ipAddress,
695  sizeof(ipAddress)))
696  return NULL;
697 
698  break;
699 
700  case AF_UNIX:
701  (void)sprintf_s(ipAddress, ARRAYSIZE(ipAddress), "127.0.0.1");
702  break;
703 
704  default:
705  return NULL;
706  }
707 
708  if (pIPv6 != NULL)
709  {
710  *pIPv6 = (sockaddr_ipv4->sin_family == AF_INET6);
711  }
712 
713  return _strdup(ipAddress);
714 }
715 
716 static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
717 {
718  struct sockaddr_storage saddr = { 0 };
719  socklen_t length = sizeof(struct sockaddr_storage);
720 
721  if (getsockname(sockfd, (struct sockaddr*)&saddr, &length) != 0)
722  {
723  return NULL;
724  }
725 
726  return freerdp_tcp_address_to_string(&saddr, pIPv6);
727 }
728 
729 char* freerdp_tcp_get_peer_address(SOCKET sockfd)
730 {
731  struct sockaddr_storage saddr = { 0 };
732  socklen_t length = sizeof(struct sockaddr_storage);
733 
734  if (getpeername((int)sockfd, (struct sockaddr*)&saddr, &length) != 0)
735  {
736  return NULL;
737  }
738 
739  return freerdp_tcp_address_to_string(&saddr, NULL);
740 }
741 
742 static int freerdp_uds_connect(const char* path)
743 {
744 #ifndef _WIN32
745  int status = 0;
746  int sockfd = 0;
747  struct sockaddr_un addr = { 0 };
748  sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
749 
750  if (sockfd == -1)
751  {
752  WLog_ERR(TAG, "socket");
753  return -1;
754  }
755 
756  addr.sun_family = AF_UNIX;
757  strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
758  status = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
759 
760  if (status < 0)
761  {
762  WLog_ERR(TAG, "connect");
763  close(sockfd);
764  return -1;
765  }
766 
767  return sockfd;
768 #else /* ifndef _WIN32 */
769  return -1;
770 #endif
771 }
772 
773 struct addrinfo* freerdp_tcp_resolve_host(const char* hostname, int port, int ai_flags)
774 {
775  char* service = NULL;
776  char port_str[16];
777  int status = 0;
778  struct addrinfo hints = { 0 };
779  struct addrinfo* result = NULL;
780  hints.ai_family = AF_UNSPEC;
781  hints.ai_socktype = SOCK_STREAM;
782  hints.ai_flags = ai_flags;
783 
784  if (port >= 0)
785  {
786  (void)sprintf_s(port_str, sizeof(port_str) - 1, "%d", port);
787  service = port_str;
788  }
789 
790  status = getaddrinfo(hostname, service, &hints, &result);
791 
792  if (status)
793  return NULL;
794 
795  return result;
796 }
797 
798 static BOOL freerdp_tcp_is_hostname_resolvable(rdpContext* context, const char* hostname)
799 {
800  struct addrinfo* result = freerdp_tcp_resolve_host(hostname, -1, 0);
801 
802  if (!result)
803  {
804  freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
805 
806  return FALSE;
807  }
808 
809  freerdp_set_last_error_log(context, 0);
810  freeaddrinfo(result);
811  return TRUE;
812 }
813 
814 static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd, struct sockaddr* addr,
815  socklen_t addrlen, UINT32 timeout)
816 {
817  BOOL rc = FALSE;
818  HANDLE handles[2] = { 0 };
819  DWORD count = 0;
820  u_long arg = 0;
821  DWORD tout = (timeout > 0) ? timeout : INFINITE;
822 
823  handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
824 
825  if (!handles[count])
826  return FALSE;
827 
828  const int wsastatus = WSAEventSelect((SOCKET)sockfd, handles[count++],
829  FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
830 
831  if (wsastatus < 0)
832  {
833  WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
834  goto fail;
835  }
836 
837  handles[count++] = utils_get_abort_event(context->rdp);
838  const int constatus = _connect((SOCKET)sockfd, addr, WINPR_ASSERTING_INT_CAST(int, addrlen));
839 
840  if (constatus < 0)
841  {
842  const int estatus = WSAGetLastError();
843 
844  switch (estatus)
845  {
846  case WSAEINPROGRESS:
847  case WSAEWOULDBLOCK:
848  break;
849 
850  default:
851  goto fail;
852  }
853  }
854 
855  const DWORD wstatus = WaitForMultipleObjects(count, handles, FALSE, tout);
856 
857  if (WAIT_OBJECT_0 != wstatus)
858  goto fail;
859 
860  const SSIZE_T res = recv(sockfd, NULL, 0, 0);
861 
862  if (res == SOCKET_ERROR)
863  {
864  if (WSAGetLastError() == WSAECONNRESET)
865  goto fail;
866  }
867 
868  const int status = WSAEventSelect((SOCKET)sockfd, handles[0], 0);
869 
870  if (status < 0)
871  {
872  WLog_ERR(TAG, "WSAEventSelect failed with %d", WSAGetLastError());
873  goto fail;
874  }
875 
876  if (_ioctlsocket((SOCKET)sockfd, FIONBIO, &arg) != 0)
877  goto fail;
878 
879  rc = TRUE;
880 fail:
881  (void)CloseHandle(handles[0]);
882  return rc;
883 }
884 
885 typedef struct
886 {
887  SOCKET s;
888  struct addrinfo* addr;
889  struct addrinfo* result;
890 } t_peer;
891 
892 static void peer_free(t_peer* peer)
893 {
894  if (peer->s != INVALID_SOCKET)
895  closesocket(peer->s);
896 
897  freeaddrinfo(peer->addr);
898  memset(peer, 0, sizeof(t_peer));
899  peer->s = INVALID_SOCKET;
900 }
901 
902 static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames, const UINT32* ports,
903  UINT32 count, UINT16 port, UINT32 timeout)
904 {
905  UINT32 sindex = count;
906  SOCKET sockfd = INVALID_SOCKET;
907  struct addrinfo* addr = NULL;
908  struct addrinfo* result = NULL;
909 
910  HANDLE* events = (HANDLE*)calloc(count + 1, sizeof(HANDLE));
911  t_peer* peers = (t_peer*)calloc(count, sizeof(t_peer));
912 
913  if (!peers || !events || (count < 1))
914  {
915  free(peers);
916  free((void*)events);
917  return -1;
918  }
919 
920  for (UINT32 index = 0; index < count; index++)
921  {
922  int curPort = port;
923 
924  if (ports)
925  curPort = WINPR_ASSERTING_INT_CAST(int, ports[index]);
926 
927  result = freerdp_tcp_resolve_host(hostnames[index], curPort, 0);
928 
929  if (!result)
930  continue;
931 
932  addr = result;
933 
934  if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
935  {
936  while ((addr = addr->ai_next))
937  {
938  if (addr->ai_family == AF_INET)
939  break;
940  }
941 
942  if (!addr)
943  addr = result;
944  }
945 
946  peers[index].s = _socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
947 
948  if (peers[index].s == INVALID_SOCKET)
949  {
950  freeaddrinfo(result);
951  continue;
952  }
953 
954  peers[index].addr = addr;
955  peers[index].result = result;
956  }
957 
958  for (UINT32 index = 0; index < count; index++)
959  {
960  sockfd = peers[index].s;
961  addr = peers[index].addr;
962 
963  if ((sockfd == INVALID_SOCKET) || (!addr))
964  continue;
965 
966  /* blocking tcp connect */
967  const int rc =
968  _connect(sockfd, addr->ai_addr, WINPR_ASSERTING_INT_CAST(int, addr->ai_addrlen));
969 
970  if (rc >= 0)
971  {
972  /* connection success */
973  sindex = index;
974  break;
975  }
976  }
977 
978  if (sindex < count)
979  {
980  sockfd = peers[sindex].s;
981  peers[sindex].s = INVALID_SOCKET;
982  }
983  else
984  freerdp_set_last_error_log(context, FREERDP_ERROR_CONNECT_CANCELLED);
985 
986  for (UINT32 index = 0; index < count; index++)
987  peer_free(&peers[index]);
988 
989  free(peers);
990  free((void*)events);
991  return (int)sockfd;
992 }
993 
994 BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int sockfd)
995 {
996  const BOOL keepalive = (freerdp_settings_get_bool(settings, FreeRDP_TcpKeepAlive));
997  UINT32 optval = 0;
998  socklen_t optlen = 0;
999  optval = keepalive ? 1 : 0;
1000  optlen = sizeof(optval);
1001 
1002  if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, optlen) < 0)
1003  {
1004  WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
1005  }
1006 
1007 #ifndef _WIN32
1008 #ifdef TCP_KEEPIDLE
1009  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveDelay) : 0;
1010  optlen = sizeof(optval);
1011 
1012  if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*)&optval, optlen) < 0)
1013  {
1014  WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
1015  }
1016 
1017 #endif
1018 #ifndef SOL_TCP
1019  /* "tcp" from /etc/protocols as getprotobyname(3C) */
1020 #define SOL_TCP 6
1021 #endif
1022 #ifdef TCP_KEEPCNT
1023  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveRetries) : 0;
1024  optlen = sizeof(optval);
1025 
1026  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void*)&optval, optlen) < 0)
1027  {
1028  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
1029  }
1030 
1031 #endif
1032 #ifdef TCP_KEEPINTVL
1033  optval = keepalive ? freerdp_settings_get_uint32(settings, FreeRDP_TcpKeepAliveInterval) : 0;
1034  optlen = sizeof(optval);
1035 
1036  if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void*)&optval, optlen) < 0)
1037  {
1038  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
1039  }
1040 
1041 #endif
1042 #endif
1043 #if defined(__MACOSX__) || defined(__IOS__)
1044  optval = 1;
1045  optlen = sizeof(optval);
1046 
1047  if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&optval, optlen) < 0)
1048  {
1049  WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
1050  }
1051 
1052 #endif
1053 #ifdef TCP_USER_TIMEOUT
1054  optval = freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
1055  optlen = sizeof(optval);
1056 
1057  if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*)&optval, optlen) < 0)
1058  {
1059  WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_USER_TIMEOUT");
1060  }
1061 
1062 #endif
1063  return TRUE;
1064 }
1065 
1066 int freerdp_tcp_connect(rdpContext* context, const char* hostname, int port, DWORD timeout)
1067 {
1068  rdpTransport* transport = NULL;
1069  if (!context || !context->rdp)
1070  return -1;
1071  transport = context->rdp->transport;
1072  if (!transport)
1073  return -1;
1074  return transport_tcp_connect(context->rdp->transport, hostname, port, timeout);
1075 }
1076 
1077 static int get_next_addrinfo(rdpContext* context, struct addrinfo* input, struct addrinfo** result,
1078  UINT32 errorCode)
1079 {
1080  WINPR_ASSERT(context);
1081  WINPR_ASSERT(result);
1082 
1083  struct addrinfo* addr = input;
1084  if (!addr)
1085  goto fail;
1086 
1087  if (freerdp_settings_get_bool(context->settings, FreeRDP_PreferIPv6OverIPv4))
1088  {
1089  while (addr && (addr->ai_family != AF_INET6))
1090  addr = addr->ai_next;
1091  if (!addr)
1092  addr = input;
1093  }
1094 
1095  /* We want to force IPvX, abort if not detected */
1096  const UINT32 IPvX = freerdp_settings_get_uint32(context->settings, FreeRDP_ForceIPvX);
1097  switch (IPvX)
1098  {
1099  case 4:
1100  case 6:
1101  {
1102  const int family = (IPvX == 4) ? AF_INET : AF_INET6;
1103  while (addr && (addr->ai_family != family))
1104  addr = addr->ai_next;
1105  if (!addr)
1106  goto fail;
1107  }
1108  break;
1109  default:
1110  break;
1111  }
1112 
1113  if (!addr)
1114  goto fail;
1115 
1116  *result = addr;
1117  return 0;
1118 
1119 fail:
1120  freerdp_set_last_error_if_not(context, errorCode);
1121  freeaddrinfo(input);
1122  return -1;
1123 }
1124 
1125 int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, const char* hostname,
1126  int port, DWORD timeout)
1127 {
1128  int sockfd = 0;
1129  UINT32 optval = 0;
1130  socklen_t optlen = 0;
1131  BOOL ipcSocket = FALSE;
1132  BOOL useExternalDefinedSocket = FALSE;
1133 
1134  if (!hostname)
1135  {
1136  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1137 
1138  return -1;
1139  }
1140 
1141  if (hostname[0] == '/')
1142  ipcSocket = TRUE;
1143 
1144  if (hostname[0] == '|')
1145  useExternalDefinedSocket = TRUE;
1146 
1147  const char* vsock = utils_is_vsock(hostname);
1148  if (ipcSocket)
1149  {
1150  sockfd = freerdp_uds_connect(hostname);
1151 
1152  if (sockfd < 0)
1153  {
1154  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1155 
1156  return -1;
1157  }
1158  }
1159  else if (useExternalDefinedSocket)
1160  sockfd = port;
1161  else if (vsock)
1162  {
1163 #if defined(HAVE_AF_VSOCK_H)
1164  hostname = vsock;
1165  sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
1166  struct sockaddr_vm addr = { 0 };
1167 
1168  addr.svm_family = AF_VSOCK;
1169  addr.svm_port = port;
1170 
1171  errno = 0;
1172  char* ptr = NULL;
1173  unsigned long val = strtoul(hostname, &ptr, 10);
1174  if (errno || (val > UINT32_MAX))
1175  {
1176  char ebuffer[256] = { 0 };
1177  WLog_ERR(TAG, "could not extract port from '%s', value=%ul, error=%s", hostname, val,
1178  winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
1179  return -1;
1180  }
1181  addr.svm_cid = val;
1182  if (addr.svm_cid == 2)
1183  {
1184  addr.svm_flags = VMADDR_FLAG_TO_HOST;
1185  }
1186  if ((connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_vm))) == -1)
1187  {
1188  WLog_ERR(TAG, "failed to connect to %s", hostname);
1189  return -1;
1190  }
1191 #else
1192  WLog_ERR(TAG, "Compiled without AF_VSOCK, '%s' not supported", hostname);
1193  return -1;
1194 #endif
1195  }
1196  else
1197  {
1198  sockfd = -1;
1199 
1200  if (!settings->GatewayEnabled)
1201  {
1202  if (!freerdp_tcp_is_hostname_resolvable(context, hostname) ||
1203  settings->RemoteAssistanceMode)
1204  {
1205  if (settings->TargetNetAddressCount > 0)
1206  {
1207  WINPR_ASSERT(port <= UINT16_MAX);
1208  sockfd = freerdp_tcp_connect_multi(
1209  context, settings->TargetNetAddresses, settings->TargetNetPorts,
1210  settings->TargetNetAddressCount, (UINT16)port, timeout);
1211  }
1212  }
1213  }
1214 
1215  if (sockfd <= 0)
1216  {
1217  char* peerAddress = NULL;
1218  struct addrinfo* addr = NULL;
1219  struct addrinfo* result = NULL;
1220 
1221  result = freerdp_tcp_resolve_host(hostname, port, 0);
1222 
1223  if (!result)
1224  {
1225  freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1226 
1227  return -1;
1228  }
1229  freerdp_set_last_error_log(context, 0);
1230 
1231  /* By default we take the first returned entry.
1232  *
1233  * If PreferIPv6OverIPv4 = TRUE we force to IPv6 if there
1234  * is such an address available, but fall back to first if not found
1235  */
1236  const int rc =
1237  get_next_addrinfo(context, result, &addr, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
1238  if (rc < 0)
1239  return rc;
1240 
1241  do
1242  {
1243  sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1244  if (sockfd < 0)
1245  {
1246  const int lrc = get_next_addrinfo(context, addr->ai_next, &addr,
1247  FREERDP_ERROR_CONNECT_FAILED);
1248  if (lrc < 0)
1249  return lrc;
1250  }
1251  } while (sockfd < 0);
1252 
1253  if ((peerAddress = freerdp_tcp_address_to_string(
1254  (const struct sockaddr_storage*)addr->ai_addr, NULL)) != NULL)
1255  {
1256  WLog_DBG(TAG, "connecting to peer %s", peerAddress);
1257  free(peerAddress);
1258  }
1259 
1260  if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr, addr->ai_addrlen,
1261  timeout))
1262  {
1263  freeaddrinfo(result);
1264  close(sockfd);
1265 
1266  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1267 
1268  WLog_ERR(TAG, "failed to connect to %s", hostname);
1269  return -1;
1270  }
1271 
1272  freeaddrinfo(result);
1273  }
1274  }
1275 
1276  if (!vsock)
1277  {
1278  free(settings->ClientAddress);
1279  settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled);
1280 
1281  if (!settings->ClientAddress)
1282  {
1283  if (!useExternalDefinedSocket)
1284  close(sockfd);
1285 
1286  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1287 
1288  WLog_ERR(TAG, "Couldn't get socket ip address");
1289  return -1;
1290  }
1291  }
1292 
1293  optval = 1;
1294  optlen = sizeof(optval);
1295 
1296  if (!ipcSocket && !useExternalDefinedSocket)
1297  {
1298  if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, optlen) < 0)
1299  WLog_ERR(TAG, "unable to set TCP_NODELAY");
1300  }
1301 
1302  /* receive buffer must be a least 32 K */
1303  if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, &optlen) == 0)
1304  {
1305  if (optval < (1024 * 32))
1306  {
1307  optval = 1024 * 32;
1308  optlen = sizeof(optval);
1309 
1310  if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*)&optval, optlen) < 0)
1311  {
1312  close(sockfd);
1313 
1314  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1315 
1316  WLog_ERR(TAG, "unable to set receive buffer len");
1317  return -1;
1318  }
1319  }
1320  }
1321 
1322  if (!ipcSocket && !useExternalDefinedSocket)
1323  {
1324  if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1325  {
1326  close(sockfd);
1327 
1328  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_FAILED);
1329 
1330  WLog_ERR(TAG, "Couldn't set keep alive mode.");
1331  return -1;
1332  }
1333  }
1334 
1335  if (WaitForSingleObject(utils_get_abort_event(context->rdp), 0) == WAIT_OBJECT_0)
1336  {
1337  close(sockfd);
1338  return -1;
1339  }
1340 
1341  return sockfd;
1342 }
1343 
1344 struct rdp_tcp_layer
1345 {
1346  int sockfd;
1347  HANDLE hEvent;
1348 };
1349 typedef struct rdp_tcp_layer rdpTcpLayer;
1350 
1351 static int freerdp_tcp_layer_read(void* userContext, void* data, int bytes)
1352 {
1353  if (!userContext)
1354  return -1;
1355  if (!data || !bytes)
1356  return 0;
1357 
1358  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1359 
1360  int error = 0;
1361  int status = 0;
1362 
1363  (void)WSAResetEvent(tcpLayer->hEvent);
1364  status = _recv((SOCKET)tcpLayer->sockfd, data, bytes, 0);
1365 
1366  if (status > 0)
1367  return status;
1368 
1369  if (status == 0)
1370  return -1; /* socket closed */
1371 
1372  error = WSAGetLastError();
1373 
1374  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1375  (error == WSAEALREADY))
1376  {
1377  status = 0;
1378  }
1379  else
1380  {
1381  status = -1;
1382  }
1383 
1384  return status;
1385 }
1386 
1387 static int freerdp_tcp_layer_write(void* userContext, const void* data, int bytes)
1388 {
1389  if (!userContext)
1390  return -1;
1391  if (!data || !bytes)
1392  return 0;
1393 
1394  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1395 
1396  int error = 0;
1397  int status = 0;
1398 
1399  status = _send((SOCKET)tcpLayer->sockfd, data, bytes, 0);
1400 
1401  if (status <= 0)
1402  {
1403  error = WSAGetLastError();
1404 
1405  if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || (error == WSAEINPROGRESS) ||
1406  (error == WSAEALREADY))
1407  {
1408  status = 0;
1409  }
1410  else
1411  {
1412  status = -1;
1413  }
1414  }
1415 
1416  return status;
1417 }
1418 
1419 static BOOL freerdp_tcp_layer_close(void* userContext)
1420 {
1421  if (!userContext)
1422  return FALSE;
1423 
1424  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1425 
1426  if (tcpLayer->sockfd >= 0)
1427  closesocket((SOCKET)tcpLayer->sockfd);
1428  if (tcpLayer->hEvent)
1429  (void)CloseHandle(tcpLayer->hEvent);
1430 
1431  return TRUE;
1432 }
1433 
1434 static BOOL freerdp_tcp_layer_wait(void* userContext, BOOL waitWrite, DWORD timeout)
1435 {
1436  if (!userContext)
1437  return FALSE;
1438 
1439  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1440 
1441  int status = -1;
1442  int sockfd = tcpLayer->sockfd;
1443 #ifdef WINPR_HAVE_POLL_H
1444  struct pollfd pollset = { 0 };
1445  pollset.fd = sockfd;
1446  pollset.events = waitWrite ? POLLOUT : POLLIN;
1447 
1448  do
1449  {
1450  status = poll(&pollset, 1, (int)timeout);
1451  } while ((status < 0) && (errno == EINTR));
1452 
1453 #else
1454  fd_set rset = { 0 };
1455  struct timeval tv = { 0 };
1456  FD_ZERO(&rset);
1457  FD_SET(sockfd, &rset);
1458 
1459  if (timeout)
1460  {
1461  tv.tv_sec = timeout / 1000;
1462  tv.tv_usec = (timeout % 1000) * 1000;
1463  }
1464 
1465  do
1466  {
1467  if (waitWrite)
1468  status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
1469  else
1470  status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
1471  } while ((status < 0) && (errno == EINTR));
1472 
1473 #endif
1474 
1475  return status != 0;
1476 }
1477 
1478 static HANDLE freerdp_tcp_layer_get_event(void* userContext)
1479 {
1480  if (!userContext)
1481  return NULL;
1482 
1483  rdpTcpLayer* tcpLayer = (rdpTcpLayer*)userContext;
1484 
1485  return tcpLayer->hEvent;
1486 }
1487 
1488 rdpTransportLayer* freerdp_tcp_connect_layer(rdpContext* context, const char* hostname, int port,
1489  DWORD timeout)
1490 {
1491  WINPR_ASSERT(context);
1492 
1493  const rdpSettings* settings = context->settings;
1494  WINPR_ASSERT(settings);
1495 
1496  rdpTransportLayer* layer = NULL;
1497  rdpTcpLayer* tcpLayer = NULL;
1498 
1499  int sockfd = freerdp_tcp_connect(context, hostname, port, timeout);
1500  if (sockfd < 0)
1501  goto fail;
1502  if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
1503  goto fail;
1504 
1505  layer = transport_layer_new(freerdp_get_transport(context), sizeof(rdpTcpLayer));
1506  if (!layer)
1507  goto fail;
1508 
1509  layer->Read = freerdp_tcp_layer_read;
1510  layer->Write = freerdp_tcp_layer_write;
1511  layer->Close = freerdp_tcp_layer_close;
1512  layer->Wait = freerdp_tcp_layer_wait;
1513  layer->GetEvent = freerdp_tcp_layer_get_event;
1514 
1515  tcpLayer = (rdpTcpLayer*)layer->userContext;
1516  WINPR_ASSERT(tcpLayer);
1517 
1518  tcpLayer->sockfd = -1;
1519  tcpLayer->hEvent = WSACreateEvent();
1520  if (!tcpLayer->hEvent)
1521  goto fail;
1522 
1523  /* WSAEventSelect automatically sets the socket in non-blocking mode */
1524  if (WSAEventSelect((SOCKET)sockfd, tcpLayer->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
1525  {
1526  WLog_ERR(TAG, "WSAEventSelect returned 0x%08X", WSAGetLastError());
1527  goto fail;
1528  }
1529 
1530  tcpLayer->sockfd = sockfd;
1531 
1532  return layer;
1533 
1534 fail:
1535  if (sockfd >= 0)
1536  closesocket((SOCKET)sockfd);
1537  transport_layer_free(layer);
1538  return NULL;
1539 }
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