FreeRDP
Loading...
Searching...
No Matches
autodetect.c
1
20#include <freerdp/config.h>
21
22#include <winpr/crypto.h>
23#include <winpr/assert.h>
24
25#include "autodetect.h"
26
27#define TYPE_ID_AUTODETECT_REQUEST 0x00
28#define TYPE_ID_AUTODETECT_RESPONSE 0x01
29
30#define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001
31#define RDP_RTT_REQUEST_TYPE_CONNECTTIME 0x1001
32
33#define RDP_RTT_RESPONSE_TYPE 0x0000
34
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
42
43#define RDP_NETCHAR_SYNC_RESPONSE_TYPE 0x0018
44
45#define RDP_NETCHAR_RESULTS_0x0840 0x0840U
46#define RDP_NETCHAR_RESULTS_0x0880 0x0880U
47#define RDP_NETCHAR_RESULTS_0x08C0 0x08C0U
48
49typedef struct
50{
51 UINT8 headerLength;
52 UINT8 headerTypeId;
53 UINT16 sequenceNumber;
54 UINT16 requestType;
55} AUTODETECT_REQ_PDU;
56
57typedef struct
58{
59 UINT8 headerLength;
60 UINT8 headerTypeId;
61 UINT16 sequenceNumber;
62 UINT16 responseType;
63} AUTODETECT_RSP_PDU;
64
65static const char* autodetect_header_type_string(UINT8 headerType, char* buffer, size_t size)
66{
67 const char* str = nullptr;
68 switch (headerType)
69 {
70 case TYPE_ID_AUTODETECT_REQUEST:
71 str = "TYPE_ID_AUTODETECT_REQUEST";
72 break;
73 case TYPE_ID_AUTODETECT_RESPONSE:
74 str = "TYPE_ID_AUTODETECT_RESPONSE";
75 break;
76 default:
77 str = "TYPE_ID_AUTODETECT_UNKNOWN";
78 break;
79 }
80
81 (void)_snprintf(buffer, size, "%s [0x%08" PRIx8 "]", str, headerType);
82 return buffer;
83}
84
85static const char* autodetect_request_type_to_string(UINT32 requestType)
86{
87 switch (requestType)
88 {
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";
119 default:
120 return "UNKNOWN";
121 }
122}
123
124static const char* autodetect_request_type_to_string_buffer(UINT32 requestType, char* buffer,
125 size_t size)
126{
127 const char* str = autodetect_request_type_to_string(requestType);
128 (void)_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, requestType);
129 return buffer;
130}
131
132static BOOL autodetect_send_rtt_measure_request(rdpAutoDetect* autodetect,
133 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
134 UINT16 sequenceNumber)
135{
136 UINT16 requestType = 0;
137 UINT16 sec_flags = 0;
138 wStream* s = nullptr;
139
140 WINPR_ASSERT(autodetect);
141 WINPR_ASSERT(autodetect->context);
142
143 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
144 if (!s)
145 return FALSE;
146
147 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
148 requestType = RDP_RTT_REQUEST_TYPE_CONNECTTIME;
149 else
150 requestType = RDP_RTT_REQUEST_TYPE_CONTINUOUS;
151
152 WLog_Print(autodetect->log, WLOG_TRACE, "sending RTT Measure Request PDU");
153 Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
154 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
155 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
156 Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
157 autodetect->rttMeasureStartTime = GetTickCount64();
158 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
159 sec_flags | SEC_AUTODETECT_REQ);
160}
161
162static BOOL autodetect_send_rtt_measure_response(rdpAutoDetect* autodetect, UINT16 sequenceNumber)
163{
164 UINT16 sec_flags = 0;
165 wStream* s = nullptr;
166
167 WINPR_ASSERT(autodetect);
168 WINPR_ASSERT(autodetect->context);
169
170 /* Send the response PDU to the server */
171 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
172
173 if (!s)
174 return FALSE;
175
176 WLog_Print(autodetect->log, WLOG_TRACE,
177 "sending RTT Measure Response PDU (seqNumber=0x%" PRIx16 ")", sequenceNumber);
178 Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
179 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
180 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
181 Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE); /* responseType (1 byte) */
182 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
183 sec_flags | SEC_AUTODETECT_RSP);
184}
185
186static BOOL autodetect_send_bandwidth_measure_start(rdpAutoDetect* autodetect,
187 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
188 UINT16 sequenceNumber)
189{
190 UINT16 requestType = 0;
191 UINT16 sec_flags = 0;
192 wStream* s = nullptr;
193
194 WINPR_ASSERT(autodetect);
195 WINPR_ASSERT(autodetect->context);
196
197 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
198 if (!s)
199 return FALSE;
200
201 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
202 requestType = RDP_BW_START_REQUEST_TYPE_CONNECTTIME;
203 else
204 requestType = RDP_BW_START_REQUEST_TYPE_CONTINUOUS;
205
206 WLog_Print(autodetect->log, WLOG_TRACE,
207 "sending Bandwidth Measure Start PDU(seqNumber=%" PRIu16 ")", sequenceNumber);
208 Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
209 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
210 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
211 Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
212 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
213 sec_flags | SEC_AUTODETECT_REQ);
214}
215
216static BOOL
217autodetect_send_bandwidth_measure_payload(rdpAutoDetect* autodetect,
218 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
219 UINT16 sequenceNumber, UINT16 payloadLength)
220{
221 UINT16 sec_flags = 0;
222 wStream* s = nullptr;
223
224 WINPR_ASSERT(autodetect);
225 WINPR_ASSERT(autodetect->context);
226
227 WINPR_ASSERT(freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE);
228
229 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
230 if (!s)
231 return FALSE;
232
233 WLog_Print(autodetect->log, WLOG_TRACE,
234 "sending Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "", payloadLength);
235 /* 4-bytes aligned */
236 payloadLength &= ~3;
237
238 if (!Stream_EnsureRemainingCapacity(s, 8 + payloadLength))
239 {
240 WLog_Print(autodetect->log, WLOG_ERROR, "Failed to ensure %lu bytes in stream",
241 8ul + payloadLength);
242 Stream_Release(s);
243 return FALSE;
244 }
245
246 Stream_Write_UINT8(s, 0x08); /* headerLength (1 byte) */
247 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
248 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
249 Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE); /* requestType (2 bytes) */
250 Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
251 /* Random data (better measurement in case the line is compressed) */
252 if (winpr_RAND(Stream_Pointer(s), payloadLength) < 0)
253 {
254 Stream_Release(s);
255 return FALSE;
256 }
257 Stream_Seek(s, payloadLength);
258 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
259 sec_flags | SEC_AUTODETECT_REQ);
260}
261
262static BOOL autodetect_send_bandwidth_measure_stop(rdpAutoDetect* autodetect,
263 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
264 UINT16 sequenceNumber, UINT16 payloadLength)
265{
266 UINT16 requestType = 0;
267 UINT16 sec_flags = 0;
268 wStream* s = nullptr;
269
270 WINPR_ASSERT(autodetect);
271 WINPR_ASSERT(autodetect->context);
272
273 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
274 if (!s)
275 return FALSE;
276
277 if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
278 requestType = RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME;
279 else
280 requestType = RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS;
281
282 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
283 payloadLength = 0;
284
285 WLog_Print(autodetect->log, WLOG_TRACE,
286 "sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "", payloadLength);
287 /* 4-bytes aligned */
288 payloadLength &= ~3;
289 Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
290 ? 0x08
291 : 0x06); /* headerLength (1 byte) */
292 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
293 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
294 Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
295
296 if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
297 {
298 Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
299
300 if (payloadLength > 0)
301 {
302 if (!Stream_EnsureRemainingCapacity(s, payloadLength))
303 {
304 WLog_Print(autodetect->log, WLOG_ERROR,
305 "Failed to ensure %" PRIu16 " bytes in stream", payloadLength);
306 Stream_Release(s);
307 return FALSE;
308 }
309
310 /* Random data (better measurement in case the line is compressed) */
311 if (winpr_RAND(Stream_Pointer(s), payloadLength) < 0)
312 {
313 Stream_Release(s);
314 return FALSE;
315 }
316 Stream_Seek(s, payloadLength);
317 }
318 }
319
320 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
321 sec_flags | SEC_AUTODETECT_REQ);
322}
323
324static BOOL autodetect_send_bandwidth_measure_results(rdpAutoDetect* autodetect,
325 RDP_TRANSPORT_TYPE transport,
326 UINT16 responseType, UINT16 sequenceNumber)
327{
328 BOOL success = TRUE;
329 UINT16 sec_flags = 0;
330 UINT64 timeDelta = GetTickCount64();
331
332 WINPR_ASSERT(autodetect);
333 WINPR_ASSERT(autodetect->context);
334
335 /* Compute the total time */
336 if (autodetect->bandwidthMeasureStartTime > timeDelta)
337 {
338 WLog_Print(autodetect->log, WLOG_WARN,
339 "Invalid bandwidthMeasureStartTime %" PRIu64 " > current %" PRIu64
340 ", trimming to 0",
341 autodetect->bandwidthMeasureStartTime, timeDelta);
342 timeDelta = 0;
343 }
344 else
345 timeDelta -= autodetect->bandwidthMeasureStartTime;
346
347 /* Send the result PDU to the server */
348 wStream* s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
349
350 if (!s)
351 return FALSE;
352
353 WLog_Print(autodetect->log, WLOG_TRACE,
354 "sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu64 ", byteCount=%" PRIu32
355 "",
356 timeDelta, autodetect->bandwidthMeasureByteCount);
357
358 Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
359 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
360 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
361 Stream_Write_UINT16(s, responseType); /* responseType (1 byte) */
362 Stream_Write_UINT32(s, (UINT32)MIN(timeDelta, UINT32_MAX)); /* timeDelta (4 bytes) */
363 Stream_Write_UINT32(s, autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
364 IFCALLRET(autodetect->ClientBandwidthMeasureResult, success, autodetect, transport,
365 responseType, sequenceNumber, (UINT32)MIN(timeDelta, UINT32_MAX),
366 autodetect->bandwidthMeasureByteCount);
367
368 if (!success)
369 {
370 WLog_Print(autodetect->log, WLOG_ERROR, "ClientBandwidthMeasureResult failed");
371 Stream_Release(s);
372 return FALSE;
373 }
374
375 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
376 sec_flags | SEC_AUTODETECT_RSP);
377}
378
379static BOOL autodetect_send_netchar_result(rdpAutoDetect* autodetect,
380 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
381 UINT16 sequenceNumber,
382 const rdpNetworkCharacteristicsResult* result)
383{
384 UINT16 sec_flags = 0;
385 wStream* s = nullptr;
386
387 WINPR_ASSERT(autodetect);
388 WINPR_ASSERT(autodetect->context);
389
390 s = rdp_message_channel_pdu_init(autodetect->context->rdp, &sec_flags);
391
392 if (!s)
393 return FALSE;
394
395 WLog_Print(autodetect->log, WLOG_TRACE, "sending Network Characteristics Result PDU");
396
397 switch (result->type)
398 {
399 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT:
400 Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
401 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
402 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
403 WINPR_ASSERT((result->type <= UINT16_MAX));
404 WINPR_ASSERT((result->type >= 0));
405 Stream_Write_UINT16(s, (UINT16)result->type); /* requestType (2 bytes) */
406 Stream_Write_UINT32(s, result->baseRTT); /* baseRTT (4 bytes) */
407 Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
408 break;
409 case RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT:
410 Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
411 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
412 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
413 WINPR_ASSERT((result->type <= UINT16_MAX));
414 WINPR_ASSERT((result->type >= 0));
415 Stream_Write_UINT16(s, (UINT16)result->type); /* requestType (2 bytes) */
416 Stream_Write_UINT32(s, result->bandwidth); /* bandwidth (4 bytes) */
417 Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
418 break;
419 case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT:
420 Stream_Write_UINT8(s, 0x12); /* headerLength (1 byte) */
421 Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
422 Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
423 WINPR_ASSERT((result->type <= UINT16_MAX));
424 WINPR_ASSERT((result->type >= 0));
425 Stream_Write_UINT16(s, (UINT16)result->type); /* requestType (2 bytes) */
426 Stream_Write_UINT32(s, result->baseRTT); /* baseRTT (4 bytes) */
427 Stream_Write_UINT32(s, result->bandwidth); /* bandwidth (4 bytes) */
428 Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
429 break;
430 default:
431 WINPR_ASSERT(FALSE);
432 break;
433 }
434
435 return rdp_send_message_channel_pdu(autodetect->context->rdp, s,
436 sec_flags | SEC_AUTODETECT_REQ);
437}
438
439static FREERDP_AUTODETECT_STATE
440autodetect_on_connect_time_auto_detect_begin_default(rdpAutoDetect* autodetect)
441{
442 WINPR_ASSERT(autodetect);
443 WINPR_ASSERT(autodetect->RTTMeasureRequest);
444
445 if (!autodetect->RTTMeasureRequest(autodetect, RDP_TRANSPORT_TCP, 0x23))
446 return FREERDP_AUTODETECT_STATE_FAIL;
447
448 return FREERDP_AUTODETECT_STATE_REQUEST;
449}
450
451static FREERDP_AUTODETECT_STATE
452autodetect_on_connect_time_auto_detect_progress_default(rdpAutoDetect* autodetect)
453{
454 WINPR_ASSERT(autodetect);
455
456 if (autodetect->state == FREERDP_AUTODETECT_STATE_RESPONSE ||
457 autodetect->state == FREERDP_AUTODETECT_STATE_COMPLETE)
458 return FREERDP_AUTODETECT_STATE_COMPLETE;
459
460 return autodetect->state;
461}
462
463static BOOL autodetect_recv_rtt_measure_request(rdpAutoDetect* autodetect,
464 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
465 WINPR_ATTR_UNUSED wStream* s,
466 const AUTODETECT_REQ_PDU* autodetectReqPdu)
467{
468 WINPR_ASSERT(autodetect);
469 WINPR_ASSERT(s);
470 WINPR_ASSERT(autodetectReqPdu);
471
472 if (autodetectReqPdu->headerLength != 0x06)
473 {
474 WLog_Print(autodetect->log, WLOG_ERROR,
475 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
476 autodetectReqPdu->headerLength);
477 return FALSE;
478 }
479
480 WLog_Print(autodetect->log, WLOG_TRACE, "received RTT Measure Request PDU");
481 /* Send a response to the server */
482 return autodetect_send_rtt_measure_response(autodetect, autodetectReqPdu->sequenceNumber);
483}
484
485static BOOL autodetect_recv_rtt_measure_response(rdpAutoDetect* autodetect,
486 RDP_TRANSPORT_TYPE transport,
487 WINPR_ATTR_UNUSED wStream* s,
488 const AUTODETECT_RSP_PDU* autodetectRspPdu)
489{
490 BOOL success = TRUE;
491
492 WINPR_ASSERT(autodetect);
493 WINPR_ASSERT(autodetectRspPdu);
494
495 if (autodetectRspPdu->headerLength != 0x06)
496 {
497 WLog_Print(autodetect->log, WLOG_ERROR,
498 "autodetectRspPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
499 autodetectRspPdu->headerLength);
500 return FALSE;
501 }
502
503 WLog_Print(autodetect->log, WLOG_TRACE, "received RTT Measure Response PDU");
504 autodetect->netCharAverageRTT =
505 (UINT32)MIN(GetTickCount64() - autodetect->rttMeasureStartTime, UINT32_MAX);
506
507 if (autodetect->netCharBaseRTT == 0 ||
508 autodetect->netCharBaseRTT > autodetect->netCharAverageRTT)
509 autodetect->netCharBaseRTT = autodetect->netCharAverageRTT;
510
511 IFCALLRET(autodetect->RTTMeasureResponse, success, autodetect, transport,
512 autodetectRspPdu->sequenceNumber);
513 if (!success)
514 WLog_Print(autodetect->log, WLOG_WARN, "RTTMeasureResponse failed");
515 return success;
516}
517
518static BOOL autodetect_recv_bandwidth_measure_start(rdpAutoDetect* autodetect,
519 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
520 WINPR_ATTR_UNUSED wStream* s,
521 const AUTODETECT_REQ_PDU* autodetectReqPdu)
522{
523 WINPR_ASSERT(autodetect);
524 WINPR_ASSERT(s);
525 WINPR_ASSERT(autodetectReqPdu);
526
527 if (autodetectReqPdu->headerLength != 0x06)
528 {
529 WLog_Print(autodetect->log, WLOG_ERROR,
530 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
531 autodetectReqPdu->headerLength);
532 return FALSE;
533 }
534
535 WLog_Print(autodetect->log, WLOG_TRACE,
536 "received Bandwidth Measure Start PDU - time=%" PRIu64 "", GetTickCount64());
537 /* Initialize bandwidth measurement parameters */
538 autodetect->bandwidthMeasureStartTime = GetTickCount64();
539 autodetect->bandwidthMeasureByteCount = 0;
540
541 /* Continuous Auto-Detection: mark the start of the measurement */
542 if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
543 {
544 autodetect->bandwidthMeasureStarted = TRUE;
545 }
546
547 return TRUE;
548}
549
550static BOOL
551autodetect_recv_bandwidth_measure_payload(rdpAutoDetect* autodetect,
552 WINPR_ATTR_UNUSED RDP_TRANSPORT_TYPE transport,
553 wStream* s, const AUTODETECT_REQ_PDU* autodetectReqPdu)
554{
555 UINT16 payloadLength = 0;
556
557 WINPR_ASSERT(autodetect);
558 WINPR_ASSERT(s);
559 WINPR_ASSERT(autodetectReqPdu);
560
561 if (autodetectReqPdu->headerLength != 0x08)
562 {
563 WLog_Print(autodetect->log, WLOG_ERROR,
564 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8 "]",
565 autodetectReqPdu->headerLength);
566 return FALSE;
567 }
568
569 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
570 return FALSE;
571
572 Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
573 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
574 return FALSE;
575 Stream_Seek(s, payloadLength);
576
577 WLog_Print(autodetect->log, WLOG_DEBUG,
578 "received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "",
579 payloadLength);
580 /* Add the payload length to the bandwidth measurement parameters */
581 autodetect->bandwidthMeasureByteCount += payloadLength;
582 return TRUE;
583}
584
585static BOOL autodetect_recv_bandwidth_measure_stop(rdpAutoDetect* autodetect,
586 RDP_TRANSPORT_TYPE transport, wStream* s,
587 const AUTODETECT_REQ_PDU* autodetectReqPdu)
588{
589 UINT16 payloadLength = 0;
590 UINT16 responseType = 0;
591
592 WINPR_ASSERT(autodetect);
593 WINPR_ASSERT(s);
594 WINPR_ASSERT(autodetectReqPdu);
595
596 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
597 {
598 if (autodetectReqPdu->headerLength != 0x08)
599 {
600 WLog_Print(autodetect->log, WLOG_ERROR,
601 "autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8 "]",
602 autodetectReqPdu->headerLength);
603 return FALSE;
604 }
605
606 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
607 return FALSE;
608
609 Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
610 }
611 else
612 {
613 if (autodetectReqPdu->headerLength != 0x06)
614 {
615 WLog_Print(autodetect->log, WLOG_ERROR,
616 "autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
617 autodetectReqPdu->headerLength);
618 return FALSE;
619 }
620
621 payloadLength = 0;
622 }
623
624 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
625 return FALSE;
626 Stream_Seek(s, payloadLength);
627
628 WLog_Print(autodetect->log, WLOG_TRACE,
629 "received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "", payloadLength);
630 /* Add the payload length to the bandwidth measurement parameters */
631 autodetect->bandwidthMeasureByteCount += payloadLength;
632
633 /* Continuous Auto-Detection: mark the stop of the measurement */
634 if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
635 {
636 autodetect->bandwidthMeasureStarted = FALSE;
637 }
638
639 /* Send a response the server */
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);
645}
646
647static BOOL autodetect_recv_bandwidth_measure_results(rdpAutoDetect* autodetect,
648 RDP_TRANSPORT_TYPE transport, wStream* s,
649 const AUTODETECT_RSP_PDU* autodetectRspPdu)
650{
651 UINT32 timeDelta = 0;
652 UINT32 byteCount = 0;
653 BOOL success = TRUE;
654
655 WINPR_ASSERT(autodetect);
656 WINPR_ASSERT(s);
657 WINPR_ASSERT(autodetectRspPdu);
658
659 if (autodetectRspPdu->headerLength != 0x0E)
660 {
661 WLog_Print(autodetect->log, WLOG_ERROR,
662 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
663 autodetectRspPdu->headerLength);
664 return FALSE;
665 }
666
667 WLog_Print(autodetect->log, WLOG_TRACE, "received Bandwidth Measure Results PDU");
668 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
669 return FALSE;
670 Stream_Read_UINT32(s, timeDelta); /* timeDelta (4 bytes) */
671 Stream_Read_UINT32(s, byteCount); /* byteCount (4 bytes) */
672
673 IFCALLRET(autodetect->BandwidthMeasureResults, success, autodetect, transport,
674 autodetectRspPdu->sequenceNumber, autodetectRspPdu->responseType, timeDelta,
675 byteCount);
676 if (!success)
677 WLog_Print(autodetect->log, WLOG_WARN, "BandwidthMeasureResults failed");
678 return success;
679}
680
681static BOOL autodetect_recv_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
682 wStream* s, const AUTODETECT_RSP_PDU* autodetectRspPdu)
683{
684 UINT32 bandwidth = 0;
685 UINT32 rtt = 0;
686 BOOL success = TRUE;
687
688 WINPR_ASSERT(autodetect);
689 WINPR_ASSERT(s);
690 WINPR_ASSERT(autodetectRspPdu);
691
692 if (autodetectRspPdu->headerLength != 0x0E)
693 {
694 WLog_Print(autodetect->log, WLOG_ERROR,
695 "autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
696 autodetectRspPdu->headerLength);
697 return FALSE;
698 }
699 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
700 return FALSE;
701
702 /* bandwidth and averageRTT fields are present (baseRTT field is not) */
703 Stream_Read_UINT32(s, bandwidth); /* bandwidth (4 bytes) */
704 Stream_Read_UINT32(s, rtt); /* rtt (4 bytes) */
705
706 WLog_Print(autodetect->log, WLOG_TRACE,
707 "received Network Characteristics Sync PDU -> bandwidth=%" PRIu32 ", rtt=%" PRIu32
708 "",
709 bandwidth, rtt);
710
711 IFCALLRET(autodetect->NetworkCharacteristicsSync, success, autodetect, transport,
712 autodetectRspPdu->sequenceNumber, bandwidth, rtt);
713 if (!success)
714 WLog_Print(autodetect->log, WLOG_WARN, "NetworkCharacteristicsSync failed");
715 return success;
716}
717
718static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
719 wStream* s, const AUTODETECT_REQ_PDU* autodetectReqPdu)
720{
721 rdpNetworkCharacteristicsResult result = {
722 .type = RDP_NETCHAR_RESERVED, .baseRTT = 0, .averageRTT = 0, .bandwidth = 0
723 };
724 BOOL success = TRUE;
725
726 WINPR_ASSERT(autodetect);
727 WINPR_ASSERT(s);
728 WINPR_ASSERT(autodetectReqPdu);
729
730 switch (autodetectReqPdu->requestType)
731 {
732 case RDP_NETCHAR_RESULTS_0x0840:
733
734 /* baseRTT and averageRTT fields are present (bandwidth field is not) */
735 if (autodetectReqPdu->headerLength != 0x0E)
736 {
737 WLog_Print(autodetect->log, WLOG_ERROR,
738 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
739 autodetectReqPdu->headerLength);
740 return FALSE;
741 }
742 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
743 return FALSE;
744
745 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT;
746 Stream_Read_UINT32(s, result.baseRTT); /* baseRTT (4 bytes) */
747 Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
748 break;
749
750 case RDP_NETCHAR_RESULTS_0x0880:
751
752 /* bandwidth and averageRTT fields are present (baseRTT field is not) */
753 if (autodetectReqPdu->headerLength != 0x0E)
754 {
755 WLog_Print(autodetect->log, WLOG_ERROR,
756 "autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
757 autodetectReqPdu->headerLength);
758 return FALSE;
759 }
760 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
761 return FALSE;
762
763 result.type = RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT;
764 Stream_Read_UINT32(s, result.bandwidth); /* bandwidth (4 bytes) */
765 Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
766 break;
767
768 case RDP_NETCHAR_RESULTS_0x08C0:
769
770 /* baseRTT, bandwidth, and averageRTT fields are present */
771 if (autodetectReqPdu->headerLength != 0x12)
772 {
773 WLog_Print(autodetect->log, WLOG_ERROR,
774 "autodetectReqPdu->headerLength != 0x012 [0x%02" PRIx8 "]",
775 autodetectReqPdu->headerLength);
776 return FALSE;
777 }
778 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 12))
779 return FALSE;
780
781 result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT;
782 Stream_Read_UINT32(s, result.baseRTT); /* baseRTT (4 bytes) */
783 Stream_Read_UINT32(s, result.bandwidth); /* bandwidth (4 bytes) */
784 Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
785 break;
786
787 default:
788 WINPR_ASSERT(FALSE);
789 break;
790 }
791
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);
796
797 IFCALLRET(autodetect->NetworkCharacteristicsResult, success, autodetect, transport,
798 autodetectReqPdu->sequenceNumber, &result);
799 if (!success)
800 WLog_Print(autodetect->log, WLOG_WARN, "NetworkCharacteristicsResult failed");
801 return success;
802}
803
804state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
805 wStream* s)
806{
807 AUTODETECT_REQ_PDU autodetectReqPdu = WINPR_C_ARRAY_INIT;
808 const rdpSettings* settings = nullptr;
809 BOOL success = FALSE;
810
811 WINPR_ASSERT(autodetect);
812 WINPR_ASSERT(autodetect->context);
813
814 settings = autodetect->context->settings;
815 WINPR_ASSERT(settings);
816
817 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
818 return STATE_RUN_FAILED;
819
820 Stream_Read_UINT8(s, autodetectReqPdu.headerLength); /* headerLength (1 byte) */
821 Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId); /* headerTypeId (1 byte) */
822 Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
823 Stream_Read_UINT16(s, autodetectReqPdu.requestType); /* requestType (2 bytes) */
824
825 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
826 {
827 char rbuffer[128] = WINPR_C_ARRAY_INIT;
828 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
829 autodetectReqPdu.requestType, rbuffer, sizeof(rbuffer));
830
831 char hbuffer[128] = WINPR_C_ARRAY_INIT;
832 const char* headerStr =
833 autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer, sizeof(hbuffer));
834
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,
839 requestTypeStr);
840 }
841
842 if (!freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
843 {
844 char rbuffer[128] = WINPR_C_ARRAY_INIT;
845 const char* requestTypeStr = autodetect_request_type_to_string_buffer(
846 autodetectReqPdu.requestType, rbuffer, sizeof(rbuffer));
847
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",
851 requestTypeStr);
852 goto fail;
853 }
854
855 if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
856 {
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));
863
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);
868 goto fail;
869 }
870
871 if (!IFCALLRESULT(TRUE, autodetect->RequestReceived, autodetect, transport,
872 autodetectReqPdu.requestType, autodetectReqPdu.sequenceNumber))
873 goto fail;
874
875 switch (autodetectReqPdu.requestType)
876 {
877 case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
878 case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
879 /* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
880 success =
881 autodetect_recv_rtt_measure_request(autodetect, transport, s, &autodetectReqPdu);
882 break;
883
884 case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
885 case RDP_BW_START_REQUEST_TYPE_TUNNEL:
886 case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
887 /* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
888 success = autodetect_recv_bandwidth_measure_start(autodetect, transport, s,
889 &autodetectReqPdu);
890 break;
891
892 case RDP_BW_PAYLOAD_REQUEST_TYPE:
893 /* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
894 success = autodetect_recv_bandwidth_measure_payload(autodetect, transport, s,
895 &autodetectReqPdu);
896 break;
897
898 case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
899 case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
900 case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
901 /* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
902 success =
903 autodetect_recv_bandwidth_measure_stop(autodetect, transport, s, &autodetectReqPdu);
904 break;
905
906 case RDP_NETCHAR_RESULTS_0x0840:
907 case RDP_NETCHAR_RESULTS_0x0880:
908 case RDP_NETCHAR_RESULTS_0x08C0:
909 /* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
910 success = autodetect_recv_netchar_request(autodetect, transport, s, &autodetectReqPdu);
911 break;
912
913 default:
914 WLog_Print(autodetect->log, WLOG_ERROR, "Unknown requestType=0x%04" PRIx16,
915 autodetectReqPdu.requestType);
916 break;
917 }
918
919fail:
920 if (success)
921 autodetect->state = FREERDP_AUTODETECT_STATE_REQUEST;
922 else
923 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
924 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
925}
926
927state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
928 wStream* s)
929{
930 AUTODETECT_RSP_PDU autodetectRspPdu = WINPR_C_ARRAY_INIT;
931 const rdpSettings* settings = nullptr;
932 BOOL success = FALSE;
933
934 WINPR_ASSERT(autodetect);
935 WINPR_ASSERT(autodetect->context);
936 WINPR_ASSERT(s);
937
938 settings = autodetect->context->settings;
939 WINPR_ASSERT(settings);
940
941 if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
942 goto fail;
943
944 Stream_Read_UINT8(s, autodetectRspPdu.headerLength); /* headerLength (1 byte) */
945 Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId); /* headerTypeId (1 byte) */
946 Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
947 Stream_Read_UINT16(s, autodetectRspPdu.responseType); /* responseType (2 bytes) */
948
949 if (WLog_IsLevelActive(autodetect->log, WLOG_TRACE))
950 {
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));
957
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,
962 requestStr);
963 }
964
965 if (!freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
966 {
967 char rbuffer[128] = WINPR_C_ARRAY_INIT;
968
969 const char* requestStr = autodetect_request_type_to_string_buffer(
970 autodetectRspPdu.responseType, rbuffer, sizeof(rbuffer));
971
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",
975 requestStr);
976 return STATE_RUN_FAILED;
977 }
978
979 if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
980 {
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);
991 goto fail;
992 }
993
994 if (!IFCALLRESULT(TRUE, autodetect->ResponseReceived, autodetect, transport,
995 autodetectRspPdu.responseType, autodetectRspPdu.sequenceNumber))
996 goto fail;
997
998 switch (autodetectRspPdu.responseType)
999 {
1000 case RDP_RTT_RESPONSE_TYPE:
1001 /* RTT Measure Response (RDP_RTT_RESPONSE) - MS-RDPBCGR 2.2.14.2.1 */
1002 success =
1003 autodetect_recv_rtt_measure_response(autodetect, transport, s, &autodetectRspPdu);
1004 break;
1005
1006 case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
1007 case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
1008 /* Bandwidth Measure Results (RDP_BW_RESULTS) - MS-RDPBCGR 2.2.14.2.2 */
1009 success = autodetect_recv_bandwidth_measure_results(autodetect, transport, s,
1010 &autodetectRspPdu);
1011 break;
1012
1013 case RDP_NETCHAR_SYNC_RESPONSE_TYPE:
1014 /* Network Characteristics Sync (RDP_NETCHAR_SYNC) - MS-RDPBCGR 2.2.14.2.3 */
1015 success = autodetect_recv_netchar_sync(autodetect, transport, s, &autodetectRspPdu);
1016 break;
1017
1018 default:
1019 WLog_Print(autodetect->log, WLOG_ERROR, "Unknown responseType=0x%04" PRIx16,
1020 autodetectRspPdu.responseType);
1021 break;
1022 }
1023
1024fail:
1025 if (success)
1026 {
1027 if (autodetectRspPdu.responseType == RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME)
1028 autodetect->state = FREERDP_AUTODETECT_STATE_COMPLETE;
1029 else
1030 autodetect->state = FREERDP_AUTODETECT_STATE_RESPONSE;
1031 }
1032 else
1033 autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
1034
1035 return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
1036}
1037
1038void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect)
1039{
1040 WINPR_ASSERT(autodetect);
1041 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectBegin);
1042
1043 autodetect->state = autodetect->OnConnectTimeAutoDetectBegin(autodetect);
1044}
1045
1046void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect)
1047{
1048 WINPR_ASSERT(autodetect);
1049 WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectProgress);
1050
1051 autodetect->state = autodetect->OnConnectTimeAutoDetectProgress(autodetect);
1052}
1053
1054rdpAutoDetect* autodetect_new(rdpContext* context)
1055{
1056 rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1, sizeof(rdpAutoDetect));
1057 if (!autoDetect)
1058 return nullptr;
1059 autoDetect->context = context;
1060 autoDetect->log = WLog_Get(AUTODETECT_TAG);
1061
1062 return autoDetect;
1063}
1064
1065void autodetect_free(rdpAutoDetect* autoDetect)
1066{
1067 free(autoDetect);
1068}
1069
1070void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
1071{
1072 WINPR_ASSERT(autodetect);
1073
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;
1079
1080 /*
1081 * Default handlers for Connect-Time Auto-Detection
1082 * (MAY be overridden by the API user)
1083 */
1084 autodetect->OnConnectTimeAutoDetectBegin = autodetect_on_connect_time_auto_detect_begin_default;
1085 autodetect->OnConnectTimeAutoDetectProgress =
1086 autodetect_on_connect_time_auto_detect_progress_default;
1087}
1088
1089FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect)
1090{
1091 WINPR_ASSERT(autodetect);
1092 return autodetect->state;
1093}
1094
1095rdpAutoDetect* autodetect_get(rdpContext* context)
1096{
1097 WINPR_ASSERT(context);
1098 WINPR_ASSERT(context->rdp);
1099 return context->rdp->autodetect;
1100}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.