20#include <freerdp/config.h>
24#include <winpr/assert.h>
27#include <winpr/synch.h>
28#include <winpr/print.h>
29#include <winpr/stream.h>
30#include <winpr/winsock.h>
31#include <winpr/crypto.h>
33#include <freerdp/log.h>
34#include <freerdp/error.h>
35#include <freerdp/utils/ringbuffer.h>
37#include <openssl/bio.h>
44#include <sys/socket.h>
47#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
48#include <valgrind/memcheck.h>
58#include "childsession.h"
60#include "gateway/rdg.h"
61#include "gateway/wst.h"
62#include "gateway/arm.h"
64#define TAG FREERDP_TAG("core.transport")
66#define BUFFER_SIZE 16384
70 TRANSPORT_LAYER layer;
80 TransportRecv ReceiveCallback;
81 wStreamPool* ReceivePool;
82 HANDLE connectedEvent;
94 BOOL haveMoreBytesToRead;
105 void* userContextShadowPtr;
106} rdpTransportLayerInt;
108static const char* where2str(
int where,
char* ibuffer,
size_t ilen)
110 if (!ibuffer || (ilen < 2))
114 size_t len = ilen - 1;
115 char* buffer = &ibuffer[1];
116 if (where & SSL_CB_ALERT)
117 winpr_str_append(
"SSL_CB_ALERT", buffer, len,
"|");
118 if (where & SSL_ST_ACCEPT)
119 winpr_str_append(
"SSL_ST_ACCEPT", buffer, len,
"|");
120 if (where & SSL_ST_CONNECT)
121 winpr_str_append(
"SSL_ST_CONNECT", buffer, len,
"|");
122 if (where & SSL_CB_HANDSHAKE_DONE)
123 winpr_str_append(
"SSL_CB_HANDSHAKE_DONE", buffer, len,
"|");
124 if (where & SSL_CB_HANDSHAKE_START)
125 winpr_str_append(
"SSL_CB_HANDSHAKE_START", buffer, len,
"|");
126 if (where & SSL_CB_WRITE)
127 winpr_str_append(
"SSL_CB_WRITE", buffer, len,
"|");
128 if (where & SSL_CB_READ)
129 winpr_str_append(
"SSL_CB_READ", buffer, len,
"|");
130 if (where & SSL_CB_EXIT)
131 winpr_str_append(
"SSL_CB_EXIT", buffer, len,
"|");
132 if (where & SSL_CB_LOOP)
133 winpr_str_append(
"SSL_CB_LOOP", buffer, len,
"|");
135 char nr[32] = WINPR_C_ARRAY_INIT;
136 (void)_snprintf(nr,
sizeof(nr),
"]{0x%08" PRIx32
"}", (unsigned)where);
137 winpr_str_append(nr, buffer, len,
"");
141static void transport_ssl_cb(
const SSL* ssl,
int where,
int ret)
143 if (where & SSL_CB_ALERT)
145 char buffer[128] = WINPR_C_ARRAY_INIT;
146 rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
147 WINPR_ASSERT(transport);
151 case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
153 if (!freerdp_get_last_error(transport_get_context(transport)))
155 WLog_Print(transport->log, WLOG_ERROR,
"where=%s ACCESS DENIED",
156 where2str(where, buffer,
sizeof(buffer)));
157 freerdp_set_last_error_log(transport_get_context(transport),
158 FREERDP_ERROR_AUTHENTICATION_FAILED);
163 case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
165 WLog_Print(transport->log, WLOG_WARN,
"SSL error (where=%s, ret=%d [%s, %s])",
166 where2str(where, buffer,
sizeof(buffer)), ret,
167 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
169 if (transport->NlaMode)
171 if (!freerdp_get_last_error(transport_get_context(transport)))
175 kret = nla_get_error(transport->nla);
177 kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
178 freerdp_set_last_error_log(transport_get_context(transport), kret);
184 case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
185 WLog_Print(transport->log, WLOG_DEBUG,
"SSL warning (where=%s, ret=%d [%s, %s])",
186 where2str(where, buffer,
sizeof(buffer)), ret,
187 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
191 WLog_Print(transport->log, WLOG_WARN,
192 "Unhandled SSL error (where=%s, ret=%d [%s, %s])",
193 where2str(where, buffer,
sizeof(buffer)), ret,
194 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
200wStream* transport_send_stream_init(WINPR_ATTR_UNUSED rdpTransport* transport,
size_t size)
202 WINPR_ASSERT(transport);
204 return Stream_New(
nullptr, size);
207BOOL transport_attach(rdpTransport* transport,
int sockfd)
211 return IFCALLRESULT(FALSE, transport->io.TransportAttach, transport, sockfd);
214static BOOL transport_default_attach(rdpTransport* transport,
int sockfd)
216 BIO* socketBio =
nullptr;
217 BIO* bufferedBio =
nullptr;
218 const rdpSettings* settings =
nullptr;
219 rdpContext* context = transport_get_context(transport);
223 WLog_WARN(TAG,
"Running peer without socket (sockfd=%d)", sockfd);
227 settings = context->settings;
228 WINPR_ASSERT(settings);
232 if (!freerdp_tcp_set_keep_alive_mode(settings, sockfd))
235 socketBio = BIO_new(BIO_s_simple_socket());
241 bufferedBio = BIO_new(BIO_s_buffered_socket());
252 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
253 bufferedBio = BIO_push(bufferedBio, socketBio);
257 EnterCriticalSection(&(transport->ReadLock));
258 EnterCriticalSection(&(transport->WriteLock));
259 transport->frontBio = bufferedBio;
260 LeaveCriticalSection(&(transport->WriteLock));
261 LeaveCriticalSection(&(transport->ReadLock));
267 BIO_free_all(socketBio);
269 closesocket((SOCKET)sockfd);
274BOOL transport_connect_rdp(rdpTransport* transport)
279 switch (utils_authenticate(transport_get_context(transport)->instance, AUTH_RDP, FALSE))
283 case AUTH_NO_CREDENTIALS:
286 freerdp_set_last_error_if_not(transport_get_context(transport),
287 FREERDP_ERROR_CONNECT_CANCELLED);
294BOOL transport_connect_tls(rdpTransport* transport)
296 const rdpSettings* settings =
nullptr;
297 rdpContext* context = transport_get_context(transport);
299 settings = context->settings;
300 WINPR_ASSERT(settings);
303 if (settings->SelectedProtocol == PROTOCOL_SSL)
305 switch (utils_authenticate(context->instance, AUTH_TLS, FALSE))
309 case AUTH_NO_CREDENTIALS:
312 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
319 return IFCALLRESULT(FALSE, transport->io.TLSConnect, transport);
322static BOOL transport_default_connect_tls(rdpTransport* transport)
325 rdpTls* tls =
nullptr;
326 rdpContext* context =
nullptr;
327 rdpSettings* settings =
nullptr;
329 WINPR_ASSERT(transport);
331 context = transport_get_context(transport);
332 WINPR_ASSERT(context);
334 settings = context->settings;
335 WINPR_ASSERT(settings);
337 if (!(tls = freerdp_tls_new(context)))
340 transport->tls = tls;
342 if (transport->GatewayEnabled)
343 transport->layer = TRANSPORT_LAYER_TSG_TLS;
345 transport->layer = TRANSPORT_LAYER_TLS;
347 tls->hostname = settings->ServerHostname;
348 tls->serverName = settings->UserSpecifiedServerName;
349 tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->ServerPort));
354 tls->isGatewayTransport = FALSE;
355 tlsStatus = freerdp_tls_connect(tls, transport->frontBio);
361 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
365 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
371 transport->frontBio = tls->bio;
380 typedef void (*ssl_cb_t)(
const SSL* ssl,
int type,
int val);
381 ssl_cb_t fkt = transport_ssl_cb;
383 BIO_info_cb* bfkt = WINPR_FUNC_PTR_CAST(fkt, BIO_info_cb*);
384 BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, bfkt);
385 SSL_set_app_data(tls->ssl, transport);
387 if (!transport->frontBio)
389 WLog_Print(transport->log, WLOG_ERROR,
"unable to prepend a filtering TLS bio");
396BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
398 rdpContext* context =
nullptr;
399 rdpSettings* settings =
nullptr;
400 rdpRdp* rdp =
nullptr;
404 context = transport_get_context(transport);
405 WINPR_ASSERT(context);
407 settings = context->settings;
408 WINPR_ASSERT(settings);
413 if (!transport_connect_tls(transport))
416 if (!settings->Authentication)
420 rdp->nla = nla_new(context, transport);
425 nla_set_early_user_auth(rdp->nla, earlyUserAuth);
427 transport_set_nla_mode(transport, TRUE);
429 if (settings->AuthenticationServiceClass)
431 if (!nla_set_service_principal(rdp->nla, settings->AuthenticationServiceClass,
436 if (nla_client_begin(rdp->nla) < 0)
438 WLog_Print(transport->log, WLOG_ERROR,
"NLA begin failed");
440 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
442 transport_set_nla_mode(transport, FALSE);
446 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
449BOOL transport_connect_rdstls(rdpTransport* transport)
452 rdpRdstls* rdstls =
nullptr;
453 rdpContext* context =
nullptr;
455 WINPR_ASSERT(transport);
457 context = transport_get_context(transport);
458 WINPR_ASSERT(context);
460 if (!transport_connect_tls(transport))
463 rdstls = rdstls_new(context, transport);
467 transport_set_rdstls_mode(transport, TRUE);
469 if (rdstls_authenticate(rdstls) < 0)
471 WLog_Print(transport->log, WLOG_ERROR,
"RDSTLS authentication failed");
472 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
476 transport_set_rdstls_mode(transport, FALSE);
483BOOL transport_connect_aad(rdpTransport* transport)
485 rdpContext* context =
nullptr;
486 rdpSettings* settings =
nullptr;
487 rdpRdp* rdp =
nullptr;
491 context = transport_get_context(transport);
492 WINPR_ASSERT(context);
494 settings = context->settings;
495 WINPR_ASSERT(settings);
500 if (!transport_connect_tls(transport))
503 if (!settings->Authentication)
509 transport_set_aad_mode(transport, TRUE);
511 if (aad_client_begin(rdp->aad) < 0)
513 WLog_Print(transport->log, WLOG_ERROR,
"AAD begin failed");
515 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
517 transport_set_aad_mode(transport, FALSE);
521 return rdp_client_transition_to_state(rdp, CONNECTION_STATE_AAD);
524static BOOL transport_can_retry(
const rdpContext* context, BOOL status)
526 switch (freerdp_get_last_error(context))
528 case FREERDP_ERROR_CONNECT_TARGET_BOOTING:
535BOOL transport_connect(rdpTransport* transport,
const char* hostname, UINT16 port, DWORD timeout)
538 rdpContext* context = transport_get_context(transport);
540 WINPR_ASSERT(context);
541 WINPR_ASSERT(hostname);
543 rdpSettings* settings = context->settings;
544 WINPR_ASSERT(settings);
546 BOOL rpcFallback = !settings->GatewayHttpTransport;
548 if (transport->GatewayEnabled)
550 if (settings->GatewayUrl)
552 WINPR_ASSERT(!transport->wst);
553 transport->wst = wst_new(context);
557 WLog_Print(transport->log, WLOG_ERROR,
"wst_new failed");
561 status = wst_connect(transport->wst, timeout);
565 transport->frontBio = wst_get_front_bio_and_take_ownership(transport->wst);
566 WINPR_ASSERT(transport->frontBio);
567 BIO_set_nonblock(transport->frontBio, 0);
568 transport->layer = TRANSPORT_LAYER_TSG;
573 wst_free(transport->wst);
574 transport->wst =
nullptr;
577 if (transport_can_retry(transport->context, status) && settings->GatewayHttpTransport)
579 WINPR_ASSERT(!transport->rdg);
580 transport->rdg = rdg_new(context);
584 WLog_Print(transport->log, WLOG_ERROR,
"rdg_new failed");
588 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
592 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
593 WINPR_ASSERT(transport->frontBio);
594 BIO_set_nonblock(transport->frontBio, 0);
595 transport->layer = TRANSPORT_LAYER_TSG;
600 rdg_free(transport->rdg);
601 transport->rdg =
nullptr;
605 if (transport_can_retry(transport->context, status) && settings->GatewayRpcTransport &&
608 WINPR_ASSERT(!transport->tsg);
609 transport->tsg = tsg_new(transport);
615 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
616 status = tsg_connect(transport->tsg, hostname, port, timeout);
620 transport->frontBio = tsg_get_bio(transport->tsg);
621 transport->layer = TRANSPORT_LAYER_TSG;
626 tsg_free(transport->tsg);
627 transport->tsg =
nullptr;
634 const char* proxyHostname =
nullptr;
635 const char* proxyUsername =
nullptr;
636 const char* proxyPassword =
nullptr;
637 BOOL isProxyConnection =
638 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
641 if (isProxyConnection)
642 layer = transport_connect_layer(transport, proxyHostname, peerPort, timeout);
644 layer = transport_connect_layer(transport, hostname, port, timeout);
649 if (!transport_attach_layer(transport, layer))
651 transport_layer_free(layer);
655 if (isProxyConnection)
657 if (!proxy_connect(context, transport->frontBio, proxyUsername, proxyPassword, hostname,
668BOOL transport_connect_childsession(rdpTransport* transport)
670 WINPR_ASSERT(transport);
672 transport->frontBio = createChildSessionBio();
673 if (!transport->frontBio)
676 transport->layer = TRANSPORT_LAYER_TSG;
680BOOL transport_accept_rdp(rdpTransport* transport)
682 return transport !=
nullptr;
686BOOL transport_accept_tls(rdpTransport* transport)
690 return IFCALLRESULT(FALSE, transport->io.TLSAccept, transport);
693static BOOL transport_default_accept_tls(rdpTransport* transport)
695 rdpContext* context = transport_get_context(transport);
696 rdpSettings* settings =
nullptr;
698 WINPR_ASSERT(context);
700 settings = context->settings;
701 WINPR_ASSERT(settings);
704 transport->tls = freerdp_tls_new(context);
706 transport->layer = TRANSPORT_LAYER_TLS;
708 if (!freerdp_tls_accept(transport->tls, transport->frontBio, settings))
711 transport->frontBio = transport->tls->bio;
715BOOL transport_accept_nla(rdpTransport* transport, BOOL ext)
717 rdpContext* context = transport_get_context(transport);
718 rdpSettings* settings =
nullptr;
720 WINPR_ASSERT(context);
722 settings = context->settings;
723 WINPR_ASSERT(settings);
725 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
730 if (!settings->Authentication)
735 transport->nla = nla_new(context, transport);
736 transport_set_nla_mode(transport, TRUE);
739 nla_set_early_user_auth(transport->nla, ext);
740 if (nla_authenticate(transport->nla) < 0)
742 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
743 transport_set_nla_mode(transport, FALSE);
744 nla_free(transport->nla);
745 transport->nla =
nullptr;
746 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
747 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
748 freerdp_tls_send_alert(transport->tls);
753 transport_set_nla_mode(transport, FALSE);
757BOOL transport_accept_rdstls(rdpTransport* transport)
760 rdpRdstls* rdstls =
nullptr;
761 rdpContext* context =
nullptr;
763 WINPR_ASSERT(transport);
765 context = transport_get_context(transport);
766 WINPR_ASSERT(context);
768 if (!IFCALLRESULT(FALSE, transport->io.TLSAccept, transport))
771 rdstls = rdstls_new(context, transport);
775 transport_set_rdstls_mode(transport, TRUE);
777 if (rdstls_authenticate(rdstls) < 0)
779 WLog_Print(transport->log, WLOG_ERROR,
"client authentication failure");
780 freerdp_tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
781 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
782 freerdp_tls_send_alert(transport->tls);
786 transport_set_rdstls_mode(transport, FALSE);
793#define WLog_ERR_BIO(transport, biofunc, bio) \
794 transport_bio_error_log(transport, biofunc, bio, __FILE__, __func__, __LINE__)
796static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc,
797 WINPR_ATTR_UNUSED BIO* bio, LPCSTR file, LPCSTR func,
800 unsigned long sslerr = 0;
804 WINPR_ASSERT(transport);
809 if (!WLog_IsLevelActive(transport->log, level))
812 if (ERR_peek_error() == 0)
814 char ebuffer[256] = WINPR_C_ARRAY_INIT;
817 WLog_PrintTextMessage(transport->log, level, line, file, func,
"%s retries exceeded",
820 WLog_PrintTextMessage(transport->log, level, line, file, func,
821 "%s returned a system error %d: %s", biofunc, saveerrno,
822 winpr_strerror(saveerrno, ebuffer,
sizeof(ebuffer)));
826 while ((sslerr = ERR_get_error()))
828 char buf[120] = WINPR_C_ARRAY_INIT;
830 ERR_error_string_n(sslerr, buf, 120);
831 WLog_PrintTextMessage(transport->log, level, line, file, func,
"%s returned an error: %s",
836static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data,
size_t bytes)
839 rdpRdp* rdp =
nullptr;
840 rdpContext* context =
nullptr;
842 WINPR_ASSERT(transport);
844 context = transport_get_context(transport);
845 WINPR_ASSERT(context);
850 if (!transport->frontBio || (bytes > SSIZE_MAX))
852 transport->layer = TRANSPORT_LAYER_CLOSED;
853 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
857 while (read < (SSIZE_T)bytes)
859 const SSIZE_T tr = (SSIZE_T)bytes - read;
860 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
862 int status = BIO_read(transport->frontBio, data + read, r);
864 if (freerdp_shall_disconnect_context(context))
869 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
872 if (!transport->frontBio)
874 WLog_Print(transport->log, WLOG_ERROR,
"BIO_read: transport->frontBio null");
878 WLog_ERR_BIO(transport,
"BIO_read", transport->frontBio);
879 transport->layer = TRANSPORT_LAYER_CLOSED;
880 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
885 if (!transport->blocking)
890 if (BIO_wait_read(transport->frontBio, 100) < 0)
892 WLog_ERR_BIO(transport,
"BIO_wait_read", transport->frontBio);
899#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H
900 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
903 rdp->inBytes += WINPR_ASSERTING_INT_CAST(uint64_t, status);
923static SSIZE_T transport_read_layer_bytes(rdpTransport* transport,
wStream* s,
size_t toRead)
929 if (toRead > SSIZE_MAX)
932 status = IFCALLRESULT(-1, transport->io.ReadBytes, transport, Stream_Pointer(s), toRead);
937 Stream_Seek(s, (
size_t)status);
938 return status == (SSIZE_T)toRead ? 1 : 0;
953int transport_read_pdu(rdpTransport* transport,
wStream* s)
957 return IFCALLRESULT(-1, transport->io.ReadPdu, transport, s);
961static SSIZE_T parse_nla_mode_pdu(rdpTransport* transport,
wStream* stream)
963 SSIZE_T pduLength = 0;
964 wStream sbuffer = WINPR_C_ARRAY_INIT;
965 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
972 UINT8 typeEncoding = 0;
973 if (Stream_GetRemainingLength(s) < 1)
975 Stream_Read_UINT8(s, typeEncoding);
976 if (typeEncoding != 0x30)
980 UINT8 lengthEncoding = 0;
981 if (Stream_GetRemainingLength(s) < 1)
983 Stream_Read_UINT8(s, lengthEncoding);
984 if (lengthEncoding & 0x80)
986 if ((lengthEncoding & ~(0x80)) == 1)
989 if (Stream_GetRemainingLength(s) < 1)
991 Stream_Read_UINT8(s, length);
995 else if ((lengthEncoding & ~(0x80)) == 2)
999 if (Stream_GetRemainingLength(s) < 2)
1001 Stream_Read_UINT16_BE(s, length);
1007 WLog_Print(transport->log, WLOG_ERROR,
"Error reading TSRequest!");
1013 pduLength = lengthEncoding;
1020static SSIZE_T parse_default_mode_pdu(rdpTransport* transport,
wStream* stream)
1022 SSIZE_T pduLength = 0;
1023 wStream sbuffer = WINPR_C_ARRAY_INIT;
1024 wStream* s = Stream_StaticConstInit(&sbuffer, Stream_Buffer(stream), Stream_Length(stream));
1027 if (Stream_GetRemainingLength(s) < 1)
1029 Stream_Read_UINT8(s, version);
1030 if (version == 0x03)
1034 if (Stream_GetRemainingLength(s) < 3)
1037 Stream_Read_UINT16_BE(s, length);
1041 if ((pduLength < 7) || (pduLength > 0xFFFF))
1043 WLog_Print(transport->log, WLOG_ERROR,
"tpkt - invalid pduLength: %" PRIdz, pduLength);
1051 if (Stream_GetRemainingLength(s) < 1)
1053 Stream_Read_UINT8(s, length1);
1057 if (Stream_GetRemainingLength(s) < 1)
1059 Stream_Read_UINT8(s, length2);
1060 pduLength = ((length1 & 0x7F) << 8) | length2;
1063 pduLength = length1;
1070 if (pduLength < 3 || pduLength > 0x8000)
1072 WLog_Print(transport->log, WLOG_ERROR,
"fast path - invalid pduLength: %" PRIdz,
1081SSIZE_T transport_parse_pdu(rdpTransport* transport,
wStream* s, BOOL* incomplete)
1083 SSIZE_T pduLength = 0;
1094 Stream_SealLength(s);
1095 if (transport->NlaMode)
1096 pduLength = parse_nla_mode_pdu(transport, s);
1097 else if (transport->RdstlsMode)
1098 pduLength = rdstls_parse_pdu(transport->log, s);
1100 pduLength = parse_default_mode_pdu(transport, s);
1105 const size_t len = Stream_Length(s);
1106 if (len > WINPR_ASSERTING_INT_CAST(
size_t, pduLength))
1110 *incomplete = len < WINPR_ASSERTING_INT_CAST(
size_t, pduLength);
1115static int transport_default_read_pdu(rdpTransport* transport,
wStream* s)
1117 BOOL incomplete = 0;
1119 size_t pduLength = 0;
1120 size_t position = 0;
1122 WINPR_ASSERT(transport);
1127 if (transport->AadMode)
1132 const SSIZE_T rc = transport_read_layer(transport, &c, 1);
1134 return (rc == 0) ? 0 : -1;
1135 if (!Stream_EnsureRemainingCapacity(s, 1))
1137 Stream_Write_UINT8(s, c);
1138 }
while (c !=
'\0');
1140 else if (transport->earlyUserAuth)
1142 if (!Stream_EnsureRemainingCapacity(s, 4))
1144 const SSIZE_T rc = transport_read_layer_bytes(transport, s, 4);
1146 return (rc == 0) ? 0 : -1;
1151 status = transport_parse_pdu(transport, s, &incomplete);
1152 while ((status == 0) && incomplete)
1154 if (!Stream_EnsureRemainingCapacity(s, 1))
1156 SSIZE_T rc = transport_read_layer_bytes(transport, s, 1);
1161 status = transport_parse_pdu(transport, s, &incomplete);
1167 pduLength = (size_t)status;
1170 if (!Stream_EnsureCapacity(s, pduLength))
1173 position = Stream_GetPosition(s);
1174 if (position > pduLength)
1176 else if (position < pduLength)
1178 status = transport_read_layer_bytes(transport, s, pduLength - position);
1181 if ((status < INT32_MIN) || (status > INT32_MAX))
1187 if (Stream_GetPosition(s) >= pduLength)
1188 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength,
1189 WLOG_PACKET_INBOUND);
1192 Stream_SealLength(s);
1193 Stream_ResetPosition(s);
1194 const size_t len = Stream_Length(s);
1195 if (len > INT32_MAX)
1200int transport_write(rdpTransport* transport,
wStream* s)
1205 return IFCALLRESULT(-1, transport->io.WritePdu, transport, s);
1208static int transport_default_write(rdpTransport* transport,
wStream* s)
1211 rdpContext* context = transport_get_context(transport);
1213 WINPR_ASSERT(transport);
1214 WINPR_ASSERT(context);
1221 rdpRdp* rdp = context->rdp;
1225 EnterCriticalSection(&(transport->WriteLock));
1226 if (!transport->frontBio)
1230 size_t length = Stream_GetPosition(s);
1231 size_t writtenlength = length;
1232 Stream_ResetPosition(s);
1236 rdp->outBytes += length;
1237 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
1243 const int towrite = (length > INT32_MAX) ? INT32_MAX : (int)length;
1244 status = BIO_write(transport->frontBio, Stream_ConstPointer(s), towrite);
1252 if (!BIO_should_retry(transport->frontBio))
1254 WLog_ERR_BIO(transport,
"BIO_should_retry", transport->frontBio);
1260 if (!transport->blocking)
1262 WLog_ERR_BIO(transport,
"BIO_write", transport->frontBio);
1266 if (BIO_wait_write(transport->frontBio, 100) < 0)
1268 WLog_ERR_BIO(transport,
"BIO_wait_write", transport->frontBio);
1276 WINPR_ASSERT(context->settings);
1277 if (transport->blocking || context->settings->WaitForOutputBufferFlush)
1279 while (BIO_write_blocked(transport->frontBio))
1281 if (BIO_wait_write(transport->frontBio, 100) < 0)
1283 WLog_Print(transport->log, WLOG_ERROR,
"error when selecting for write");
1288 if (BIO_flush(transport->frontBio) < 1)
1290 WLog_Print(transport->log, WLOG_ERROR,
"error when flushing outputBuffer");
1297 const size_t ustatus = (size_t)status;
1298 if (ustatus > length)
1305 Stream_Seek(s, ustatus);
1308 transport->written += writtenlength;
1315 transport->layer = TRANSPORT_LAYER_CLOSED;
1316 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1319 LeaveCriticalSection(&(transport->WriteLock));
1325BOOL transport_get_public_key(rdpTransport* transport,
const BYTE** data, DWORD* length)
1327 return IFCALLRESULT(FALSE, transport->io.GetPublicKey, transport, data, length);
1330static BOOL transport_default_get_public_key(rdpTransport* transport,
const BYTE** data,
1333 rdpTls* tls = transport_get_tls(transport);
1337 *data = tls->PublicKey;
1338 *length = tls->PublicKeyLength;
1343BOOL transport_get_peer_address(rdpTransport* transport,
struct sockaddr_storage* address,
1346 WINPR_ASSERT(transport);
1347 WINPR_ASSERT(address);
1348 WINPR_ASSERT(length);
1350 if (transport->GatewayEnabled)
1354 if (transport->frontBio)
1355 (void)BIO_get_fd(transport->frontBio, &sockfd);
1356 if ((sockfd < 0) && transport->tls && transport->tls->underlying)
1357 (
void)BIO_get_fd(transport->tls->underlying, &sockfd);
1360 WLog_Print(transport->log, WLOG_DEBUG,
"no socket found for the peer address");
1364 socklen_t len =
sizeof(*address);
1365 if (getpeername(sockfd, (
struct sockaddr*)address, &len) != 0)
1371DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
1375 WINPR_ASSERT(transport);
1376 WINPR_ASSERT(events);
1377 WINPR_ASSERT(count > 0);
1383 WLog_Print(transport->log, WLOG_ERROR,
"provided handles array is too small");
1387 events[nCount++] = transport->rereadEvent;
1389 if (transport->useIoEvent)
1393 events[nCount++] = transport->ioEvent;
1397 if (!transport->GatewayEnabled)
1401 if (nCount >= count)
1403 WLog_Print(transport->log, WLOG_ERROR,
1404 "provided handles array is too small (count=%" PRIu32
" nCount=%" PRIu32
1410 if (transport->frontBio)
1412 if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
1414 WLog_Print(transport->log, WLOG_ERROR,
"error getting the frontBio handle");
1426 rdg_get_event_handles(transport->rdg, &events[nCount], count - nCount);
1433 else if (transport->tsg)
1436 tsg_get_event_handles(transport->tsg, &events[nCount], count - nCount);
1443 else if (transport->wst)
1446 wst_get_event_handles(transport->wst, &events[nCount], count - nCount);
1458#if defined(WITH_FREERDP_DEPRECATED)
1459void transport_get_fds(rdpTransport* transport,
void** rfds,
int* rcount)
1462 HANDLE events[MAXIMUM_WAIT_OBJECTS] = WINPR_C_ARRAY_INIT;
1464 WINPR_ASSERT(transport);
1466 WINPR_ASSERT(rcount);
1468 nCount = transport_get_event_handles(transport, events, ARRAYSIZE(events));
1469 *rcount = nCount + 1;
1471 for (DWORD index = 0; index < nCount; index++)
1473 rfds[index] = GetEventWaitObject(events[index]);
1476 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
1480BOOL transport_is_write_blocked(rdpTransport* transport)
1482 WINPR_ASSERT(transport);
1483 WINPR_ASSERT(transport->frontBio);
1484 return BIO_write_blocked(transport->frontBio) != 0;
1487int transport_drain_output_buffer(rdpTransport* transport)
1489 BOOL status = FALSE;
1491 WINPR_ASSERT(transport);
1492 WINPR_ASSERT(transport->frontBio);
1493 if (BIO_write_blocked(transport->frontBio))
1495 if (BIO_flush(transport->frontBio) < 1)
1498 const long rc = BIO_write_blocked(transport->frontBio);
1505int transport_check_fds(rdpTransport* transport)
1508 state_run_t recv_status = STATE_RUN_FAILED;
1510 rdpContext* context = transport_get_context(transport);
1512 WINPR_ASSERT(context);
1514 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1516 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport layer closed");
1517 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1530 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1533 WLog_Print(transport->log, WLOG_DEBUG,
"transport_check_fds: transport_read_pdu() - %i",
1535 if (transport->haveMoreBytesToRead)
1537 transport->haveMoreBytesToRead = FALSE;
1538 (void)ResetEvent(transport->rereadEvent);
1543 received = transport->ReceiveBuffer;
1544 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1545 if (!transport->ReceiveBuffer)
1547 Stream_Release(received);
1557 WINPR_ASSERT(transport->ReceiveCallback);
1558 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1559 Stream_Release(received);
1561 if (state_run_failed(recv_status))
1563 char buffer[64] = WINPR_C_ARRAY_INIT;
1564 WLog_Print(transport->log, WLOG_ERROR,
1565 "transport_check_fds: transport->ReceiveCallback() - %s",
1566 state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
1573 if (!transport->haveMoreBytesToRead)
1575 transport->haveMoreBytesToRead = TRUE;
1576 (void)SetEvent(transport->rereadEvent);
1581BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1583 WINPR_ASSERT(transport);
1585 return IFCALLRESULT(FALSE, transport->io.SetBlockingMode, transport, blocking);
1588static BOOL transport_default_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1590 WINPR_ASSERT(transport);
1592 transport->blocking = blocking;
1594 if (transport->frontBio)
1596 if (!BIO_set_nonblock(transport->frontBio, !(blocking)))
1603rdpTransportLayer* transport_connect_layer(rdpTransport* transport,
const char* hostname,
int port,
1606 WINPR_ASSERT(transport);
1609 IFCALLRESULT(
nullptr, transport->io.ConnectLayer, transport, hostname, port, timeout);
1611 WLog_Print(transport->log, WLOG_ERROR,
"ConnectLayer %s:%d [%" PRIu32
"ms] failed",
1612 hostname, port, timeout);
1616static rdpTransportLayer* transport_default_connect_layer(rdpTransport* transport,
1617 const char* hostname,
int port,
1620 rdpContext* context = transport_get_context(transport);
1621 WINPR_ASSERT(context);
1623 return freerdp_tcp_connect_layer(context, hostname, port, timeout);
1628 WINPR_ASSERT(transport);
1629 WINPR_ASSERT(layer);
1631 const BOOL rc = IFCALLRESULT(FALSE, transport->io.AttachLayer, transport, layer);
1633 WLog_Print(transport->log, WLOG_ERROR,
"AttachLayer failed");
1637static BOOL transport_default_attach_layer(rdpTransport* transport,
rdpTransportLayer* layer)
1639 BIO* layerBio = BIO_new(BIO_s_transport_layer());
1644 BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
1648 bufferedBio = BIO_push(bufferedBio, layerBio);
1653 BIO_set_data(layerBio, layer);
1655 transport->frontBio = bufferedBio;
1661 BIO_free_all(layerBio);
1666void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1668 WINPR_ASSERT(transport);
1669 transport->GatewayEnabled = GatewayEnabled;
1672void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1674 WINPR_ASSERT(transport);
1675 transport->NlaMode = NlaMode;
1678void transport_set_rdstls_mode(rdpTransport* transport, BOOL RdstlsMode)
1680 WINPR_ASSERT(transport);
1681 transport->RdstlsMode = RdstlsMode;
1684void transport_set_aad_mode(rdpTransport* transport, BOOL AadMode)
1686 WINPR_ASSERT(transport);
1687 transport->AadMode = AadMode;
1690BOOL transport_disconnect(rdpTransport* transport)
1694 return IFCALLRESULT(FALSE, transport->io.TransportDisconnect, transport);
1697static BOOL transport_default_disconnect(rdpTransport* transport)
1704 EnterCriticalSection(&(transport->ReadLock));
1705 EnterCriticalSection(&(transport->WriteLock));
1708 freerdp_tls_free(transport->tls);
1709 transport->tls =
nullptr;
1713 if (transport->frontBio)
1714 BIO_free_all(transport->frontBio);
1719 tsg_free(transport->tsg);
1720 transport->tsg =
nullptr;
1725 rdg_free(transport->rdg);
1726 transport->rdg =
nullptr;
1731 wst_free(transport->wst);
1732 transport->wst =
nullptr;
1735 transport->frontBio =
nullptr;
1736 transport->layer = TRANSPORT_LAYER_TCP;
1737 transport->earlyUserAuth = FALSE;
1738 LeaveCriticalSection(&(transport->WriteLock));
1739 LeaveCriticalSection(&(transport->ReadLock));
1743rdpTransport* transport_new(rdpContext* context)
1745 rdpTransport* transport = (rdpTransport*)calloc(1,
sizeof(rdpTransport));
1747 WINPR_ASSERT(context);
1751 transport->log = WLog_Create(TAG, WLog_GetRoot());
1753 if (!transport->log)
1756 transport->context = context;
1757 transport->haveReadLock = InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000);
1758 transport->haveWriteLock = InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000);
1759 if (!transport->haveReadLock || !transport->haveWriteLock)
1762 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1764 if (!transport->ReceivePool)
1768 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1770 if (!transport->ReceiveBuffer)
1773 transport->connectedEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1775 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1778 transport->rereadEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1780 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1783 transport->ioEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1785 if (!transport->ioEvent || transport->ioEvent == INVALID_HANDLE_VALUE)
1788 transport->haveMoreBytesToRead = FALSE;
1789 transport->blocking = TRUE;
1790 transport->GatewayEnabled = FALSE;
1791 transport->layer = TRANSPORT_LAYER_TCP;
1794 transport->io.TCPConnect = freerdp_tcp_default_connect;
1795 transport->io.TLSConnect = transport_default_connect_tls;
1796 transport->io.TLSAccept = transport_default_accept_tls;
1797 transport->io.TransportAttach = transport_default_attach;
1798 transport->io.TransportDisconnect = transport_default_disconnect;
1799 transport->io.ReadPdu = transport_default_read_pdu;
1800 transport->io.WritePdu = transport_default_write;
1801 transport->io.ReadBytes = transport_read_layer;
1802 transport->io.GetPublicKey = transport_default_get_public_key;
1803 transport->io.SetBlockingMode = transport_default_set_blocking_mode;
1804 transport->io.ConnectLayer = transport_default_connect_layer;
1805 transport->io.AttachLayer = transport_default_attach_layer;
1809 WINPR_PRAGMA_DIAG_PUSH
1810 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1811 transport_free(transport);
1812 WINPR_PRAGMA_DIAG_POP
1816void transport_free(rdpTransport* transport)
1821 transport_disconnect(transport);
1823 if (transport->haveReadLock)
1824 EnterCriticalSection(&(transport->ReadLock));
1826 if (transport->ReceiveBuffer)
1827 Stream_Release(transport->ReceiveBuffer);
1829 if (transport->haveReadLock)
1830 LeaveCriticalSection(&(transport->ReadLock));
1832 if (transport->ReceivePool)
1833 (void)StreamPool_WaitForReturn(transport->ReceivePool, INFINITE);
1835 if (transport->haveReadLock)
1836 EnterCriticalSection(&(transport->ReadLock));
1838 if (transport->haveWriteLock)
1839 EnterCriticalSection(&(transport->WriteLock));
1841 nla_free(transport->nla);
1842 StreamPool_Free(transport->ReceivePool);
1843 (void)CloseHandle(transport->connectedEvent);
1844 (void)CloseHandle(transport->rereadEvent);
1845 (void)CloseHandle(transport->ioEvent);
1847 if (transport->haveReadLock)
1848 LeaveCriticalSection(&(transport->ReadLock));
1849 DeleteCriticalSection(&(transport->ReadLock));
1851 if (transport->haveWriteLock)
1852 LeaveCriticalSection(&(transport->WriteLock));
1853 DeleteCriticalSection(&(transport->WriteLock));
1854 WLog_Discard(transport->log);
1858BOOL transport_set_io_callbacks(rdpTransport* transport,
const rdpTransportIo* io_callbacks)
1860 if (!transport || !io_callbacks)
1863 transport->io = *io_callbacks;
1867const rdpTransportIo* transport_get_io_callbacks(
const rdpTransport* transport)
1871 return &transport->io;
1874rdpContext* transport_get_context(rdpTransport* transport)
1876 WINPR_ASSERT(transport);
1877 return transport->context;
1880rdpTransport* freerdp_get_transport(rdpContext* context)
1882 WINPR_ASSERT(context);
1883 WINPR_ASSERT(context->rdp);
1884 return context->rdp->transport;
1887BOOL transport_set_nla(rdpTransport* transport, rdpNla* nla)
1889 WINPR_ASSERT(transport);
1890 nla_free(transport->nla);
1891 transport->nla = nla;
1895rdpNla* transport_get_nla(rdpTransport* transport)
1897 WINPR_ASSERT(transport);
1898 return transport->nla;
1901BOOL transport_set_tls(rdpTransport* transport, rdpTls* tls)
1903 WINPR_ASSERT(transport);
1904 freerdp_tls_free(transport->tls);
1905 transport->tls = tls;
1909rdpTls* transport_get_tls(rdpTransport* transport)
1911 WINPR_ASSERT(transport);
1912 return transport->tls;
1915BOOL transport_set_tsg(rdpTransport* transport, rdpTsg* tsg)
1917 WINPR_ASSERT(transport);
1918 tsg_free(transport->tsg);
1919 transport->tsg = tsg;
1923rdpTsg* transport_get_tsg(rdpTransport* transport)
1925 WINPR_ASSERT(transport);
1926 return transport->tsg;
1929wStream* transport_take_from_pool(rdpTransport* transport,
size_t size)
1931 WINPR_ASSERT(transport);
1932 if (!transport->frontBio)
1934 return StreamPool_Take(transport->ReceivePool, size);
1937UINT64 transport_get_bytes_sent(rdpTransport* transport, BOOL resetCount)
1940 WINPR_ASSERT(transport);
1941 rc = transport->written;
1943 transport->written = 0;
1947TRANSPORT_LAYER transport_get_layer(rdpTransport* transport)
1949 WINPR_ASSERT(transport);
1950 return transport->layer;
1953BOOL transport_set_layer(rdpTransport* transport, TRANSPORT_LAYER layer)
1955 WINPR_ASSERT(transport);
1956 transport->layer = layer;
1960BOOL transport_set_connected_event(rdpTransport* transport)
1962 WINPR_ASSERT(transport);
1963 return SetEvent(transport->connectedEvent);
1966BOOL transport_set_recv_callbacks(rdpTransport* transport, TransportRecv recv,
void* extra)
1968 WINPR_ASSERT(transport);
1969 transport->ReceiveCallback = recv;
1970 transport->ReceiveExtra = extra;
1974BOOL transport_get_blocking(
const rdpTransport* transport)
1976 WINPR_ASSERT(transport);
1977 return transport->blocking;
1980BOOL transport_set_blocking(rdpTransport* transport, BOOL blocking)
1982 WINPR_ASSERT(transport);
1983 transport->blocking = blocking;
1987BOOL transport_have_more_bytes_to_read(rdpTransport* transport)
1989 WINPR_ASSERT(transport);
1990 return transport->haveMoreBytesToRead;
1993int transport_tcp_connect(rdpTransport* transport,
const char* hostname,
int port, DWORD timeout)
1995 rdpContext* context = transport_get_context(transport);
1996 WINPR_ASSERT(context);
1997 WINPR_ASSERT(context->settings);
1998 return IFCALLRESULT(-1, transport->io.TCPConnect, context, context->settings, hostname, port,
2002HANDLE transport_get_front_bio(rdpTransport* transport)
2004 HANDLE hEvent =
nullptr;
2005 WINPR_ASSERT(transport);
2006 WINPR_ASSERT(transport->frontBio);
2008 BIO_get_event(transport->frontBio, &hEvent);
2012BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
2014 WINPR_ASSERT(transport);
2015 transport->useIoEvent = TRUE;
2017 return ResetEvent(transport->ioEvent);
2018 return SetEvent(transport->ioEvent);
2021void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
2023 WINPR_ASSERT(transport);
2024 transport->earlyUserAuth = EUAMode;
2025 WLog_Print(transport->log, WLOG_DEBUG,
"Early User Auth Mode: %s", EUAMode ?
"on" :
"off");
2028rdpTransportLayer* transport_layer_new(WINPR_ATTR_UNUSED rdpTransport* transport,
2031 rdpTransportLayerInt* layer = (rdpTransportLayerInt*)calloc(1,
sizeof(rdpTransportLayerInt));
2037 layer->userContextShadowPtr = calloc(1, contextSize);
2038 if (!layer->userContextShadowPtr)
2044 layer->pub.userContext = layer->userContextShadowPtr;
2051 rdpTransportLayerInt* intern = (rdpTransportLayerInt*)layer;
2055 if (intern->pub.Close)
2056 intern->pub.Close(intern->pub.userContext);
2057 free(intern->userContextShadowPtr);
2061static int transport_layer_bio_write(BIO* bio,
const char* buf,
int size)
2074 BIO_clear_flags(bio, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY);
2077 const int status = IFCALLRESULT(-1, layer->Write, layer->userContext, buf, size);
2079 if (status >= 0 && status < size)
2080 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
2085 BIO_set_flags(bio, (BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY));
2094static int transport_layer_bio_read(BIO* bio,
char* buf,
int size)
2107 BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY);
2109 const int status = IFCALLRESULT(-1, layer->Read, layer->userContext, buf, size);
2114 BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
2123static int transport_layer_bio_puts(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED
const char* str)
2128static int transport_layer_bio_gets(WINPR_ATTR_UNUSED BIO* bio, WINPR_ATTR_UNUSED
char* str,
2129 WINPR_ATTR_UNUSED
int size)
2134static long transport_layer_bio_ctrl(BIO* bio,
int cmd,
long arg1,
void* arg2)
2145 case BIO_C_GET_EVENT:
2146 *((HANDLE*)arg2) = IFCALLRESULT(
nullptr, layer->GetEvent, layer->userContext);
2150 case BIO_C_SET_NONBLOCK:
2154 case BIO_C_WAIT_READ:
2156 int timeout = (int)arg1;
2157 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, FALSE,
2158 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2170 case BIO_C_WAIT_WRITE:
2172 int timeout = (int)arg1;
2173 BOOL r = IFCALLRESULT(FALSE, layer->Wait, layer->userContext, TRUE,
2174 WINPR_ASSERTING_INT_CAST(uint32_t, timeout));
2186 case BIO_CTRL_GET_CLOSE:
2187 status = BIO_get_shutdown(bio);
2190 case BIO_CTRL_SET_CLOSE:
2191 BIO_set_shutdown(bio, (
int)arg1);
2195 case BIO_CTRL_FLUSH:
2208static int transport_layer_bio_new(BIO* bio)
2212 BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2213 BIO_set_init(bio, 1);
2217static int transport_layer_bio_free(BIO* bio)
2224 transport_layer_free(layer);
2226 BIO_set_data(bio,
nullptr);
2227 BIO_set_init(bio, 0);
2228 BIO_set_flags(bio, 0);
2233BIO_METHOD* BIO_s_transport_layer(
void)
2235 static BIO_METHOD* bio_methods =
nullptr;
2237 if (bio_methods ==
nullptr)
2239 if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE,
"TransportLayer")))
2242 BIO_meth_set_write(bio_methods, transport_layer_bio_write);
2243 BIO_meth_set_read(bio_methods, transport_layer_bio_read);
2244 BIO_meth_set_puts(bio_methods, transport_layer_bio_puts);
2245 BIO_meth_set_gets(bio_methods, transport_layer_bio_gets);
2246 BIO_meth_set_ctrl(bio_methods, transport_layer_bio_ctrl);
2247 BIO_meth_set_create(bio_methods, transport_layer_bio_new);
2248 BIO_meth_set_destroy(bio_methods, transport_layer_bio_free);
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.