20#include <freerdp/config.h>
22#include <winpr/crypto.h>
23#include <winpr/assert.h>
25#include "autodetect.h"
27#define TYPE_ID_AUTODETECT_REQUEST 0x00
28#define TYPE_ID_AUTODETECT_RESPONSE 0x01
30#define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001
31#define RDP_RTT_REQUEST_TYPE_CONNECTTIME 0x1001
33#define RDP_RTT_RESPONSE_TYPE 0x0000
35#define RDP_BW_START_REQUEST_TYPE_CONTINUOUS 0x0014
36#define RDP_BW_START_REQUEST_TYPE_TUNNEL 0x0114
37#define RDP_BW_START_REQUEST_TYPE_CONNECTTIME 0x1014
38#define RDP_BW_PAYLOAD_REQUEST_TYPE 0x0002
39#define RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME 0x002B
40#define RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS 0x0429
41#define RDP_BW_STOP_REQUEST_TYPE_TUNNEL 0x0629
43#define RDP_NETCHAR_SYNC_RESPONSE_TYPE 0x0018
45#define RDP_NETCHAR_RESULTS_0x0840 0x0840U
46#define RDP_NETCHAR_RESULTS_0x0880 0x0880U
47#define RDP_NETCHAR_RESULTS_0x08C0 0x08C0U
53 UINT16 sequenceNumber;
61 UINT16 sequenceNumber;
65static const char* autodetect_header_type_string(UINT8 headerType,
char* buffer,
size_t size)
67 const char* str =
nullptr;
70 case TYPE_ID_AUTODETECT_REQUEST:
71 str =
"TYPE_ID_AUTODETECT_REQUEST";
73 case TYPE_ID_AUTODETECT_RESPONSE:
74 str =
"TYPE_ID_AUTODETECT_RESPONSE";
77 str =
"TYPE_ID_AUTODETECT_UNKNOWN";
81 (void)_snprintf(buffer, size,
"%s [0x%08" PRIx8
"]", str, headerType);
85static const char* autodetect_request_type_to_string(UINT32 requestType)
89 case RDP_RTT_RESPONSE_TYPE:
90 return "RDP_RTT_RESPONSE_TYPE";
91 case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
92 return "RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME";
93 case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
94 return "RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS";
95 case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
96 return "RDP_RTT_REQUEST_TYPE_CONTINUOUS";
97 case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
98 return "RDP_RTT_REQUEST_TYPE_CONNECTTIME";
99 case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
100 return "RDP_BW_START_REQUEST_TYPE_CONTINUOUS";
101 case RDP_BW_START_REQUEST_TYPE_TUNNEL:
102 return "RDP_BW_START_REQUEST_TYPE_TUNNEL";
103 case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
104 return "RDP_BW_START_REQUEST_TYPE_CONNECTTIME";
105 case RDP_BW_PAYLOAD_REQUEST_TYPE:
106 return "RDP_BW_PAYLOAD_REQUEST_TYPE";
107 case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
108 return "RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME";
109 case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
110 return "RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS";
111 case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
112 return "RDP_BW_STOP_REQUEST_TYPE_TUNNEL";
113 case RDP_NETCHAR_RESULTS_0x0840:
114 return "RDP_NETCHAR_RESULTS_0x0840";
115 case RDP_NETCHAR_RESULTS_0x0880:
116 return "RDP_NETCHAR_RESULTS_0x0880";
117 case RDP_NETCHAR_RESULTS_0x08C0:
118 return "RDP_NETCHAR_RESULTS_0x08C0";
124static const char* autodetect_request_type_to_string_buffer(UINT32 requestType,
char* buffer,
127 const char* str = autodetect_request_type_to_string(requestType);
128 (void)_snprintf(buffer, size,
"%s [0x%08" PRIx32
"]", str, requestType);
132static BOOL autodetect_send_rtt_measure_request(rdpAutoDetect* autodetect,
133 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
134 UINT16 sequenceNumber)
136 UINT16 requestType = 0;
137 UINT16 sec_flags = 0;
140 WINPR_ASSERT(autodetect);
141 WINPR_ASSERT(autodetect->context);
143 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
147 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
148 requestType = RDP_RTT_REQUEST_TYPE_CONNECTTIME;
150 requestType = RDP_RTT_REQUEST_TYPE_CONTINUOUS;
152 WLog_Print(autodetect->log, WLOG_TRACE,
"sending RTT Measure Request PDU");
153 Stream_Write_UINT8(s, 0x06);
154 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
155 Stream_Write_UINT16(s, sequenceNumber);
156 Stream_Write_UINT16(s, requestType);
157 autodetect->rttMeasureStartTime = GetTickCount64();
158 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
159 sec_flags | SEC_AUTODETECT_REQ);
162static BOOL autodetect_send_rtt_measure_response(rdpAutoDetect* autodetect, UINT16 sequenceNumber)
164 UINT16 sec_flags = 0;
167 WINPR_ASSERT(autodetect);
168 WINPR_ASSERT(autodetect->context);
171 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
176 WLog_Print(autodetect->log, WLOG_TRACE,
177 "sending RTT Measure Response PDU (seqNumber=0x%" PRIx16
")", sequenceNumber);
178 Stream_Write_UINT8(s, 0x06);
179 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
180 Stream_Write_UINT16(s, sequenceNumber);
181 Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE);
182 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
183 sec_flags | SEC_AUTODETECT_RSP);
186static BOOL autodetect_send_bandwidth_measure_start(rdpAutoDetect* autodetect,
187 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
188 UINT16 sequenceNumber)
190 UINT16 requestType = 0;
191 UINT16 sec_flags = 0;
194 WINPR_ASSERT(autodetect);
195 WINPR_ASSERT(autodetect->context);
197 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
201 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
202 requestType = RDP_BW_START_REQUEST_TYPE_CONNECTTIME;
204 requestType = RDP_BW_START_REQUEST_TYPE_CONTINUOUS;
206 WLog_Print(autodetect->log, WLOG_TRACE,
207 "sending Bandwidth Measure Start PDU(seqNumber=%" PRIu16
")", sequenceNumber);
208 Stream_Write_UINT8(s, 0x06);
209 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
210 Stream_Write_UINT16(s, sequenceNumber);
211 Stream_Write_UINT16(s, requestType);
212 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
213 sec_flags | SEC_AUTODETECT_REQ);
217autodetect_send_bandwidth_measure_payload(rdpAutoDetect* autodetect,
218 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
219 UINT16 sequenceNumber, UINT16 payloadLength)
221 UINT16 sec_flags = 0;
224 WINPR_ASSERT(autodetect);
225 WINPR_ASSERT(autodetect->context);
227 WINPR_ASSERT(freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE);
229 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
233 WLog_Print(autodetect->log, WLOG_TRACE,
234 "sending Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16
"", payloadLength);
238 if (!Stream_EnsureRemainingCapacity(s, 8 + payloadLength))
240 WLog_Print(autodetect->log, WLOG_ERROR,
"Failed to ensure %lu bytes in stream",
241 8ul + payloadLength);
246 Stream_Write_UINT8(s, 0x08);
247 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
248 Stream_Write_UINT16(s, sequenceNumber);
249 Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE);
250 Stream_Write_UINT16(s, payloadLength);
252 if (winpr_RAND(Stream_Pointer(s), payloadLength) < 0)
257 Stream_Seek(s, payloadLength);
258 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
259 sec_flags | SEC_AUTODETECT_REQ);
262static BOOL autodetect_send_bandwidth_measure_stop(rdpAutoDetect* autodetect,
263 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
264 UINT16 sequenceNumber, UINT16 payloadLength)
266 UINT16 requestType = 0;
267 UINT16 sec_flags = 0;
270 WINPR_ASSERT(autodetect);
271 WINPR_ASSERT(autodetect->context);
273 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
277 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
278 requestType = RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME;
280 requestType = RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS;
282 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
285 WLog_Print(autodetect->log, WLOG_TRACE,
286 "sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
289 Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
292 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
293 Stream_Write_UINT16(s, sequenceNumber);
294 Stream_Write_UINT16(s, requestType);
296 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
298 Stream_Write_UINT16(s, payloadLength);
300 if (payloadLength > 0)
302 if (!Stream_EnsureRemainingCapacity(s, payloadLength))
304 WLog_Print(autodetect->log, WLOG_ERROR,
305 "Failed to ensure %" PRIu16
" bytes in stream", payloadLength);
311 if (winpr_RAND(Stream_Pointer(s), payloadLength) < 0)
316 Stream_Seek(s, payloadLength);
320 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
321 sec_flags | SEC_AUTODETECT_REQ);
324static BOOL autodetect_send_bandwidth_measure_results(rdpAutoDetect* autodetect,
325 RDP_TRANSPORT_TYPE transport,
326 UINT16 responseType, UINT16 sequenceNumber)
329 UINT16 sec_flags = 0;
330 UINT64 timeDelta = GetTickCount64();
332 WINPR_ASSERT(autodetect);
333 WINPR_ASSERT(autodetect->context);
336 if (autodetect->bandwidthMeasureStartTime > timeDelta)
338 WLog_Print(autodetect->log, WLOG_WARN,
339 "Invalid bandwidthMeasureStartTime %" PRIu64
" > current %" PRIu64
341 autodetect->bandwidthMeasureStartTime, timeDelta);
345 timeDelta -= autodetect->bandwidthMeasureStartTime;
348 wStream* s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
353 WLog_Print(autodetect->log, WLOG_TRACE,
354 "sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu64
", byteCount=%" PRIu32
356 timeDelta, autodetect->bandwidthMeasureByteCount);
358 Stream_Write_UINT8(s, 0x0E);
359 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
360 Stream_Write_UINT16(s, sequenceNumber);
361 Stream_Write_UINT16(s, responseType);
362 Stream_Write_UINT32(s, (UINT32)MIN(timeDelta, UINT32_MAX));
363 Stream_Write_UINT32(s, autodetect->bandwidthMeasureByteCount);
364 IFCALLRET(autodetect->ClientBandwidthMeasureResult, success, autodetect, transport,
365 responseType, sequenceNumber, (UINT32)MIN(timeDelta, UINT32_MAX),
366 autodetect->bandwidthMeasureByteCount);
370 WLog_Print(autodetect->log, WLOG_ERROR,
"ClientBandwidthMeasureResult failed");
375 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
376 sec_flags | SEC_AUTODETECT_RSP);
379static BOOL autodetect_send_netchar_result(rdpAutoDetect* autodetect,
380 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
381 UINT16 sequenceNumber,
382 const rdpNetworkCharacteristicsResult* result)
384 UINT16 sec_flags = 0;
387 WINPR_ASSERT(autodetect);
388 WINPR_ASSERT(autodetect->context);
390 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
395 WLog_Print(autodetect->log, WLOG_TRACE,
"sending Network Characteristics Result PDU");
397 switch (result->type)
399 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT:
400 Stream_Write_UINT8(s, 0x0E);
401 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
402 Stream_Write_UINT16(s, sequenceNumber);
403 WINPR_ASSERT((result->type <= UINT16_MAX));
404 WINPR_ASSERT((result->type >= 0));
405 Stream_Write_UINT16(s, (UINT16)result->type);
406 Stream_Write_UINT32(s, result->baseRTT);
407 Stream_Write_UINT32(s, result->averageRTT);
409 case RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT:
410 Stream_Write_UINT8(s, 0x0E);
411 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
412 Stream_Write_UINT16(s, sequenceNumber);
413 WINPR_ASSERT((result->type <= UINT16_MAX));
414 WINPR_ASSERT((result->type >= 0));
415 Stream_Write_UINT16(s, (UINT16)result->type);
416 Stream_Write_UINT32(s, result->bandwidth);
417 Stream_Write_UINT32(s, result->averageRTT);
419 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT:
420 Stream_Write_UINT8(s, 0x12);
421 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
422 Stream_Write_UINT16(s, sequenceNumber);
423 WINPR_ASSERT((result->type <= UINT16_MAX));
424 WINPR_ASSERT((result->type >= 0));
425 Stream_Write_UINT16(s, (UINT16)result->type);
426 Stream_Write_UINT32(s, result->baseRTT);
427 Stream_Write_UINT32(s, result->bandwidth);
428 Stream_Write_UINT32(s, result->averageRTT);
435 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
436 sec_flags | SEC_AUTODETECT_REQ);
439static FREERDP_AUTODETECT_STATE
440autodetect_on_connect_time_auto_detect_begin_default(rdpAutoDetect* autodetect)
442 WINPR_ASSERT(autodetect);
443 WINPR_ASSERT(autodetect->RTTMeasureRequest);
445 if (!autodetect->RTTMeasureRequest(autodetect, RDP_TRANSPORT_TCP, 0x23))
446 return FREERDP_AUTODETECT_STATE_FAIL;
448 return FREERDP_AUTODETECT_STATE_REQUEST;
451static FREERDP_AUTODETECT_STATE
452autodetect_on_connect_time_auto_detect_progress_default(rdpAutoDetect* autodetect)
454 WINPR_ASSERT(autodetect);
456 if (autodetect->state == FREERDP_AUTODETECT_STATE_RESPONSE ||
457 autodetect->state == FREERDP_AUTODETECT_STATE_COMPLETE)
458 return FREERDP_AUTODETECT_STATE_COMPLETE;
460 return autodetect->state;
463static BOOL autodetect_recv_rtt_measure_request(rdpAutoDetect* autodetect,
464 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
466 const AUTODETECT_REQ_PDU* autodetectReqPdu)
468 WINPR_ASSERT(autodetect);
470 WINPR_ASSERT(autodetectReqPdu);
472 if (autodetectReqPdu->headerLength != 0x06)
474 WLog_Print(autodetect->log, WLOG_ERROR,
475 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
476 autodetectReqPdu->headerLength);
480 WLog_Print(autodetect->log, WLOG_TRACE,
"received RTT Measure Request PDU");
482 return autodetect_send_rtt_measure_response(autodetect, autodetectReqPdu->sequenceNumber);
485static BOOL autodetect_recv_rtt_measure_response(rdpAutoDetect* autodetect,
486 RDP_TRANSPORT_TYPE transport,
488 const AUTODETECT_RSP_PDU* autodetectRspPdu)
492 WINPR_ASSERT(autodetect);
493 WINPR_ASSERT(autodetectRspPdu);
495 if (autodetectRspPdu->headerLength != 0x06)
497 WLog_Print(autodetect->log, WLOG_ERROR,
498 "autodetectRspPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
499 autodetectRspPdu->headerLength);
503 WLog_Print(autodetect->log, WLOG_TRACE,
"received RTT Measure Response PDU");
504 autodetect->netCharAverageRTT =
505 (UINT32)MIN(GetTickCount64() - autodetect->rttMeasureStartTime, UINT32_MAX);
507 if (autodetect->netCharBaseRTT == 0 ||
508 autodetect->netCharBaseRTT > autodetect->netCharAverageRTT)
509 autodetect->netCharBaseRTT = autodetect->netCharAverageRTT;
511 IFCALLRET(autodetect->RTTMeasureResponse, success, autodetect, transport,
512 autodetectRspPdu->sequenceNumber);
514 WLog_Print(autodetect->log, WLOG_WARN,
"RTTMeasureResponse failed");
518static BOOL autodetect_recv_bandwidth_measure_start(rdpAutoDetect* autodetect,
519 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
521 const AUTODETECT_REQ_PDU* autodetectReqPdu)
523 WINPR_ASSERT(autodetect);
525 WINPR_ASSERT(autodetectReqPdu);
527 if (autodetectReqPdu->headerLength != 0x06)
529 WLog_Print(autodetect->log, WLOG_ERROR,
530 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
531 autodetectReqPdu->headerLength);
535 WLog_Print(autodetect->log, WLOG_TRACE,
536 "received Bandwidth Measure Start PDU - time=%" PRIu64
"", GetTickCount64());
538 autodetect->bandwidthMeasureStartTime = GetTickCount64();
539 autodetect->bandwidthMeasureByteCount = 0;
542 if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
544 autodetect->bandwidthMeasureStarted = TRUE;
551autodetect_recv_bandwidth_measure_payload(rdpAutoDetect* autodetect,
552 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
553 wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
555 UINT16 payloadLength = 0;
557 WINPR_ASSERT(autodetect);
559 WINPR_ASSERT(autodetectReqPdu);
561 if (autodetectReqPdu->headerLength != 0x08)
563 WLog_Print(autodetect->log, WLOG_ERROR,
564 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
565 autodetectReqPdu->headerLength);
569 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
572 Stream_Read_UINT16(s, payloadLength);
573 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
575 Stream_Seek(s, payloadLength);
577 WLog_Print(autodetect->log, WLOG_DEBUG,
578 "received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16
"",
581 autodetect->bandwidthMeasureByteCount += payloadLength;
585static BOOL autodetect_recv_bandwidth_measure_stop(rdpAutoDetect* autodetect,
586 RDP_TRANSPORT_TYPE transport,
wStream* s,
587 const AUTODETECT_REQ_PDU* autodetectReqPdu)
589 UINT16 payloadLength = 0;
590 UINT16 responseType = 0;
592 WINPR_ASSERT(autodetect);
594 WINPR_ASSERT(autodetectReqPdu);
596 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
598 if (autodetectReqPdu->headerLength != 0x08)
600 WLog_Print(autodetect->log, WLOG_ERROR,
601 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
602 autodetectReqPdu->headerLength);
606 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
609 Stream_Read_UINT16(s, payloadLength);
613 if (autodetectReqPdu->headerLength != 0x06)
615 WLog_Print(autodetect->log, WLOG_ERROR,
616 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
617 autodetectReqPdu->headerLength);
624 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
626 Stream_Seek(s, payloadLength);
628 WLog_Print(autodetect->log, WLOG_TRACE,
629 "received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
631 autodetect->bandwidthMeasureByteCount += payloadLength;
634 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
636 autodetect->bandwidthMeasureStarted = FALSE;
640 responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
641 ? RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME
642 : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
643 return autodetect_send_bandwidth_measure_results(autodetect, transport, responseType,
644 autodetectReqPdu->sequenceNumber);
647static BOOL autodetect_recv_bandwidth_measure_results(rdpAutoDetect* autodetect,
648 RDP_TRANSPORT_TYPE transport,
wStream* s,
649 const AUTODETECT_RSP_PDU* autodetectRspPdu)
651 UINT32 timeDelta = 0;
652 UINT32 byteCount = 0;
655 WINPR_ASSERT(autodetect);
657 WINPR_ASSERT(autodetectRspPdu);
659 if (autodetectRspPdu->headerLength != 0x0E)
661 WLog_Print(autodetect->log, WLOG_ERROR,
662 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
663 autodetectRspPdu->headerLength);
667 WLog_Print(autodetect->log, WLOG_TRACE,
"received Bandwidth Measure Results PDU");
668 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
670 Stream_Read_UINT32(s, timeDelta);
671 Stream_Read_UINT32(s, byteCount);
673 IFCALLRET(autodetect->BandwidthMeasureResults, success, autodetect, transport,
674 autodetectRspPdu->sequenceNumber, autodetectRspPdu->responseType, timeDelta,
677 WLog_Print(autodetect->log, WLOG_WARN,
"BandwidthMeasureResults failed");
681static BOOL autodetect_recv_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
682 wStream* s,
const AUTODETECT_RSP_PDU* autodetectRspPdu)
684 UINT32 bandwidth = 0;
688 WINPR_ASSERT(autodetect);
690 WINPR_ASSERT(autodetectRspPdu);
692 if (autodetectRspPdu->headerLength != 0x0E)
694 WLog_Print(autodetect->log, WLOG_ERROR,
695 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
696 autodetectRspPdu->headerLength);
699 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
703 Stream_Read_UINT32(s, bandwidth);
704 Stream_Read_UINT32(s, rtt);
706 WLog_Print(autodetect->log, WLOG_TRACE,
707 "received Network Characteristics Sync PDU -> bandwidth=%" PRIu32
", rtt=%" PRIu32
711 IFCALLRET(autodetect->NetworkCharacteristicsSync, success, autodetect, transport,
712 autodetectRspPdu->sequenceNumber, bandwidth, rtt);
714 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsSync failed");
718static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
719 wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
721 rdpNetworkCharacteristicsResult result = {
722 .type = RDP_NETCHAR_RESERVED, .baseRTT = 0, .averageRTT = 0, .bandwidth = 0
726 WINPR_ASSERT(autodetect);
728 WINPR_ASSERT(autodetectReqPdu);
730 switch (autodetectReqPdu->requestType)
732 case RDP_NETCHAR_RESULTS_0x0840:
735 if (autodetectReqPdu->headerLength != 0x0E)
737 WLog_Print(autodetect->log, WLOG_ERROR,
738 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
739 autodetectReqPdu->headerLength);
742 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
745 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT;
746 Stream_Read_UINT32(s, result.baseRTT);
747 Stream_Read_UINT32(s, result.averageRTT);
750 case RDP_NETCHAR_RESULTS_0x0880:
753 if (autodetectReqPdu->headerLength != 0x0E)
755 WLog_Print(autodetect->log, WLOG_ERROR,
756 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
757 autodetectReqPdu->headerLength);
760 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
763 result.type = RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT;
764 Stream_Read_UINT32(s, result.bandwidth);
765 Stream_Read_UINT32(s, result.averageRTT);
768 case RDP_NETCHAR_RESULTS_0x08C0:
771 if (autodetectReqPdu->headerLength != 0x12)
773 WLog_Print(autodetect->log, WLOG_ERROR,
774 "autodetectReqPdu->headerLength != 0x012 [0x%02" PRIx8
"]",
775 autodetectReqPdu->headerLength);
778 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 12))
781 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT;
782 Stream_Read_UINT32(s, result.baseRTT);
783 Stream_Read_UINT32(s, result.bandwidth);
784 Stream_Read_UINT32(s, result.averageRTT);
792 WLog_Print(autodetect->log, WLOG_TRACE,
793 "received Network Characteristics Result PDU -> baseRTT=%" PRIu32
794 ", bandwidth=%" PRIu32
", averageRTT=%" PRIu32
"",
795 result.baseRTT, result.bandwidth, result.averageRTT);
797 IFCALLRET(autodetect->NetworkCharacteristicsResult, success, autodetect, transport,
798 autodetectReqPdu->sequenceNumber, &result);
800 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsResult failed");
804state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
807 AUTODETECT_REQ_PDU autodetectReqPdu = WINPR_C_ARRAY_INIT;
808 const rdpSettings* settings =
nullptr;
809 BOOL success = FALSE;
811 WINPR_ASSERT(autodetect);
812 WINPR_ASSERT(autodetect->context);
814 settings = autodetect->context->settings;
815 WINPR_ASSERT(settings);
817 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
818 return STATE_RUN_FAILED;
820 Stream_Read_UINT8(s, autodetectReqPdu.headerLength);
821 Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId);
822 Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber);
823 Stream_Read_UINT16(s, autodetectReqPdu.requestType);
825 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
827 char rbuffer[128] = WINPR_C_ARRAY_INIT;
828 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
829 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
831 char hbuffer[128] = WINPR_C_ARRAY_INIT;
832 const char* headerStr =
833 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
835 WLog_Print(autodetect->log, WLOG_TRACE,
836 "rdp_recv_autodetect_request_packet: headerLength=%" PRIu8
837 ", headerTypeId=%s, sequenceNumber=%" PRIu16
", requestType=%s",
838 autodetectReqPdu.headerLength, headerStr, autodetectReqPdu.sequenceNumber,
844 char rbuffer[128] = WINPR_C_ARRAY_INIT;
845 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
846 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
848 WLog_Print(autodetect->log, WLOG_WARN,
849 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
850 "message but support was not enabled",
855 if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
857 char rbuffer[128] = WINPR_C_ARRAY_INIT;
858 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
859 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
860 char hbuffer[128] = WINPR_C_ARRAY_INIT;
861 const char* headerStr =
862 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
864 WLog_Print(autodetect->log, WLOG_ERROR,
865 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
866 "message with invalid headerTypeId=%s",
867 requestTypeStr, headerStr);
871 if (!IFCALLRESULT(TRUE, autodetect->RequestReceived, autodetect, transport,
872 autodetectReqPdu.requestType, autodetectReqPdu.sequenceNumber))
875 switch (autodetectReqPdu.requestType)
877 case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
878 case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
881 autodetect_recv_rtt_measure_request(autodetect, transport, s, &autodetectReqPdu);
884 case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
885 case RDP_BW_START_REQUEST_TYPE_TUNNEL:
886 case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
888 success = autodetect_recv_bandwidth_measure_start(autodetect, transport, s,
892 case RDP_BW_PAYLOAD_REQUEST_TYPE:
894 success = autodetect_recv_bandwidth_measure_payload(autodetect, transport, s,
898 case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
899 case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
900 case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
903 autodetect_recv_bandwidth_measure_stop(autodetect, transport, s, &autodetectReqPdu);
906 case RDP_NETCHAR_RESULTS_0x0840:
907 case RDP_NETCHAR_RESULTS_0x0880:
908 case RDP_NETCHAR_RESULTS_0x08C0:
910 success = autodetect_recv_netchar_request(autodetect, transport, s, &autodetectReqPdu);
914 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown requestType=0x%04" PRIx16,
915 autodetectReqPdu.requestType);
921 autodetect->state = FREERDP_AUTODETECT_STATE_REQUEST;
923 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
924 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
927state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
930 AUTODETECT_RSP_PDU autodetectRspPdu = WINPR_C_ARRAY_INIT;
931 const rdpSettings* settings =
nullptr;
932 BOOL success = FALSE;
934 WINPR_ASSERT(autodetect);
935 WINPR_ASSERT(autodetect->context);
938 settings = autodetect->context->settings;
939 WINPR_ASSERT(settings);
941 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
944 Stream_Read_UINT8(s, autodetectRspPdu.headerLength);
945 Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId);
946 Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber);
947 Stream_Read_UINT16(s, autodetectRspPdu.responseType);
949 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
951 char rbuffer[128] = WINPR_C_ARRAY_INIT;
952 const char* requestStr = autodetect_request_type_to_string_buffer(
953 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
954 char hbuffer[128] = WINPR_C_ARRAY_INIT;
955 const char* headerStr =
956 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
958 WLog_Print(autodetect->log, WLOG_TRACE,
959 "rdp_recv_autodetect_response_packet: headerLength=%" PRIu8
", headerTypeId=%s"
960 ", sequenceNumber=%" PRIu16
", requestType=%s",
961 autodetectRspPdu.headerLength, headerStr, autodetectRspPdu.sequenceNumber,
967 char rbuffer[128] = WINPR_C_ARRAY_INIT;
969 const char* requestStr = autodetect_request_type_to_string_buffer(
970 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
972 WLog_Print(autodetect->log, WLOG_WARN,
973 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
974 "message but support was not enabled",
976 return STATE_RUN_FAILED;
979 if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
981 char rbuffer[128] = WINPR_C_ARRAY_INIT;
982 const char* requestStr = autodetect_request_type_to_string_buffer(
983 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
984 char hbuffer[128] = WINPR_C_ARRAY_INIT;
985 const char* headerStr =
986 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
987 WLog_Print(autodetect->log, WLOG_ERROR,
988 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
989 "message with invalid headerTypeId=%s",
990 requestStr, headerStr);
994 if (!IFCALLRESULT(TRUE, autodetect->ResponseReceived, autodetect, transport,
995 autodetectRspPdu.responseType, autodetectRspPdu.sequenceNumber))
998 switch (autodetectRspPdu.responseType)
1000 case RDP_RTT_RESPONSE_TYPE:
1003 autodetect_recv_rtt_measure_response(autodetect, transport, s, &autodetectRspPdu);
1006 case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
1007 case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
1009 success = autodetect_recv_bandwidth_measure_results(autodetect, transport, s,
1013 case RDP_NETCHAR_SYNC_RESPONSE_TYPE:
1015 success = autodetect_recv_netchar_sync(autodetect, transport, s, &autodetectRspPdu);
1019 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown responseType=0x%04" PRIx16,
1020 autodetectRspPdu.responseType);
1027 if (autodetectRspPdu.responseType == RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME)
1028 autodetect->state = FREERDP_AUTODETECT_STATE_COMPLETE;
1030 autodetect->state = FREERDP_AUTODETECT_STATE_RESPONSE;
1033 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
1035 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
1038void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect)
1040 WINPR_ASSERT(autodetect);
1041 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectBegin);
1043 autodetect->state = autodetect->OnConnectTimeAutoDetectBegin(autodetect);
1046void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect)
1048 WINPR_ASSERT(autodetect);
1049 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectProgress);
1051 autodetect->state = autodetect->OnConnectTimeAutoDetectProgress(autodetect);
1054rdpAutoDetect* autodetect_new(rdpContext* context)
1056 rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1,
sizeof(rdpAutoDetect));
1059 autoDetect->context = context;
1060 autoDetect->log = WLog_Get(AUTODETECT_TAG);
1065void autodetect_free(rdpAutoDetect* autoDetect)
1070void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
1072 WINPR_ASSERT(autodetect);
1074 autodetect->RTTMeasureRequest = autodetect_send_rtt_measure_request;
1075 autodetect->BandwidthMeasureStart = autodetect_send_bandwidth_measure_start;
1076 autodetect->BandwidthMeasurePayload = autodetect_send_bandwidth_measure_payload;
1077 autodetect->BandwidthMeasureStop = autodetect_send_bandwidth_measure_stop;
1078 autodetect->NetworkCharacteristicsResult = autodetect_send_netchar_result;
1084 autodetect->OnConnectTimeAutoDetectBegin = autodetect_on_connect_time_auto_detect_begin_default;
1085 autodetect->OnConnectTimeAutoDetectProgress =
1086 autodetect_on_connect_time_auto_detect_progress_default;
1089FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect)
1091 WINPR_ASSERT(autodetect);
1092 return autodetect->state;
1095rdpAutoDetect* autodetect_get(rdpContext* context)
1097 WINPR_ASSERT(context);
1098 WINPR_ASSERT(context->rdp);
1099 return context->rdp->autodetect;
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.