FreeRDP/libfreerdp/core/autodetect.c

1059 lines
38 KiB
C
Raw Normal View History

2014-01-24 07:23:47 +04:00
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Auto-Detect PDUs
*
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2022-02-16 13:20:38 +03:00
#include <freerdp/config.h>
2014-01-24 07:23:47 +04:00
#include <winpr/crypto.h>
#include <winpr/assert.h>
2014-01-24 07:23:47 +04:00
#include "autodetect.h"
#define TYPE_ID_AUTODETECT_REQUEST 0x00
#define TYPE_ID_AUTODETECT_RESPONSE 0x01
2019-11-06 17:24:51 +03:00
#define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001
2014-11-11 05:14:44 +03:00
#define RDP_RTT_REQUEST_TYPE_CONNECTTIME 0x1001
#define RDP_RTT_RESPONSE_TYPE 0x0000
2019-11-06 17:24:51 +03:00
#define RDP_BW_START_REQUEST_TYPE_CONTINUOUS 0x0014
#define RDP_BW_START_REQUEST_TYPE_TUNNEL 0x0114
2014-11-11 05:14:44 +03:00
#define RDP_BW_START_REQUEST_TYPE_CONNECTTIME 0x1014
2019-11-06 17:24:51 +03:00
#define RDP_BW_PAYLOAD_REQUEST_TYPE 0x0002
#define RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME 0x002B
#define RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS 0x0429
#define RDP_BW_STOP_REQUEST_TYPE_TUNNEL 0x0629
2014-11-11 05:14:44 +03:00
#define RDP_NETCHAR_SYNC_RESPONSE_TYPE 0x0018
#define RDP_NETCHAR_RESULTS_0x0840 0x0840U
#define RDP_NETCHAR_RESULTS_0x0880 0x0880U
#define RDP_NETCHAR_RESULTS_0x08C0 0x08C0U
2014-01-24 07:23:47 +04:00
typedef struct
{
UINT8 headerLength;
UINT8 headerTypeId;
UINT16 sequenceNumber;
UINT16 requestType;
} AUTODETECT_REQ_PDU;
typedef struct
{
UINT8 headerLength;
UINT8 headerTypeId;
UINT16 sequenceNumber;
UINT16 responseType;
} AUTODETECT_RSP_PDU;
static const char* autodetect_header_type_string(UINT8 headerType, char* buffer, size_t size)
{
const char* str = NULL;
switch (headerType)
{
case TYPE_ID_AUTODETECT_REQUEST:
str = "TYPE_ID_AUTODETECT_REQUEST";
break;
case TYPE_ID_AUTODETECT_RESPONSE:
str = "TYPE_ID_AUTODETECT_RESPONSE";
break;
default:
str = "TYPE_ID_AUTODETECT_UNKNOWN";
break;
}
_snprintf(buffer, size, "%s [0x%08" PRIx8 "]", str, headerType);
return buffer;
}
static const char* autodetect_request_type_to_string(UINT32 requestType)
{
switch (requestType)
{
case RDP_RTT_RESPONSE_TYPE:
return "RDP_RTT_RESPONSE_TYPE";
case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
return "RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME";
case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
return "RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS";
case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
return "RDP_RTT_REQUEST_TYPE_CONTINUOUS";
case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
return "RDP_RTT_REQUEST_TYPE_CONNECTTIME";
case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
return "RDP_BW_START_REQUEST_TYPE_CONTINUOUS";
case RDP_BW_START_REQUEST_TYPE_TUNNEL:
return "RDP_BW_START_REQUEST_TYPE_TUNNEL";
case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
return "RDP_BW_START_REQUEST_TYPE_CONNECTTIME";
case RDP_BW_PAYLOAD_REQUEST_TYPE:
return "RDP_BW_PAYLOAD_REQUEST_TYPE";
case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
return "RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME";
case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
return "RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS";
case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
return "RDP_BW_STOP_REQUEST_TYPE_TUNNEL";
case RDP_NETCHAR_RESULTS_0x0840:
return "RDP_NETCHAR_RESULTS_0x0840";
case RDP_NETCHAR_RESULTS_0x0880:
return "RDP_NETCHAR_RESULTS_0x0880";
case RDP_NETCHAR_RESULTS_0x08C0:
return "RDP_NETCHAR_RESULTS_0x08C0";
default:
return "UNKNOWN";
}
}
static const char* autodetect_request_type_to_string_buffer(UINT32 requestType, char* buffer,
size_t size)
{
const char* str = autodetect_request_type_to_string(requestType);
_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, requestType);
return buffer;
}
static BOOL autodetect_send_rtt_measure_request(rdpAutoDetect* autodetect,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
RDP_TRANSPORT_TYPE transport, UINT16 sequenceNumber)
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 requestType;
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
if (!s)
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
requestType = RDP_RTT_REQUEST_TYPE_CONNECTTIME;
else
requestType = RDP_RTT_REQUEST_TYPE_CONTINUOUS;
WLog_Print(autodetect->log, WLOG_TRACE, "sending RTT Measure Request PDU");
2019-11-06 17:24:51 +03:00
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
2019-11-06 17:24:51 +03:00
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
autodetect->rttMeasureStartTime = GetTickCount64();
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
}
static BOOL autodetect_send_rtt_measure_response(rdpAutoDetect* autodetect, UINT16 sequenceNumber)
2014-01-24 07:23:47 +04:00
{
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
2014-01-24 07:23:47 +04:00
/* Send the response PDU to the server */
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
2014-02-11 07:23:59 +04:00
if (!s)
2014-02-11 07:23:59 +04:00
return FALSE;
2014-01-24 07:23:47 +04:00
WLog_Print(autodetect->log, WLOG_TRACE,
"sending RTT Measure Response PDU (seqNumber=0x%" PRIx16 ")", sequenceNumber);
2019-11-06 17:24:51 +03:00
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
2014-01-24 07:23:47 +04:00
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
2019-11-06 17:24:51 +03:00
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE); /* responseType (1 byte) */
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
2014-01-24 07:23:47 +04:00
}
static BOOL autodetect_send_bandwidth_measure_start(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 sequenceNumber)
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 requestType;
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
if (!s)
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
requestType = RDP_BW_START_REQUEST_TYPE_CONNECTTIME;
else
requestType = RDP_BW_START_REQUEST_TYPE_CONTINUOUS;
WLog_Print(autodetect->log, WLOG_TRACE,
"sending Bandwidth Measure Start PDU(seqNumber=%" PRIu16 ")", sequenceNumber);
2019-11-06 17:24:51 +03:00
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
2019-11-06 17:24:51 +03:00
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
}
2023-05-23 13:05:51 +03:00
static BOOL autodetect_send_bandwidth_measure_payload(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport,
UINT16 sequenceNumber, UINT16 payloadLength)
{
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
WINPR_ASSERT(freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
if (!s)
return FALSE;
WLog_Print(autodetect->log, WLOG_TRACE,
"sending Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "", payloadLength);
/* 4-bytes aligned */
payloadLength &= ~3;
if (!Stream_EnsureRemainingCapacity(s, 8 + payloadLength))
{
WLog_Print(autodetect->log, WLOG_ERROR, "Failed to ensure %" PRIuz " bytes in stream",
8ull + payloadLength);
Stream_Release(s);
return FALSE;
}
2019-11-06 17:24:51 +03:00
Stream_Write_UINT8(s, 0x08); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
2014-11-11 05:14:44 +03:00
Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE); /* requestType (2 bytes) */
2019-11-06 17:24:51 +03:00
Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
/* Random data (better measurement in case the line is compressed) */
winpr_RAND(Stream_Pointer(s), payloadLength);
Stream_Seek(s, payloadLength);
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
}
static BOOL autodetect_send_bandwidth_measure_stop(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 sequenceNumber, UINT16 payloadLength)
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 requestType;
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
if (!s)
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
if (freerdp_get_state(autodetect->context) < CONNECTION_STATE_ACTIVE)
requestType = RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME;
else
requestType = RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS;
if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
payloadLength = 0;
WLog_Print(autodetect->log, WLOG_TRACE,
"sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "", payloadLength);
/* 4-bytes aligned */
payloadLength &= ~3;
2019-11-06 17:24:51 +03:00
Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
? 0x08
: 0x06); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
2019-11-06 17:24:51 +03:00
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, requestType); /* requestType (2 bytes) */
2014-11-11 05:14:44 +03:00
if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
{
Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
if (payloadLength > 0)
{
if (!Stream_EnsureRemainingCapacity(s, payloadLength))
{
WLog_Print(autodetect->log, WLOG_ERROR,
"Failed to ensure %" PRIuz " bytes in stream", payloadLength);
Stream_Release(s);
return FALSE;
}
/* Random data (better measurement in case the line is compressed) */
winpr_RAND(Stream_Pointer(s), payloadLength);
Stream_Seek(s, payloadLength);
}
}
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
}
static BOOL autodetect_send_bandwidth_measure_results(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport,
UINT16 responseType, UINT16 sequenceNumber)
2014-01-24 07:23:47 +04:00
{
BOOL success = TRUE;
2014-01-24 07:23:47 +04:00
wStream* s;
UINT64 timeDelta = GetTickCount64();
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
2014-01-24 07:23:47 +04:00
/* Compute the total time */
if (autodetect->bandwidthMeasureStartTime > timeDelta)
{
WLog_Print(autodetect->log, WLOG_WARN,
"Invalid bandwidthMeasureStartTime %" PRIu64 " > current %" PRIu64
", trimming to 0",
autodetect->bandwidthMeasureStartTime, timeDelta);
timeDelta = 0;
}
else
timeDelta -= autodetect->bandwidthMeasureStartTime;
2014-01-24 07:23:47 +04:00
/* Send the result PDU to the server */
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
2014-02-11 07:23:59 +04:00
if (!s)
2014-02-11 07:23:59 +04:00
return FALSE;
2014-01-24 07:23:47 +04:00
WLog_Print(autodetect->log, WLOG_TRACE,
"sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu64 ", byteCount=%" PRIu32
"",
timeDelta, autodetect->bandwidthMeasureByteCount);
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, responseType); /* responseType (1 byte) */
Stream_Write_UINT32(s, (UINT32)MIN(timeDelta, UINT32_MAX)); /* timeDelta (4 bytes) */
Stream_Write_UINT32(s, autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
IFCALLRET(autodetect->ClientBandwidthMeasureResult, success, autodetect, transport,
responseType, sequenceNumber, (UINT32)MIN(timeDelta, UINT32_MAX),
autodetect->bandwidthMeasureByteCount);
if (!success)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR, "ClientBandwidthMeasureResult failed");
return FALSE;
2022-10-05 15:53:23 +03:00
}
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
2014-01-24 07:23:47 +04:00
}
static BOOL autodetect_send_netchar_result(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT16 sequenceNumber,
const rdpNetworkCharacteristicsResult* result)
{
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
if (!s)
return FALSE;
WLog_Print(autodetect->log, WLOG_TRACE, "sending Network Characteristics Result PDU");
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
switch (result->type)
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT:
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, result->type); /* requestType (2 bytes) */
Stream_Write_UINT32(s, result->baseRTT); /* baseRTT (4 bytes) */
Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
break;
case RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT:
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, result->type); /* requestType (2 bytes) */
Stream_Write_UINT32(s, result->bandwidth); /* bandwidth (4 bytes) */
Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
break;
case RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT:
Stream_Write_UINT8(s, 0x12); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, result->type); /* requestType (2 bytes) */
Stream_Write_UINT32(s, result->baseRTT); /* baseRTT (4 bytes) */
Stream_Write_UINT32(s, result->bandwidth); /* bandwidth (4 bytes) */
Stream_Write_UINT32(s, result->averageRTT); /* averageRTT (4 bytes) */
break;
default:
WINPR_ASSERT(FALSE);
break;
}
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_REQ);
}
core/autodetect: Allow overriding connect-time autodetection handling Currently, FreeRDP-based server implementations can do connect-time autodetection. However, without having any control over it. In order to be able to override the default connect-time autodetection handling, introduce three new states for the state machine of the connection sequence and two new callbacks for the autodetect handling. These are: - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_BEGIN - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_IN_PROGRESS - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_END - OnConnectTimeAutoDetectBegin() - OnConnectTimeAutoDetectProgress() The END state is pretty simple: When the autodetection is finished and the autodetect state is FREERDP_AUTODETECT_STATE_COMPLETE, transition into the next state of the connection sequence. The BEGIN state is entered, when capability-wise network autodetection is available. In this state, the OnConnectTimeAutoDetectBegin callback is called, the server implementation may initialize any related handling here. If the server implementation determines, that no further handling is required, it can end the autodetection phase by returning FREERDP_AUTODETECT_STATE_COMPLETE. If not, and an autodetection request is sent, it returns FREERDP_AUTODETECT_STATE_REQUEST. The state machine of the connection sequence will then switch into the IN_PROGRESS state. In the IN_PROGRESS state, any incoming PDU is handled first, then the OnConnectTimeAutoDetectProgress callback is called. Like in the BEGIN state, the return value will determine, whether the state machine of the connection sequence goes into the END state or goes into (or rather stays) in the IN_PROGRESS state.
2023-04-09 19:34:56 +03:00
static FREERDP_AUTODETECT_STATE
autodetect_on_connect_time_auto_detect_begin_default(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->RTTMeasureRequest);
if (!autodetect->RTTMeasureRequest(autodetect, RDP_TRANSPORT_TCP, 0x23))
return FREERDP_AUTODETECT_STATE_FAIL;
return FREERDP_AUTODETECT_STATE_REQUEST;
}
static FREERDP_AUTODETECT_STATE
autodetect_on_connect_time_auto_detect_progress_default(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
if (autodetect->state == FREERDP_AUTODETECT_STATE_RESPONSE ||
autodetect->state == FREERDP_AUTODETECT_STATE_COMPLETE)
return FREERDP_AUTODETECT_STATE_COMPLETE;
return autodetect->state;
}
static BOOL autodetect_send_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
UINT16 sequenceNumber)
2014-01-24 07:23:47 +04:00
{
wStream* s;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
WINPR_ASSERT(autodetect->context->rdp);
2014-01-24 07:23:47 +04:00
/* Send the response PDU to the server */
s = rdp_message_channel_pdu_init(autodetect->context->rdp);
2014-02-11 07:23:59 +04:00
if (!s)
2014-02-11 07:23:59 +04:00
return FALSE;
2014-01-24 07:23:47 +04:00
WLog_Print(autodetect->log, WLOG_TRACE,
"sending Network Characteristics Sync PDU -> bandwidth=%" PRIu32 ", rtt=%" PRIu32 "",
autodetect->netCharBandwidth, autodetect->netCharAverageRTT);
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */
Stream_Write_UINT16(s, RDP_NETCHAR_SYNC_RESPONSE_TYPE); /* responseType (1 byte) */
Stream_Write_UINT32(s, autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
Stream_Write_UINT32(s, autodetect->netCharAverageRTT); /* rtt (4 bytes) */
return rdp_send_message_channel_pdu(autodetect->context->rdp, s, SEC_AUTODETECT_RSP);
2014-01-24 07:23:47 +04:00
}
static BOOL autodetect_recv_rtt_measure_request(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
2014-01-24 07:23:47 +04:00
{
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectReqPdu);
2014-01-24 07:23:47 +04:00
if (autodetectReqPdu->headerLength != 0x06)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2014-01-24 07:23:47 +04:00
return FALSE;
2022-10-05 15:53:23 +03:00
}
2014-01-24 07:23:47 +04:00
WLog_Print(autodetect->log, WLOG_TRACE, "received RTT Measure Request PDU");
2014-01-24 07:23:47 +04:00
/* Send a response to the server */
return autodetect_send_rtt_measure_response(autodetect, autodetectReqPdu->sequenceNumber);
2014-01-24 07:23:47 +04:00
}
static BOOL autodetect_recv_rtt_measure_response(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_RSP_PDU* autodetectRspPdu)
{
BOOL success = TRUE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetectRspPdu);
if (autodetectRspPdu->headerLength != 0x06)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectRspPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
autodetectRspPdu->headerLength);
return FALSE;
2022-10-05 15:53:23 +03:00
}
WLog_Print(autodetect->log, WLOG_TRACE, "received RTT Measure Response PDU");
autodetect->netCharAverageRTT =
(UINT32)MIN(GetTickCount64() - autodetect->rttMeasureStartTime, UINT32_MAX);
if (autodetect->netCharBaseRTT == 0 ||
autodetect->netCharBaseRTT > autodetect->netCharAverageRTT)
autodetect->netCharBaseRTT = autodetect->netCharAverageRTT;
IFCALLRET(autodetect->RTTMeasureResponse, success, autodetect, transport,
autodetectRspPdu->sequenceNumber);
2022-10-05 15:53:23 +03:00
if (!success)
WLog_Print(autodetect->log, WLOG_WARN, "RTTMeasureResponse failed");
return success;
}
static BOOL autodetect_recv_bandwidth_measure_start(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
2014-01-24 07:23:47 +04:00
{
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectReqPdu);
2014-01-24 07:23:47 +04:00
if (autodetectReqPdu->headerLength != 0x06)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2014-01-24 07:23:47 +04:00
return FALSE;
2022-10-05 15:53:23 +03:00
}
2014-01-24 07:23:47 +04:00
WLog_Print(autodetect->log, WLOG_TRACE,
"received Bandwidth Measure Start PDU - time=%" PRIu64 "", GetTickCount64());
2014-01-24 07:23:47 +04:00
/* Initialize bandwidth measurement parameters */
autodetect->bandwidthMeasureStartTime = GetTickCount64();
autodetect->bandwidthMeasureByteCount = 0;
2014-01-24 07:23:47 +04:00
/* Continuous Auto-Detection: mark the start of the measurement */
2014-11-11 05:14:44 +03:00
if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
{
autodetect->bandwidthMeasureStarted = TRUE;
}
2014-01-24 07:23:47 +04:00
return TRUE;
}
static BOOL autodetect_recv_bandwidth_measure_payload(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
2014-01-24 07:23:47 +04:00
{
UINT16 payloadLength;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectReqPdu);
2014-01-24 07:23:47 +04:00
if (autodetectReqPdu->headerLength != 0x08)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2014-01-24 07:23:47 +04:00
return FALSE;
2022-10-05 15:53:23 +03:00
}
2014-01-24 07:23:47 +04:00
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
2014-01-24 07:23:47 +04:00
return FALSE;
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
return FALSE;
2022-10-05 15:53:23 +03:00
Stream_Seek(s, payloadLength);
WLog_Print(autodetect->log, WLOG_DEBUG,
"received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "",
payloadLength);
2014-01-24 07:23:47 +04:00
/* Add the payload length to the bandwidth measurement parameters */
autodetect->bandwidthMeasureByteCount += payloadLength;
2014-01-24 07:23:47 +04:00
return TRUE;
}
static BOOL autodetect_recv_bandwidth_measure_stop(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_REQ_PDU* autodetectReqPdu)
2014-01-24 07:23:47 +04:00
{
UINT16 payloadLength;
UINT16 responseType;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectReqPdu);
2014-11-11 05:14:44 +03:00
if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
2014-01-24 07:23:47 +04:00
{
if (autodetectReqPdu->headerLength != 0x08)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x08 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2014-01-24 07:23:47 +04:00
return FALSE;
2022-10-05 15:53:23 +03:00
}
2014-01-24 07:23:47 +04:00
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 2))
2014-01-24 07:23:47 +04:00
return FALSE;
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
}
else
{
if (autodetectReqPdu->headerLength != 0x06)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x06 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2014-01-24 07:23:47 +04:00
return FALSE;
2022-10-05 15:53:23 +03:00
}
2014-01-24 07:23:47 +04:00
payloadLength = 0;
}
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, payloadLength))
return FALSE;
2022-10-05 15:53:23 +03:00
Stream_Seek(s, payloadLength);
WLog_Print(autodetect->log, WLOG_TRACE,
"received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "", payloadLength);
2014-01-24 07:23:47 +04:00
/* Add the payload length to the bandwidth measurement parameters */
autodetect->bandwidthMeasureByteCount += payloadLength;
2014-01-24 07:23:47 +04:00
/* Continuous Auto-Detection: mark the stop of the measurement */
2014-11-11 05:14:44 +03:00
if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
{
autodetect->bandwidthMeasureStarted = FALSE;
}
2014-01-24 07:23:47 +04:00
/* Send a response the server */
2019-11-06 17:24:51 +03:00
responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
? RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME
: RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
return autodetect_send_bandwidth_measure_results(autodetect, transport, responseType,
2019-11-06 17:24:51 +03:00
autodetectReqPdu->sequenceNumber);
2014-01-24 07:23:47 +04:00
}
static BOOL autodetect_recv_bandwidth_measure_results(rdpAutoDetect* autodetect,
RDP_TRANSPORT_TYPE transport, wStream* s,
const AUTODETECT_RSP_PDU* autodetectRspPdu)
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT32 timeDelta;
UINT32 byteCount;
BOOL success = TRUE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectRspPdu);
if (autodetectRspPdu->headerLength != 0x0E)
2022-10-05 15:53:23 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
autodetectRspPdu->headerLength);
return FALSE;
2022-10-05 15:53:23 +03:00
}
WLog_Print(autodetect->log, WLOG_TRACE, "received Bandwidth Measure Results PDU");
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
Stream_Read_UINT32(s, timeDelta); /* timeDelta (4 bytes) */
Stream_Read_UINT32(s, byteCount); /* byteCount (4 bytes) */
IFCALLRET(autodetect->BandwidthMeasureResults, success, autodetect, transport,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetectRspPdu->sequenceNumber, autodetectRspPdu->responseType, timeDelta,
byteCount);
2022-10-05 15:53:23 +03:00
if (!success)
WLog_Print(autodetect->log, WLOG_WARN, "BandwidthMeasureResults failed");
return success;
}
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
static BOOL autodetect_recv_netchar_sync(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
wStream* s, const AUTODETECT_RSP_PDU* autodetectRspPdu)
2022-10-05 15:25:35 +03:00
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
UINT32 bandwidth = 0;
UINT32 rtt = 0;
2022-10-05 15:25:35 +03:00
BOOL success = TRUE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectRspPdu);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
if (autodetectRspPdu->headerLength != 0x0E)
2022-10-05 15:25:35 +03:00
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectRspPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
autodetectRspPdu->headerLength);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
return FALSE;
2022-10-05 15:25:35 +03:00
}
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
return FALSE;
/* bandwidth and averageRTT fields are present (baseRTT field is not) */
Stream_Read_UINT32(s, bandwidth); /* bandwidth (4 bytes) */
Stream_Read_UINT32(s, rtt); /* rtt (4 bytes) */
2022-10-05 15:25:35 +03:00
WLog_Print(autodetect->log, WLOG_TRACE,
"received Network Characteristics Sync PDU -> bandwidth=%" PRIu32 ", rtt=%" PRIu32
"",
bandwidth, rtt);
2022-10-05 15:25:35 +03:00
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
IFCALLRET(autodetect->NetworkCharacteristicsSync, success, autodetect, transport,
autodetectRspPdu->sequenceNumber, bandwidth, rtt);
2022-10-05 15:53:23 +03:00
if (!success)
WLog_Print(autodetect->log, WLOG_WARN, "NetworkCharacteristicsSync failed");
2022-10-05 15:25:35 +03:00
return success;
}
static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
wStream* s, const AUTODETECT_REQ_PDU* autodetectReqPdu)
2014-01-24 07:23:47 +04:00
{
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
rdpNetworkCharacteristicsResult result = { 0 };
BOOL success = TRUE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(s);
WINPR_ASSERT(autodetectReqPdu);
2014-01-24 07:23:47 +04:00
switch (autodetectReqPdu->requestType)
{
case RDP_NETCHAR_RESULTS_0x0840:
2014-01-24 07:23:47 +04:00
/* baseRTT and averageRTT fields are present (bandwidth field is not) */
2022-10-05 15:53:23 +03:00
if (autodetectReqPdu->headerLength != 0x0E)
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2022-10-05 15:53:23 +03:00
return FALSE;
}
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
return FALSE;
2014-01-24 07:23:47 +04:00
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_AVG_RTT;
Stream_Read_UINT32(s, result.baseRTT); /* baseRTT (4 bytes) */
Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
break;
case RDP_NETCHAR_RESULTS_0x0880:
/* bandwidth and averageRTT fields are present (baseRTT field is not) */
2022-10-05 15:53:23 +03:00
if (autodetectReqPdu->headerLength != 0x0E)
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x0E [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2022-10-05 15:53:23 +03:00
return FALSE;
}
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 8))
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
result.type = RDP_NETCHAR_RESULT_TYPE_BW_AVG_RTT;
Stream_Read_UINT32(s, result.bandwidth); /* bandwidth (4 bytes) */
Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
break;
case RDP_NETCHAR_RESULTS_0x08C0:
2014-01-24 07:23:47 +04:00
/* baseRTT, bandwidth, and averageRTT fields are present */
2022-10-05 15:53:23 +03:00
if (autodetectReqPdu->headerLength != 0x12)
{
WLog_Print(autodetect->log, WLOG_ERROR,
"autodetectReqPdu->headerLength != 0x012 [0x%02" PRIx8 "]",
autodetectReqPdu->headerLength);
2022-10-05 15:53:23 +03:00
return FALSE;
}
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 12))
return FALSE;
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
result.type = RDP_NETCHAR_RESULT_TYPE_BASE_RTT_BW_AVG_RTT;
Stream_Read_UINT32(s, result.baseRTT); /* baseRTT (4 bytes) */
Stream_Read_UINT32(s, result.bandwidth); /* bandwidth (4 bytes) */
Stream_Read_UINT32(s, result.averageRTT); /* averageRTT (4 bytes) */
break;
2022-10-05 15:25:35 +03:00
default:
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
WINPR_ASSERT(FALSE);
2022-10-05 15:25:35 +03:00
break;
}
WLog_Print(autodetect->log, WLOG_TRACE,
"received Network Characteristics Result PDU -> baseRTT=%" PRIu32
", bandwidth=%" PRIu32 ", averageRTT=%" PRIu32 "",
result.baseRTT, result.bandwidth, result.averageRTT);
IFCALLRET(autodetect->NetworkCharacteristicsResult, success, autodetect, transport,
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetectReqPdu->sequenceNumber, &result);
2022-10-05 15:53:23 +03:00
if (!success)
WLog_Print(autodetect->log, WLOG_WARN, "NetworkCharacteristicsResult failed");
return success;
2014-01-24 07:23:47 +04:00
}
state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
wStream* s)
2014-01-24 07:23:47 +04:00
{
AUTODETECT_REQ_PDU autodetectReqPdu = { 0 };
const rdpSettings* settings;
2014-01-24 07:23:47 +04:00
BOOL success = FALSE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
settings = autodetect->context->settings;
WINPR_ASSERT(settings);
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
return STATE_RUN_FAILED;
2014-01-24 07:23:47 +04:00
2019-11-06 17:24:51 +03:00
Stream_Read_UINT8(s, autodetectReqPdu.headerLength); /* headerLength (1 byte) */
Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId); /* headerTypeId (1 byte) */
2014-01-24 07:23:47 +04:00
Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
2019-11-06 17:24:51 +03:00
Stream_Read_UINT16(s, autodetectReqPdu.requestType); /* requestType (2 bytes) */
char rbuffer[128] = { 0 };
const char* requestTypeStr = autodetect_request_type_to_string_buffer(
autodetectReqPdu.requestType, rbuffer, sizeof(rbuffer));
char hbuffer[128] = { 0 };
const char* headerStr =
autodetect_header_type_string(autodetectReqPdu.headerTypeId, hbuffer, sizeof(hbuffer));
WLog_Print(autodetect->log, WLOG_TRACE,
"rdp_recv_autodetect_request_packet: headerLength=%" PRIu8
", headerTypeId=%s, sequenceNumber=%" PRIu16 ", requestType=%s",
autodetectReqPdu.headerLength, headerStr, autodetectReqPdu.sequenceNumber,
requestTypeStr);
if (!freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
{
WLog_Print(autodetect->log, WLOG_WARN,
"Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
"message but support was not enabled",
requestTypeStr);
}
2014-01-24 07:23:47 +04:00
if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
{
WLog_Print(autodetect->log, WLOG_ERROR,
"Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request [%s] "
"message with invalid headerTypeId=%s",
requestTypeStr, headerStr);
goto fail;
}
2014-01-24 07:23:47 +04:00
IFCALL(autodetect->RequestReceived, autodetect, transport, autodetectReqPdu.requestType,
autodetectReqPdu.sequenceNumber);
2014-01-24 07:23:47 +04:00
switch (autodetectReqPdu.requestType)
{
case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
/* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
success =
autodetect_recv_rtt_measure_request(autodetect, transport, s, &autodetectReqPdu);
break;
case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
case RDP_BW_START_REQUEST_TYPE_TUNNEL:
case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
/* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
success = autodetect_recv_bandwidth_measure_start(autodetect, transport, s,
&autodetectReqPdu);
break;
case RDP_BW_PAYLOAD_REQUEST_TYPE:
/* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
success = autodetect_recv_bandwidth_measure_payload(autodetect, transport, s,
&autodetectReqPdu);
break;
case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
/* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
success =
autodetect_recv_bandwidth_measure_stop(autodetect, transport, s, &autodetectReqPdu);
break;
case RDP_NETCHAR_RESULTS_0x0840:
case RDP_NETCHAR_RESULTS_0x0880:
case RDP_NETCHAR_RESULTS_0x08C0:
/* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
success = autodetect_recv_netchar_request(autodetect, transport, s, &autodetectReqPdu);
break;
default:
WLog_Print(autodetect->log, WLOG_ERROR, "Unknown requestType=0x%04" PRIx16,
autodetectReqPdu.requestType);
break;
2014-01-24 07:23:47 +04:00
}
fail:
if (success)
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->state = FREERDP_AUTODETECT_STATE_REQUEST;
else
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
2014-01-24 07:23:47 +04:00
}
state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, RDP_TRANSPORT_TYPE transport,
wStream* s)
{
AUTODETECT_RSP_PDU autodetectRspPdu = { 0 };
const rdpSettings* settings;
BOOL success = FALSE;
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->context);
WINPR_ASSERT(s);
settings = autodetect->context->settings;
WINPR_ASSERT(settings);
if (!Stream_CheckAndLogRequiredLengthWLog(autodetect->log, s, 6))
goto fail;
2019-11-06 17:24:51 +03:00
Stream_Read_UINT8(s, autodetectRspPdu.headerLength); /* headerLength (1 byte) */
Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId); /* headerTypeId (1 byte) */
Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
2019-11-06 17:24:51 +03:00
Stream_Read_UINT16(s, autodetectRspPdu.responseType); /* responseType (2 bytes) */
char rbuffer[128] = { 0 };
const char* requestStr = autodetect_request_type_to_string_buffer(autodetectRspPdu.responseType,
rbuffer, sizeof(rbuffer));
char hbuffer[128] = { 0 };
const char* headerStr =
autodetect_header_type_string(autodetectRspPdu.headerTypeId, hbuffer, sizeof(hbuffer));
WLog_Print(autodetect->log, WLOG_TRACE,
"rdp_recv_autodetect_response_packet: headerLength=%" PRIu8 ", headerTypeId=%s"
", sequenceNumber=%" PRIu16 ", requestType=%s",
autodetectRspPdu.headerLength, headerStr, autodetectRspPdu.sequenceNumber,
requestStr);
if (!freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
{
WLog_Print(autodetect->log, WLOG_WARN,
"Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
"message but support was not enabled",
requestStr);
}
if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
{
WLog_Print(autodetect->log, WLOG_ERROR,
"Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response [%s] "
"message with invalid headerTypeId=%s",
requestStr, headerStr);
goto fail;
}
IFCALL(autodetect->ResponseReceived, autodetect, transport, autodetectRspPdu.responseType,
autodetectRspPdu.sequenceNumber);
switch (autodetectRspPdu.responseType)
{
case RDP_RTT_RESPONSE_TYPE:
/* RTT Measure Response (RDP_RTT_RESPONSE) - MS-RDPBCGR 2.2.14.2.1 */
success =
autodetect_recv_rtt_measure_response(autodetect, transport, s, &autodetectRspPdu);
break;
case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
/* Bandwidth Measure Results (RDP_BW_RESULTS) - MS-RDPBCGR 2.2.14.2.2 */
success = autodetect_recv_bandwidth_measure_results(autodetect, transport, s,
&autodetectRspPdu);
break;
2022-10-05 15:25:35 +03:00
case RDP_NETCHAR_SYNC_RESPONSE_TYPE:
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
/* Network Characteristics Sync (RDP_NETCHAR_SYNC) - MS-RDPBCGR 2.2.14.2.3 */
success = autodetect_recv_netchar_sync(autodetect, transport, s, &autodetectRspPdu);
2022-10-05 15:25:35 +03:00
break;
default:
WLog_Print(autodetect->log, WLOG_ERROR, "Unknown responseType=0x%04" PRIx16,
autodetectRspPdu.responseType);
break;
}
fail:
if (success)
{
if (autodetectRspPdu.responseType == RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME)
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->state = FREERDP_AUTODETECT_STATE_COMPLETE;
else
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->state = FREERDP_AUTODETECT_STATE_RESPONSE;
}
else
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->state = FREERDP_AUTODETECT_STATE_FAIL;
return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
}
core/autodetect: Allow overriding connect-time autodetection handling Currently, FreeRDP-based server implementations can do connect-time autodetection. However, without having any control over it. In order to be able to override the default connect-time autodetection handling, introduce three new states for the state machine of the connection sequence and two new callbacks for the autodetect handling. These are: - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_BEGIN - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_IN_PROGRESS - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_END - OnConnectTimeAutoDetectBegin() - OnConnectTimeAutoDetectProgress() The END state is pretty simple: When the autodetection is finished and the autodetect state is FREERDP_AUTODETECT_STATE_COMPLETE, transition into the next state of the connection sequence. The BEGIN state is entered, when capability-wise network autodetection is available. In this state, the OnConnectTimeAutoDetectBegin callback is called, the server implementation may initialize any related handling here. If the server implementation determines, that no further handling is required, it can end the autodetection phase by returning FREERDP_AUTODETECT_STATE_COMPLETE. If not, and an autodetection request is sent, it returns FREERDP_AUTODETECT_STATE_REQUEST. The state machine of the connection sequence will then switch into the IN_PROGRESS state. In the IN_PROGRESS state, any incoming PDU is handled first, then the OnConnectTimeAutoDetectProgress callback is called. Like in the BEGIN state, the return value will determine, whether the state machine of the connection sequence goes into the END state or goes into (or rather stays) in the IN_PROGRESS state.
2023-04-09 19:34:56 +03:00
void autodetect_on_connect_time_auto_detect_begin(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectBegin);
autodetect->state = autodetect->OnConnectTimeAutoDetectBegin(autodetect);
}
void autodetect_on_connect_time_auto_detect_progress(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
WINPR_ASSERT(autodetect->OnConnectTimeAutoDetectProgress);
autodetect->state = autodetect->OnConnectTimeAutoDetectProgress(autodetect);
}
rdpAutoDetect* autodetect_new(rdpContext* context)
2014-01-24 07:23:47 +04:00
{
2019-11-06 17:24:51 +03:00
rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1, sizeof(rdpAutoDetect));
if (!autoDetect)
return NULL;
autoDetect->context = context;
autoDetect->log = WLog_Get(AUTODETECT_TAG);
2014-02-11 07:23:59 +04:00
return autoDetect;
2014-01-24 07:23:47 +04:00
}
2014-02-11 07:23:59 +04:00
void autodetect_free(rdpAutoDetect* autoDetect)
2014-01-24 07:23:47 +04:00
{
2014-02-11 07:23:59 +04:00
free(autoDetect);
2014-01-24 07:23:47 +04:00
}
void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
autodetect->RTTMeasureRequest = autodetect_send_rtt_measure_request;
autodetect->BandwidthMeasureStart = autodetect_send_bandwidth_measure_start;
autodetect->BandwidthMeasurePayload = autodetect_send_bandwidth_measure_payload;
autodetect->BandwidthMeasureStop = autodetect_send_bandwidth_measure_stop;
autodetect->NetworkCharacteristicsResult = autodetect_send_netchar_result;
core/autodetect: Allow overriding connect-time autodetection handling Currently, FreeRDP-based server implementations can do connect-time autodetection. However, without having any control over it. In order to be able to override the default connect-time autodetection handling, introduce three new states for the state machine of the connection sequence and two new callbacks for the autodetect handling. These are: - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_BEGIN - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_IN_PROGRESS - CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_END - OnConnectTimeAutoDetectBegin() - OnConnectTimeAutoDetectProgress() The END state is pretty simple: When the autodetection is finished and the autodetect state is FREERDP_AUTODETECT_STATE_COMPLETE, transition into the next state of the connection sequence. The BEGIN state is entered, when capability-wise network autodetection is available. In this state, the OnConnectTimeAutoDetectBegin callback is called, the server implementation may initialize any related handling here. If the server implementation determines, that no further handling is required, it can end the autodetection phase by returning FREERDP_AUTODETECT_STATE_COMPLETE. If not, and an autodetection request is sent, it returns FREERDP_AUTODETECT_STATE_REQUEST. The state machine of the connection sequence will then switch into the IN_PROGRESS state. In the IN_PROGRESS state, any incoming PDU is handled first, then the OnConnectTimeAutoDetectProgress callback is called. Like in the BEGIN state, the return value will determine, whether the state machine of the connection sequence goes into the END state or goes into (or rather stays) in the IN_PROGRESS state.
2023-04-09 19:34:56 +03:00
/*
* Default handlers for Connect-Time Auto-Detection
* (MAY be overridden by the API user)
*/
autodetect->OnConnectTimeAutoDetectBegin = autodetect_on_connect_time_auto_detect_begin_default;
autodetect->OnConnectTimeAutoDetectProgress =
autodetect_on_connect_time_auto_detect_progress_default;
}
core/autodetect: Rework server side API to be closer to documentation The current state of the autodetect API for the server side does not include all allowed scenarios where the network autodetection can be used. This for example includes the connect-time autodetection, as the related calls are hidden inside FreeRDP, and not exposed as public API. In order to avoid duplicate send methods, check the state of the connection sequence. If the connection sequence is not yet done, use the connect-time request types. Otherwise, use the continuous request types. The Bandwidth Measure Payload PDU is a little special case, as it is only allowed to be sent during the connection sequence. To ensure this, add an assertion in its sending method. Also fix the handling for the Network Characteristics Sync PDU: Previously, after parsing the PDU data, the read data was just sent again to the client, which is wrong. To fix this issue, introduce a callback for this client-to-server PDU, so that the actual server implementation can hook up its own handling for this PDU. Depending on the situation, the server side may want to discard or use the retrieved data here. Moreover, decouple the send-handling for the Network Characteristics Result PDU from the local autodetect variables. Currently, these variables are shared between the send and receive methods. This leads to access problems, where the server side, wants to use a different thread to send the autodetect PDU, as the receive handler may receive an autodetect PDU and overwrite these values with possible nonsense values. This is especially the case with RTT response PDUs, as the written netCharAverageRTT and netCharBaseRTT values are only correct, when only one RTTRequest happens at a time and no stray RTTResponses are received.
2023-04-09 10:59:34 +03:00
FREERDP_AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect)
{
WINPR_ASSERT(autodetect);
return autodetect->state;
}
rdpAutoDetect* autodetect_get(rdpContext* context)
{
WINPR_ASSERT(context);
WINPR_ASSERT(context->rdp);
return context->rdp->autodetect;
}