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 = NULL;
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 %" PRIuz
" bytes in stream",
241 8ull + 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 winpr_RAND(Stream_Pointer(s), payloadLength);
253 Stream_Seek(s, payloadLength);
254 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
255 sec_flags | SEC_AUTODETECT_REQ);
258static BOOL autodetect_send_bandwidth_measure_stop(rdpAutoDetect* autodetect,
259 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
260 UINT16 sequenceNumber, UINT16 payloadLength)
262 UINT16 requestType = 0;
263 UINT16 sec_flags = 0;
266 WINPR_ASSERT(autodetect);
267 WINPR_ASSERT(autodetect->context);
269 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
273 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
274 requestType = RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME;
276 requestType = RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS;
278 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
281 WLog_Print(autodetect->log, WLOG_TRACE,
282 "sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
285 Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
288 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
289 Stream_Write_UINT16(s, sequenceNumber);
290 Stream_Write_UINT16(s, requestType);
292 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
294 Stream_Write_UINT16(s, payloadLength);
296 if (payloadLength > 0)
298 if (!Stream_EnsureRemainingCapacity(s, payloadLength))
300 WLog_Print(autodetect->log, WLOG_ERROR,
301 "Failed to ensure %" PRIuz
" bytes in stream", payloadLength);
307 winpr_RAND(Stream_Pointer(s), payloadLength);
308 Stream_Seek(s, payloadLength);
312 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
313 sec_flags | SEC_AUTODETECT_REQ);
316static BOOL autodetect_send_bandwidth_measure_results(rdpAutoDetect* autodetect,
317 RDP_TRANSPORT_TYPE transport,
318 UINT16 responseType, UINT16 sequenceNumber)
321 UINT16 sec_flags = 0;
322 UINT64 timeDelta = GetTickCount64();
324 WINPR_ASSERT(autodetect);
325 WINPR_ASSERT(autodetect->context);
328 if (autodetect->bandwidthMeasureStartTime > timeDelta)
330 WLog_Print(autodetect->log, WLOG_WARN,
331 "Invalid bandwidthMeasureStartTime %" PRIu64
" > current %" PRIu64
333 autodetect->bandwidthMeasureStartTime, timeDelta);
337 timeDelta -= autodetect->bandwidthMeasureStartTime;
340 wStream* s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
345 WLog_Print(autodetect->log, WLOG_TRACE,
346 "sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu64
", byteCount=%" PRIu32
348 timeDelta, autodetect->bandwidthMeasureByteCount);
350 Stream_Write_UINT8(s, 0x0E);
351 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
352 Stream_Write_UINT16(s, sequenceNumber);
353 Stream_Write_UINT16(s, responseType);
354 Stream_Write_UINT32(s, (UINT32)MIN(timeDelta, UINT32_MAX));
355 Stream_Write_UINT32(s, autodetect->bandwidthMeasureByteCount);
356 IFCALLRET(autodetect->ClientBandwidthMeasureResult, success, autodetect, transport,
357 responseType, sequenceNumber, (UINT32)MIN(timeDelta, UINT32_MAX),
358 autodetect->bandwidthMeasureByteCount);
362 WLog_Print(autodetect->log, WLOG_ERROR,
"ClientBandwidthMeasureResult failed");
367 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
368 sec_flags | SEC_AUTODETECT_RSP);
371static BOOL autodetect_send_netchar_result(rdpAutoDetect* autodetect,
372 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
373 UINT16 sequenceNumber,
374 const rdpNetworkCharacteristicsResult* result)
376 UINT16 sec_flags = 0;
379 WINPR_ASSERT(autodetect);
380 WINPR_ASSERT(autodetect->context);
382 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
387 WLog_Print(autodetect->log, WLOG_TRACE,
"sending Network Characteristics Result PDU");
389 switch (result->type)
391 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT:
392 Stream_Write_UINT8(s, 0x0E);
393 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
394 Stream_Write_UINT16(s, sequenceNumber);
395 WINPR_ASSERT((result->type <= UINT16_MAX));
396 WINPR_ASSERT((result->type >= 0));
397 Stream_Write_UINT16(s, (UINT16)result->type);
398 Stream_Write_UINT32(s, result->baseRTT);
399 Stream_Write_UINT32(s, result->averageRTT);
401 case RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT:
402 Stream_Write_UINT8(s, 0x0E);
403 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
404 Stream_Write_UINT16(s, sequenceNumber);
405 WINPR_ASSERT((result->type <= UINT16_MAX));
406 WINPR_ASSERT((result->type >= 0));
407 Stream_Write_UINT16(s, (UINT16)result->type);
408 Stream_Write_UINT32(s, result->bandwidth);
409 Stream_Write_UINT32(s, result->averageRTT);
411 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT:
412 Stream_Write_UINT8(s, 0x12);
413 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
414 Stream_Write_UINT16(s, sequenceNumber);
415 WINPR_ASSERT((result->type <= UINT16_MAX));
416 WINPR_ASSERT((result->type >= 0));
417 Stream_Write_UINT16(s, (UINT16)result->type);
418 Stream_Write_UINT32(s, result->baseRTT);
419 Stream_Write_UINT32(s, result->bandwidth);
420 Stream_Write_UINT32(s, result->averageRTT);
427 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
428 sec_flags | SEC_AUTODETECT_REQ);
431static FREERDP_AUTODETECT_STATE
432autodetect_on_connect_time_auto_detect_begin_default(rdpAutoDetect* autodetect)
434 WINPR_ASSERT(autodetect);
435 WINPR_ASSERT(autodetect->RTTMeasureRequest);
437 if (!autodetect->RTTMeasureRequest(autodetect, RDP_TRANSPORT_TCP, 0x23))
438 return FREERDP_AUTODETECT_STATE_FAIL;
440 return FREERDP_AUTODETECT_STATE_REQUEST;
443static FREERDP_AUTODETECT_STATE
444autodetect_on_connect_time_auto_detect_progress_default(rdpAutoDetect* autodetect)
446 WINPR_ASSERT(autodetect);
448 if (autodetect->state == FREERDP_AUTODETECT_STATE_RESPONSE ||
449 autodetect->state == FREERDP_AUTODETECT_STATE_COMPLETE)
450 return FREERDP_AUTODETECT_STATE_COMPLETE;
452 return autodetect->state;
455static BOOL autodetect_recv_rtt_measure_request(rdpAutoDetect* autodetect,
456 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
458 const AUTODETECT_REQ_PDU* autodetectReqPdu)
460 WINPR_ASSERT(autodetect);
462 WINPR_ASSERT(autodetectReqPdu);
464 if (autodetectReqPdu->headerLength != 0x06)
466 WLog_Print(autodetect->log, WLOG_ERROR,
467 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
468 autodetectReqPdu->headerLength);
472 WLog_Print(autodetect->log, WLOG_TRACE,
"received RTT Measure Request PDU");
474 return autodetect_send_rtt_measure_response(autodetect, autodetectReqPdu->sequenceNumber);
477static BOOL autodetect_recv_rtt_measure_response(rdpAutoDetect* autodetect,
478 RDP_TRANSPORT_TYPE transport,
480 const AUTODETECT_RSP_PDU* autodetectRspPdu)
484 WINPR_ASSERT(autodetect);
485 WINPR_ASSERT(autodetectRspPdu);
487 if (autodetectRspPdu->headerLength != 0x06)
489 WLog_Print(autodetect->log, WLOG_ERROR,
490 "autodetectRspPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
491 autodetectRspPdu->headerLength);
495 WLog_Print(autodetect->log, WLOG_TRACE,
"received RTT Measure Response PDU");
496 autodetect->netCharAverageRTT =
497 (UINT32)MIN(GetTickCount64() - autodetect->rttMeasureStartTime, UINT32_MAX);
499 if (autodetect->netCharBaseRTT == 0 ||
500 autodetect->netCharBaseRTT > autodetect->netCharAverageRTT)
501 autodetect->netCharBaseRTT = autodetect->netCharAverageRTT;
503 IFCALLRET(autodetect->RTTMeasureResponse, success, autodetect, transport,
504 autodetectRspPdu->sequenceNumber);
506 WLog_Print(autodetect->log, WLOG_WARN,
"RTTMeasureResponse failed");
510static BOOL autodetect_recv_bandwidth_measure_start(rdpAutoDetect* autodetect,
511 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
513 const AUTODETECT_REQ_PDU* autodetectReqPdu)
515 WINPR_ASSERT(autodetect);
517 WINPR_ASSERT(autodetectReqPdu);
519 if (autodetectReqPdu->headerLength != 0x06)
521 WLog_Print(autodetect->log, WLOG_ERROR,
522 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
523 autodetectReqPdu->headerLength);
527 WLog_Print(autodetect->log, WLOG_TRACE,
528 "received Bandwidth Measure Start PDU - time=%" PRIu64
"", GetTickCount64());
530 autodetect->bandwidthMeasureStartTime = GetTickCount64();
531 autodetect->bandwidthMeasureByteCount = 0;
534 if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
536 autodetect->bandwidthMeasureStarted = TRUE;
543autodetect_recv_bandwidth_measure_payload(rdpAutoDetect* autodetect,
544 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
545 wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
547 UINT16 payloadLength = 0;
549 WINPR_ASSERT(autodetect);
551 WINPR_ASSERT(autodetectReqPdu);
553 if (autodetectReqPdu->headerLength != 0x08)
555 WLog_Print(autodetect->log, WLOG_ERROR,
556 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
557 autodetectReqPdu->headerLength);
561 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
564 Stream_Read_UINT16(s, payloadLength);
565 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
567 Stream_Seek(s, payloadLength);
569 WLog_Print(autodetect->log, WLOG_DEBUG,
570 "received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16
"",
573 autodetect->bandwidthMeasureByteCount += payloadLength;
577static BOOL autodetect_recv_bandwidth_measure_stop(rdpAutoDetect* autodetect,
578 RDP_TRANSPORT_TYPE transport,
wStream* s,
579 const AUTODETECT_REQ_PDU* autodetectReqPdu)
581 UINT16 payloadLength = 0;
582 UINT16 responseType = 0;
584 WINPR_ASSERT(autodetect);
586 WINPR_ASSERT(autodetectReqPdu);
588 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
590 if (autodetectReqPdu->headerLength != 0x08)
592 WLog_Print(autodetect->log, WLOG_ERROR,
593 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
594 autodetectReqPdu->headerLength);
598 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
601 Stream_Read_UINT16(s, payloadLength);
605 if (autodetectReqPdu->headerLength != 0x06)
607 WLog_Print(autodetect->log, WLOG_ERROR,
608 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
609 autodetectReqPdu->headerLength);
616 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
618 Stream_Seek(s, payloadLength);
620 WLog_Print(autodetect->log, WLOG_TRACE,
621 "received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
623 autodetect->bandwidthMeasureByteCount += payloadLength;
626 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
628 autodetect->bandwidthMeasureStarted = FALSE;
632 responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
633 ? RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME
634 : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
635 return autodetect_send_bandwidth_measure_results(autodetect, transport, responseType,
636 autodetectReqPdu->sequenceNumber);
639static BOOL autodetect_recv_bandwidth_measure_results(rdpAutoDetect* autodetect,
640 RDP_TRANSPORT_TYPE transport,
wStream* s,
641 const AUTODETECT_RSP_PDU* autodetectRspPdu)
643 UINT32 timeDelta = 0;
644 UINT32 byteCount = 0;
647 WINPR_ASSERT(autodetect);
649 WINPR_ASSERT(autodetectRspPdu);
651 if (autodetectRspPdu->headerLength != 0x0E)
653 WLog_Print(autodetect->log, WLOG_ERROR,
654 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
655 autodetectRspPdu->headerLength);
659 WLog_Print(autodetect->log, WLOG_TRACE,
"received Bandwidth Measure Results PDU");
660 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
662 Stream_Read_UINT32(s, timeDelta);
663 Stream_Read_UINT32(s, byteCount);
665 IFCALLRET(autodetect->BandwidthMeasureResults, success, autodetect, transport,
666 autodetectRspPdu->sequenceNumber, autodetectRspPdu->responseType, timeDelta,
669 WLog_Print(autodetect->log, WLOG_WARN,
"BandwidthMeasureResults failed");
673static BOOL autodetect_recv_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
674 wStream* s,
const AUTODETECT_RSP_PDU* autodetectRspPdu)
676 UINT32 bandwidth = 0;
680 WINPR_ASSERT(autodetect);
682 WINPR_ASSERT(autodetectRspPdu);
684 if (autodetectRspPdu->headerLength != 0x0E)
686 WLog_Print(autodetect->log, WLOG_ERROR,
687 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
688 autodetectRspPdu->headerLength);
691 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
695 Stream_Read_UINT32(s, bandwidth);
696 Stream_Read_UINT32(s, rtt);
698 WLog_Print(autodetect->log, WLOG_TRACE,
699 "received Network Characteristics Sync PDU -> bandwidth=%" PRIu32
", rtt=%" PRIu32
703 IFCALLRET(autodetect->NetworkCharacteristicsSync, success, autodetect, transport,
704 autodetectRspPdu->sequenceNumber, bandwidth, rtt);
706 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsSync failed");
710static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
711 wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
713 rdpNetworkCharacteristicsResult result = { 0 };
716 WINPR_ASSERT(autodetect);
718 WINPR_ASSERT(autodetectReqPdu);
720 switch (autodetectReqPdu->requestType)
722 case RDP_NETCHAR_RESULTS_0x0840:
725 if (autodetectReqPdu->headerLength != 0x0E)
727 WLog_Print(autodetect->log, WLOG_ERROR,
728 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
729 autodetectReqPdu->headerLength);
732 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
735 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT;
736 Stream_Read_UINT32(s, result.baseRTT);
737 Stream_Read_UINT32(s, result.averageRTT);
740 case RDP_NETCHAR_RESULTS_0x0880:
743 if (autodetectReqPdu->headerLength != 0x0E)
745 WLog_Print(autodetect->log, WLOG_ERROR,
746 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
747 autodetectReqPdu->headerLength);
750 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
753 result.type = RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT;
754 Stream_Read_UINT32(s, result.bandwidth);
755 Stream_Read_UINT32(s, result.averageRTT);
758 case RDP_NETCHAR_RESULTS_0x08C0:
761 if (autodetectReqPdu->headerLength != 0x12)
763 WLog_Print(autodetect->log, WLOG_ERROR,
764 "autodetectReqPdu->headerLength != 0x012 [0x%02" PRIx8
"]",
765 autodetectReqPdu->headerLength);
768 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 12))
771 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT;
772 Stream_Read_UINT32(s, result.baseRTT);
773 Stream_Read_UINT32(s, result.bandwidth);
774 Stream_Read_UINT32(s, result.averageRTT);
782 WLog_Print(autodetect->log, WLOG_TRACE,
783 "received Network Characteristics Result PDU -> baseRTT=%" PRIu32
784 ", bandwidth=%" PRIu32
", averageRTT=%" PRIu32
"",
785 result.baseRTT, result.bandwidth, result.averageRTT);
787 IFCALLRET(autodetect->NetworkCharacteristicsResult, success, autodetect, transport,
788 autodetectReqPdu->sequenceNumber, &result);
790 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsResult failed");
794state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
797 AUTODETECT_REQ_PDU autodetectReqPdu = { 0 };
798 const rdpSettings* settings = NULL;
799 BOOL success = FALSE;
801 WINPR_ASSERT(autodetect);
802 WINPR_ASSERT(autodetect->context);
804 settings = autodetect->context->settings;
805 WINPR_ASSERT(settings);
807 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
808 return STATE_RUN_FAILED;
810 Stream_Read_UINT8(s, autodetectReqPdu.headerLength);
811 Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId);
812 Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber);
813 Stream_Read_UINT16(s, autodetectReqPdu.requestType);
815 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
817 char rbuffer[128] = { 0 };
818 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
819 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
821 char hbuffer[128] = { 0 };
822 const char* headerStr =
823 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
825 WLog_Print(autodetect->log, WLOG_TRACE,
826 "rdp_recv_autodetect_request_packet: headerLength=%" PRIu8
827 ", headerTypeId=%s, sequenceNumber=%" PRIu16
", requestType=%s",
828 autodetectReqPdu.headerLength, headerStr, autodetectReqPdu.sequenceNumber,
834 char rbuffer[128] = { 0 };
835 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
836 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
838 WLog_Print(autodetect->log, WLOG_WARN,
839 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
840 "message but support was not enabled",
845 if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
847 char rbuffer[128] = { 0 };
848 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
849 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
850 char hbuffer[128] = { 0 };
851 const char* headerStr =
852 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
854 WLog_Print(autodetect->log, WLOG_ERROR,
855 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
856 "message with invalid headerTypeId=%s",
857 requestTypeStr, headerStr);
861 IFCALL(autodetect->RequestReceived, autodetect, transport, autodetectReqPdu.requestType,
862 autodetectReqPdu.sequenceNumber);
863 switch (autodetectReqPdu.requestType)
865 case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
866 case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
869 autodetect_recv_rtt_measure_request(autodetect, transport, s, &autodetectReqPdu);
872 case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
873 case RDP_BW_START_REQUEST_TYPE_TUNNEL:
874 case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
876 success = autodetect_recv_bandwidth_measure_start(autodetect, transport, s,
880 case RDP_BW_PAYLOAD_REQUEST_TYPE:
882 success = autodetect_recv_bandwidth_measure_payload(autodetect, transport, s,
886 case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
887 case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
888 case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
891 autodetect_recv_bandwidth_measure_stop(autodetect, transport, s, &autodetectReqPdu);
894 case RDP_NETCHAR_RESULTS_0x0840:
895 case RDP_NETCHAR_RESULTS_0x0880:
896 case RDP_NETCHAR_RESULTS_0x08C0:
898 success = autodetect_recv_netchar_request(autodetect, transport, s, &autodetectReqPdu);
902 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown requestType=0x%04" PRIx16,
903 autodetectReqPdu.requestType);
909 autodetect->state = FREERDP_AUTODETECT_STATE_REQUEST;
911 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
912 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
915state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
918 AUTODETECT_RSP_PDU autodetectRspPdu = { 0 };
919 const rdpSettings* settings = NULL;
920 BOOL success = FALSE;
922 WINPR_ASSERT(autodetect);
923 WINPR_ASSERT(autodetect->context);
926 settings = autodetect->context->settings;
927 WINPR_ASSERT(settings);
929 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
932 Stream_Read_UINT8(s, autodetectRspPdu.headerLength);
933 Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId);
934 Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber);
935 Stream_Read_UINT16(s, autodetectRspPdu.responseType);
937 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
939 char rbuffer[128] = { 0 };
940 const char* requestStr = autodetect_request_type_to_string_buffer(
941 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
942 char hbuffer[128] = { 0 };
943 const char* headerStr =
944 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
946 WLog_Print(autodetect->log, WLOG_TRACE,
947 "rdp_recv_autodetect_response_packet: headerLength=%" PRIu8
", headerTypeId=%s"
948 ", sequenceNumber=%" PRIu16
", requestType=%s",
949 autodetectRspPdu.headerLength, headerStr, autodetectRspPdu.sequenceNumber,
955 char rbuffer[128] = { 0 };
957 const char* requestStr = autodetect_request_type_to_string_buffer(
958 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
960 WLog_Print(autodetect->log, WLOG_WARN,
961 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
962 "message but support was not enabled",
964 return STATE_RUN_FAILED;
967 if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
969 char rbuffer[128] = { 0 };
970 const char* requestStr = autodetect_request_type_to_string_buffer(
971 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
972 char hbuffer[128] = { 0 };
973 const char* headerStr =
974 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
975 WLog_Print(autodetect->log, WLOG_ERROR,
976 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
977 "message with invalid headerTypeId=%s",
978 requestStr, headerStr);
982 IFCALL(autodetect->ResponseReceived, autodetect, transport, autodetectRspPdu.responseType,
983 autodetectRspPdu.sequenceNumber);
984 switch (autodetectRspPdu.responseType)
986 case RDP_RTT_RESPONSE_TYPE:
989 autodetect_recv_rtt_measure_response(autodetect, transport, s, &autodetectRspPdu);
992 case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
993 case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
995 success = autodetect_recv_bandwidth_measure_results(autodetect, transport, s,
999 case RDP_NETCHAR_SYNC_RESPONSE_TYPE:
1001 success = autodetect_recv_netchar_sync(autodetect, transport, s, &autodetectRspPdu);
1005 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown responseType=0x%04" PRIx16,
1006 autodetectRspPdu.responseType);
1013 if (autodetectRspPdu.responseType == RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME)
1014 autodetect->state = FREERDP_AUTODETECT_STATE_COMPLETE;
1016 autodetect->state = FREERDP_AUTODETECT_STATE_RESPONSE;
1019 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
1021 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
1024void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect)
1026 WINPR_ASSERT(autodetect);
1027 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectBegin);
1029 autodetect->state = autodetect->OnConnectTimeAutoDetectBegin(autodetect);
1032void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect)
1034 WINPR_ASSERT(autodetect);
1035 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectProgress);
1037 autodetect->state = autodetect->OnConnectTimeAutoDetectProgress(autodetect);
1040rdpAutoDetect* autodetect_new(rdpContext* context)
1042 rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1,
sizeof(rdpAutoDetect));
1045 autoDetect->context = context;
1046 autoDetect->log = WLog_Get(AUTODETECT_TAG);
1051void autodetect_free(rdpAutoDetect* autoDetect)
1056void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
1058 WINPR_ASSERT(autodetect);
1060 autodetect->RTTMeasureRequest = autodetect_send_rtt_measure_request;
1061 autodetect->BandwidthMeasureStart = autodetect_send_bandwidth_measure_start;
1062 autodetect->BandwidthMeasurePayload = autodetect_send_bandwidth_measure_payload;
1063 autodetect->BandwidthMeasureStop = autodetect_send_bandwidth_measure_stop;
1064 autodetect->NetworkCharacteristicsResult = autodetect_send_netchar_result;
1070 autodetect->OnConnectTimeAutoDetectBegin = autodetect_on_connect_time_auto_detect_begin_default;
1071 autodetect->OnConnectTimeAutoDetectProgress =
1072 autodetect_on_connect_time_auto_detect_progress_default;
1075FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect)
1077 WINPR_ASSERT(autodetect);
1078 return autodetect->state;
1081rdpAutoDetect* autodetect_get(rdpContext* context)
1083 WINPR_ASSERT(context);
1084 WINPR_ASSERT(context->rdp);
1085 return context->rdp->autodetect;
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.