Coverage Report

Created: 2024-09-08 06:20

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