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;
65 static 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);
85 static 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";
124 static 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);
132 static BOOL autodetect_send_rtt_measure_request(rdpAutoDetect* autodetect,
133 RDP_TRANSPORT_TYPE transport, UINT16 sequenceNumber)
135 UINT16 requestType = 0;
138 WINPR_ASSERT(autodetect);
139 WINPR_ASSERT(autodetect->context);
141 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
145 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
146 requestType = RDP_RTT_REQUEST_TYPE_CONNECTTIME;
148 requestType = RDP_RTT_REQUEST_TYPE_CONTINUOUS;
150 WLog_Print(autodetect->log, WLOG_TRACE,
"sending RTT Measure Request PDU");
151 Stream_Write_UINT8(s, 0x06);
152 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
153 Stream_Write_UINT16(s, sequenceNumber);
154 Stream_Write_UINT16(s, requestType);
155 autodetect->rttMeasureStartTime = GetTickCount64();
156 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
159 static BOOL autodetect_send_rtt_measure_response(rdpAutoDetect* autodetect, UINT16 sequenceNumber)
163 WINPR_ASSERT(autodetect);
164 WINPR_ASSERT(autodetect->context);
167 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
172 WLog_Print(autodetect->log, WLOG_TRACE,
173 "sending RTT Measure Response PDU (seqNumber=0x%" PRIx16
")", sequenceNumber);
174 Stream_Write_UINT8(s, 0x06);
175 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
176 Stream_Write_UINT16(s, sequenceNumber);
177 Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE);
178 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
181 static BOOL autodetect_send_bandwidth_measure_start(rdpAutoDetect* autodetect,
182 RDP_TRANSPORT_TYPE transport,
183 UINT16 sequenceNumber)
185 UINT16 requestType = 0;
188 WINPR_ASSERT(autodetect);
189 WINPR_ASSERT(autodetect->context);
191 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
195 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
196 requestType = RDP_BW_START_REQUEST_TYPE_CONNECTTIME;
198 requestType = RDP_BW_START_REQUEST_TYPE_CONTINUOUS;
200 WLog_Print(autodetect->log, WLOG_TRACE,
201 "sending Bandwidth Measure Start PDU(seqNumber=%" PRIu16
")", sequenceNumber);
202 Stream_Write_UINT8(s, 0x06);
203 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
204 Stream_Write_UINT16(s, sequenceNumber);
205 Stream_Write_UINT16(s, requestType);
206 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
209 static BOOL autodetect_send_bandwidth_measure_payload(rdpAutoDetect* autodetect,
210 RDP_TRANSPORT_TYPE transport,
211 UINT16 sequenceNumber, UINT16 payloadLength)
215 WINPR_ASSERT(autodetect);
216 WINPR_ASSERT(autodetect->context);
218 WINPR_ASSERT(freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE);
220 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
224 WLog_Print(autodetect->log, WLOG_TRACE,
225 "sending Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16
"", payloadLength);
229 if (!Stream_EnsureRemainingCapacity(s, 8 + payloadLength))
231 WLog_Print(autodetect->log, WLOG_ERROR,
"Failed to ensure %" PRIuz
" bytes in stream",
232 8ull + payloadLength);
237 Stream_Write_UINT8(s, 0x08);
238 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
239 Stream_Write_UINT16(s, sequenceNumber);
240 Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE);
241 Stream_Write_UINT16(s, payloadLength);
243 winpr_RAND(Stream_Pointer(s), payloadLength);
244 Stream_Seek(s, payloadLength);
245 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
248 static BOOL autodetect_send_bandwidth_measure_stop(rdpAutoDetect* autodetect,
249 RDP_TRANSPORT_TYPE transport,
250 UINT16 sequenceNumber, UINT16 payloadLength)
252 UINT16 requestType = 0;
255 WINPR_ASSERT(autodetect);
256 WINPR_ASSERT(autodetect->context);
258 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
262 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
263 requestType = RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME;
265 requestType = RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS;
267 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
270 WLog_Print(autodetect->log, WLOG_TRACE,
271 "sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
274 Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
277 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
278 Stream_Write_UINT16(s, sequenceNumber);
279 Stream_Write_UINT16(s, requestType);
281 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
283 Stream_Write_UINT16(s, payloadLength);
285 if (payloadLength > 0)
287 if (!Stream_EnsureRemainingCapacity(s, payloadLength))
289 WLog_Print(autodetect->log, WLOG_ERROR,
290 "Failed to ensure %" PRIuz
" bytes in stream", payloadLength);
296 winpr_RAND(Stream_Pointer(s), payloadLength);
297 Stream_Seek(s, payloadLength);
301 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
304 static BOOL autodetect_send_bandwidth_measure_results(rdpAutoDetect* autodetect,
305 RDP_TRANSPORT_TYPE transport,
306 UINT16 responseType, UINT16 sequenceNumber)
310 UINT64 timeDelta = GetTickCount64();
312 WINPR_ASSERT(autodetect);
313 WINPR_ASSERT(autodetect->context);
316 if (autodetect->bandwidthMeasureStartTime > timeDelta)
318 WLog_Print(autodetect->log, WLOG_WARN,
319 "Invalid bandwidthMeasureStartTime %" PRIu64
" > current %" PRIu64
321 autodetect->bandwidthMeasureStartTime, timeDelta);
325 timeDelta -= autodetect->bandwidthMeasureStartTime;
328 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
333 WLog_Print(autodetect->log, WLOG_TRACE,
334 "sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu64
", byteCount=%" PRIu32
336 timeDelta, autodetect->bandwidthMeasureByteCount);
338 Stream_Write_UINT8(s, 0x0E);
339 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
340 Stream_Write_UINT16(s, sequenceNumber);
341 Stream_Write_UINT16(s, responseType);
342 Stream_Write_UINT32(s, (UINT32)MIN(timeDelta, UINT32_MAX));
343 Stream_Write_UINT32(s, autodetect->bandwidthMeasureByteCount);
344 IFCALLRET(autodetect->ClientBandwidthMeasureResult, success, autodetect, transport,
345 responseType, sequenceNumber, (UINT32)MIN(timeDelta, UINT32_MAX),
346 autodetect->bandwidthMeasureByteCount);
350 WLog_Print(autodetect->log, WLOG_ERROR,
"ClientBandwidthMeasureResult failed");
354 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
357 static BOOL autodetect_send_netchar_result(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
358 UINT16 sequenceNumber,
359 const rdpNetworkCharacteristicsResult* result)
363 WINPR_ASSERT(autodetect);
364 WINPR_ASSERT(autodetect->context);
366 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
371 WLog_Print(autodetect->log, WLOG_TRACE,
"sending Network Characteristics Result PDU");
373 switch (result->type)
375 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT:
376 Stream_Write_UINT8(s, 0x0E);
377 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
378 Stream_Write_UINT16(s, sequenceNumber);
379 WINPR_ASSERT((result->type <= UINT16_MAX));
380 WINPR_ASSERT((result->type >= 0));
381 Stream_Write_UINT16(s, (UINT16)result->type);
382 Stream_Write_UINT32(s, result->baseRTT);
383 Stream_Write_UINT32(s, result->averageRTT);
385 case RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT:
386 Stream_Write_UINT8(s, 0x0E);
387 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
388 Stream_Write_UINT16(s, sequenceNumber);
389 WINPR_ASSERT((result->type <= UINT16_MAX));
390 WINPR_ASSERT((result->type >= 0));
391 Stream_Write_UINT16(s, (UINT16)result->type);
392 Stream_Write_UINT32(s, result->bandwidth);
393 Stream_Write_UINT32(s, result->averageRTT);
395 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT:
396 Stream_Write_UINT8(s, 0x12);
397 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);
398 Stream_Write_UINT16(s, sequenceNumber);
399 WINPR_ASSERT((result->type <= UINT16_MAX));
400 WINPR_ASSERT((result->type >= 0));
401 Stream_Write_UINT16(s, (UINT16)result->type);
402 Stream_Write_UINT32(s, result->baseRTT);
403 Stream_Write_UINT32(s, result->bandwidth);
404 Stream_Write_UINT32(s, result->averageRTT);
411 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
414 static FREERDP_AUTODETECT_STATE
415 autodetect_on_connect_time_auto_detect_begin_default(rdpAutoDetect* autodetect)
417 WINPR_ASSERT(autodetect);
418 WINPR_ASSERT(autodetect->RTTMeasureRequest);
420 if (!autodetect->RTTMeasureRequest(autodetect, RDP_TRANSPORT_TCP, 0x23))
421 return FREERDP_AUTODETECT_STATE_FAIL;
423 return FREERDP_AUTODETECT_STATE_REQUEST;
426 static FREERDP_AUTODETECT_STATE
427 autodetect_on_connect_time_auto_detect_progress_default(rdpAutoDetect* autodetect)
429 WINPR_ASSERT(autodetect);
431 if (autodetect->state == FREERDP_AUTODETECT_STATE_RESPONSE ||
432 autodetect->state == FREERDP_AUTODETECT_STATE_COMPLETE)
433 return FREERDP_AUTODETECT_STATE_COMPLETE;
435 return autodetect->state;
438 static BOOL autodetect_send_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
439 UINT16 sequenceNumber)
443 WINPR_ASSERT(autodetect);
444 WINPR_ASSERT(autodetect->context);
445 WINPR_ASSERT(autodetect->context->rdp);
448 s = rdp_message_channel_pdu_init(autodetect->context->rdp);
453 WLog_Print(autodetect->log, WLOG_TRACE,
454 "sending Network Characteristics Sync PDU -> bandwidth=%" PRIu32
", rtt=%" PRIu32
"",
455 autodetect->netCharBandwidth, autodetect->netCharAverageRTT);
456 Stream_Write_UINT8(s, 0x0E);
457 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);
458 Stream_Write_UINT16(s, sequenceNumber);
459 Stream_Write_UINT16(s, RDP_NETCHAR_SYNC_RESPONSE_TYPE);
460 Stream_Write_UINT32(s, autodetect->netCharBandwidth);
461 Stream_Write_UINT32(s, autodetect->netCharAverageRTT);
462 return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
465 static BOOL autodetect_recv_rtt_measure_request(rdpAutoDetect* autodetect,
466 RDP_TRANSPORT_TYPE transport,
wStream* s,
467 const AUTODETECT_REQ_PDU* autodetectReqPdu)
469 WINPR_ASSERT(autodetect);
471 WINPR_ASSERT(autodetectReqPdu);
473 if (autodetectReqPdu->headerLength != 0x06)
475 WLog_Print(autodetect->log, WLOG_ERROR,
476 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
477 autodetectReqPdu->headerLength);
481 WLog_Print(autodetect->log, WLOG_TRACE,
"received RTT Measure Request PDU");
483 return autodetect_send_rtt_measure_response(autodetect, autodetectReqPdu->sequenceNumber);
486 static BOOL autodetect_recv_rtt_measure_response(rdpAutoDetect* autodetect,
487 RDP_TRANSPORT_TYPE transport,
wStream* s,
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");
518 static BOOL autodetect_recv_bandwidth_measure_start(rdpAutoDetect* autodetect,
519 RDP_TRANSPORT_TYPE transport,
wStream* s,
520 const AUTODETECT_REQ_PDU* autodetectReqPdu)
522 WINPR_ASSERT(autodetect);
524 WINPR_ASSERT(autodetectReqPdu);
526 if (autodetectReqPdu->headerLength != 0x06)
528 WLog_Print(autodetect->log, WLOG_ERROR,
529 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
530 autodetectReqPdu->headerLength);
534 WLog_Print(autodetect->log, WLOG_TRACE,
535 "received Bandwidth Measure Start PDU - time=%" PRIu64
"", GetTickCount64());
537 autodetect->bandwidthMeasureStartTime = GetTickCount64();
538 autodetect->bandwidthMeasureByteCount = 0;
541 if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
543 autodetect->bandwidthMeasureStarted = TRUE;
549 static BOOL autodetect_recv_bandwidth_measure_payload(rdpAutoDetect* autodetect,
550 RDP_TRANSPORT_TYPE transport,
wStream* s,
551 const AUTODETECT_REQ_PDU* autodetectReqPdu)
553 UINT16 payloadLength = 0;
555 WINPR_ASSERT(autodetect);
557 WINPR_ASSERT(autodetectReqPdu);
559 if (autodetectReqPdu->headerLength != 0x08)
561 WLog_Print(autodetect->log, WLOG_ERROR,
562 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
563 autodetectReqPdu->headerLength);
567 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
570 Stream_Read_UINT16(s, payloadLength);
571 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
573 Stream_Seek(s, payloadLength);
575 WLog_Print(autodetect->log, WLOG_DEBUG,
576 "received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16
"",
579 autodetect->bandwidthMeasureByteCount += payloadLength;
583 static BOOL autodetect_recv_bandwidth_measure_stop(rdpAutoDetect* autodetect,
584 RDP_TRANSPORT_TYPE transport,
wStream* s,
585 const AUTODETECT_REQ_PDU* autodetectReqPdu)
587 UINT16 payloadLength = 0;
588 UINT16 responseType = 0;
590 WINPR_ASSERT(autodetect);
592 WINPR_ASSERT(autodetectReqPdu);
594 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
596 if (autodetectReqPdu->headerLength != 0x08)
598 WLog_Print(autodetect->log, WLOG_ERROR,
599 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8
"]",
600 autodetectReqPdu->headerLength);
604 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
607 Stream_Read_UINT16(s, payloadLength);
611 if (autodetectReqPdu->headerLength != 0x06)
613 WLog_Print(autodetect->log, WLOG_ERROR,
614 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8
"]",
615 autodetectReqPdu->headerLength);
622 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
624 Stream_Seek(s, payloadLength);
626 WLog_Print(autodetect->log, WLOG_TRACE,
627 "received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16
"", payloadLength);
629 autodetect->bandwidthMeasureByteCount += payloadLength;
632 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
634 autodetect->bandwidthMeasureStarted = FALSE;
638 responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
639 ? RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME
640 : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
641 return autodetect_send_bandwidth_measure_results(autodetect, transport, responseType,
642 autodetectReqPdu->sequenceNumber);
645 static BOOL autodetect_recv_bandwidth_measure_results(rdpAutoDetect* autodetect,
646 RDP_TRANSPORT_TYPE transport,
wStream* s,
647 const AUTODETECT_RSP_PDU* autodetectRspPdu)
649 UINT32 timeDelta = 0;
650 UINT32 byteCount = 0;
653 WINPR_ASSERT(autodetect);
655 WINPR_ASSERT(autodetectRspPdu);
657 if (autodetectRspPdu->headerLength != 0x0E)
659 WLog_Print(autodetect->log, WLOG_ERROR,
660 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
661 autodetectRspPdu->headerLength);
665 WLog_Print(autodetect->log, WLOG_TRACE,
"received Bandwidth Measure Results PDU");
666 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
668 Stream_Read_UINT32(s, timeDelta);
669 Stream_Read_UINT32(s, byteCount);
671 IFCALLRET(autodetect->BandwidthMeasureResults, success, autodetect, transport,
672 autodetectRspPdu->sequenceNumber, autodetectRspPdu->responseType, timeDelta,
675 WLog_Print(autodetect->log, WLOG_WARN,
"BandwidthMeasureResults failed");
679 static BOOL autodetect_recv_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
680 wStream* s,
const AUTODETECT_RSP_PDU* autodetectRspPdu)
682 UINT32 bandwidth = 0;
686 WINPR_ASSERT(autodetect);
688 WINPR_ASSERT(autodetectRspPdu);
690 if (autodetectRspPdu->headerLength != 0x0E)
692 WLog_Print(autodetect->log, WLOG_ERROR,
693 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
694 autodetectRspPdu->headerLength);
697 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
701 Stream_Read_UINT32(s, bandwidth);
702 Stream_Read_UINT32(s, rtt);
704 WLog_Print(autodetect->log, WLOG_TRACE,
705 "received Network Characteristics Sync PDU -> bandwidth=%" PRIu32
", rtt=%" PRIu32
709 IFCALLRET(autodetect->NetworkCharacteristicsSync, success, autodetect, transport,
710 autodetectRspPdu->sequenceNumber, bandwidth, rtt);
712 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsSync failed");
716 static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
717 wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
719 rdpNetworkCharacteristicsResult result = { 0 };
722 WINPR_ASSERT(autodetect);
724 WINPR_ASSERT(autodetectReqPdu);
726 switch (autodetectReqPdu->requestType)
728 case RDP_NETCHAR_RESULTS_0x0840:
731 if (autodetectReqPdu->headerLength != 0x0E)
733 WLog_Print(autodetect->log, WLOG_ERROR,
734 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
735 autodetectReqPdu->headerLength);
738 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
741 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT;
742 Stream_Read_UINT32(s, result.baseRTT);
743 Stream_Read_UINT32(s, result.averageRTT);
746 case RDP_NETCHAR_RESULTS_0x0880:
749 if (autodetectReqPdu->headerLength != 0x0E)
751 WLog_Print(autodetect->log, WLOG_ERROR,
752 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8
"]",
753 autodetectReqPdu->headerLength);
756 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
759 result.type = RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT;
760 Stream_Read_UINT32(s, result.bandwidth);
761 Stream_Read_UINT32(s, result.averageRTT);
764 case RDP_NETCHAR_RESULTS_0x08C0:
767 if (autodetectReqPdu->headerLength != 0x12)
769 WLog_Print(autodetect->log, WLOG_ERROR,
770 "autodetectReqPdu->headerLength != 0x012 [0x%02" PRIx8
"]",
771 autodetectReqPdu->headerLength);
774 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 12))
777 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT;
778 Stream_Read_UINT32(s, result.baseRTT);
779 Stream_Read_UINT32(s, result.bandwidth);
780 Stream_Read_UINT32(s, result.averageRTT);
788 WLog_Print(autodetect->log, WLOG_TRACE,
789 "received Network Characteristics Result PDU -> baseRTT=%" PRIu32
790 ", bandwidth=%" PRIu32
", averageRTT=%" PRIu32
"",
791 result.baseRTT, result.bandwidth, result.averageRTT);
793 IFCALLRET(autodetect->NetworkCharacteristicsResult, success, autodetect, transport,
794 autodetectReqPdu->sequenceNumber, &result);
796 WLog_Print(autodetect->log, WLOG_WARN,
"NetworkCharacteristicsResult failed");
800 state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
803 AUTODETECT_REQ_PDU autodetectReqPdu = { 0 };
804 const rdpSettings* settings = NULL;
805 BOOL success = FALSE;
807 WINPR_ASSERT(autodetect);
808 WINPR_ASSERT(autodetect->context);
810 settings = autodetect->context->settings;
811 WINPR_ASSERT(settings);
813 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
814 return STATE_RUN_FAILED;
816 Stream_Read_UINT8(s, autodetectReqPdu.headerLength);
817 Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId);
818 Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber);
819 Stream_Read_UINT16(s, autodetectReqPdu.requestType);
821 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
823 char rbuffer[128] = { 0 };
824 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
825 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
827 char hbuffer[128] = { 0 };
828 const char* headerStr =
829 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
831 WLog_Print(autodetect->log, WLOG_TRACE,
832 "rdp_recv_autodetect_request_packet: headerLength=%" PRIu8
833 ", headerTypeId=%s, sequenceNumber=%" PRIu16
", requestType=%s",
834 autodetectReqPdu.headerLength, headerStr, autodetectReqPdu.sequenceNumber,
840 char rbuffer[128] = { 0 };
841 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
842 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
844 WLog_Print(autodetect->log, WLOG_WARN,
845 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
846 "message but support was not enabled",
851 if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
853 char rbuffer[128] = { 0 };
854 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
855 autodetectReqPdu.requestType, rbuffer,
sizeof(rbuffer));
856 char hbuffer[128] = { 0 };
857 const char* headerStr =
858 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
860 WLog_Print(autodetect->log, WLOG_ERROR,
861 "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
862 "message with invalid headerTypeId=%s",
863 requestTypeStr, headerStr);
867 IFCALL(autodetect->RequestReceived, autodetect, transport, autodetectReqPdu.requestType,
868 autodetectReqPdu.sequenceNumber);
869 switch (autodetectReqPdu.requestType)
871 case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
872 case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
875 autodetect_recv_rtt_measure_request(autodetect, transport, s, &autodetectReqPdu);
878 case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
879 case RDP_BW_START_REQUEST_TYPE_TUNNEL:
880 case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
882 success = autodetect_recv_bandwidth_measure_start(autodetect, transport, s,
886 case RDP_BW_PAYLOAD_REQUEST_TYPE:
888 success = autodetect_recv_bandwidth_measure_payload(autodetect, transport, s,
892 case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
893 case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
894 case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
897 autodetect_recv_bandwidth_measure_stop(autodetect, transport, s, &autodetectReqPdu);
900 case RDP_NETCHAR_RESULTS_0x0840:
901 case RDP_NETCHAR_RESULTS_0x0880:
902 case RDP_NETCHAR_RESULTS_0x08C0:
904 success = autodetect_recv_netchar_request(autodetect, transport, s, &autodetectReqPdu);
908 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown requestType=0x%04" PRIx16,
909 autodetectReqPdu.requestType);
915 autodetect->state = FREERDP_AUTODETECT_STATE_REQUEST;
917 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
918 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
921 state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
924 AUTODETECT_RSP_PDU autodetectRspPdu = { 0 };
925 const rdpSettings* settings = NULL;
926 BOOL success = FALSE;
928 WINPR_ASSERT(autodetect);
929 WINPR_ASSERT(autodetect->context);
932 settings = autodetect->context->settings;
933 WINPR_ASSERT(settings);
935 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
938 Stream_Read_UINT8(s, autodetectRspPdu.headerLength);
939 Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId);
940 Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber);
941 Stream_Read_UINT16(s, autodetectRspPdu.responseType);
943 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
945 char rbuffer[128] = { 0 };
946 const char* requestStr = autodetect_request_type_to_string_buffer(
947 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
948 char hbuffer[128] = { 0 };
949 const char* headerStr =
950 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
952 WLog_Print(autodetect->log, WLOG_TRACE,
953 "rdp_recv_autodetect_response_packet: headerLength=%" PRIu8
", headerTypeId=%s"
954 ", sequenceNumber=%" PRIu16
", requestType=%s",
955 autodetectRspPdu.headerLength, headerStr, autodetectRspPdu.sequenceNumber,
961 char rbuffer[128] = { 0 };
963 const char* requestStr = autodetect_request_type_to_string_buffer(
964 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
966 WLog_Print(autodetect->log, WLOG_WARN,
967 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
968 "message but support was not enabled",
970 return STATE_RUN_FAILED;
973 if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
975 char rbuffer[128] = { 0 };
976 const char* requestStr = autodetect_request_type_to_string_buffer(
977 autodetectRspPdu.responseType, rbuffer,
sizeof(rbuffer));
978 char hbuffer[128] = { 0 };
979 const char* headerStr =
980 autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer,
sizeof(hbuffer));
981 WLog_Print(autodetect->log, WLOG_ERROR,
982 "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
983 "message with invalid headerTypeId=%s",
984 requestStr, headerStr);
988 IFCALL(autodetect->ResponseReceived, autodetect, transport, autodetectRspPdu.responseType,
989 autodetectRspPdu.sequenceNumber);
990 switch (autodetectRspPdu.responseType)
992 case RDP_RTT_RESPONSE_TYPE:
995 autodetect_recv_rtt_measure_response(autodetect, transport, s, &autodetectRspPdu);
998 case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
999 case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
1001 success = autodetect_recv_bandwidth_measure_results(autodetect, transport, s,
1005 case RDP_NETCHAR_SYNC_RESPONSE_TYPE:
1007 success = autodetect_recv_netchar_sync(autodetect, transport, s, &autodetectRspPdu);
1011 WLog_Print(autodetect->log, WLOG_ERROR,
"Unknown responseType=0x%04" PRIx16,
1012 autodetectRspPdu.responseType);
1019 if (autodetectRspPdu.responseType == RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME)
1020 autodetect->state = FREERDP_AUTODETECT_STATE_COMPLETE;
1022 autodetect->state = FREERDP_AUTODETECT_STATE_RESPONSE;
1025 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
1027 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
1030 void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect)
1032 WINPR_ASSERT(autodetect);
1033 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectBegin);
1035 autodetect->state = autodetect->OnConnectTimeAutoDetectBegin(autodetect);
1038 void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect)
1040 WINPR_ASSERT(autodetect);
1041 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectProgress);
1043 autodetect->state = autodetect->OnConnectTimeAutoDetectProgress(autodetect);
1046 rdpAutoDetect* autodetect_new(rdpContext* context)
1048 rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1,
sizeof(rdpAutoDetect));
1051 autoDetect->context = context;
1052 autoDetect->log = WLog_Get(AUTODETECT_TAG);
1057 void autodetect_free(rdpAutoDetect* autoDetect)
1062 void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
1064 WINPR_ASSERT(autodetect);
1066 autodetect->RTTMeasureRequest = autodetect_send_rtt_measure_request;
1067 autodetect->BandwidthMeasureStart = autodetect_send_bandwidth_measure_start;
1068 autodetect->BandwidthMeasurePayload = autodetect_send_bandwidth_measure_payload;
1069 autodetect->BandwidthMeasureStop = autodetect_send_bandwidth_measure_stop;
1070 autodetect->NetworkCharacteristicsResult = autodetect_send_netchar_result;
1076 autodetect->OnConnectTimeAutoDetectBegin = autodetect_on_connect_time_auto_detect_begin_default;
1077 autodetect->OnConnectTimeAutoDetectProgress =
1078 autodetect_on_connect_time_auto_detect_progress_default;
1081 FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect)
1083 WINPR_ASSERT(autodetect);
1084 return autodetect->state;
1087 rdpAutoDetect* autodetect_get(rdpContext* context)
1089 WINPR_ASSERT(context);
1090 WINPR_ASSERT(context->rdp);
1091 return context->rdp->autodetect;
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.