[core] Unify RDP state machine

Up to this commit the client and server state machine handling used
different return values for state machine changes.
This is fixed with this commit:
* Use common enum return values
* Use common helper functions
This commit is contained in:
akallabeth 2022-11-11 12:26:28 +01:00 committed by akallabeth
parent 8760cecbc7
commit bc31bae2b5
22 changed files with 419 additions and 327 deletions

View File

@ -48,6 +48,8 @@ set(${MODULE_PREFIX}_GATEWAY_SRCS
${${MODULE_PREFIX}_GATEWAY_DIR}/ncacn_http.h)
set(${MODULE_PREFIX}_SRCS
state.h
state.c
utils.c
utils.h
streamdump.c

View File

@ -735,7 +735,7 @@ static BOOL autodetect_recv_netchar_request(rdpAutoDetect* autodetect, wStream*
return success;
}
int autodetect_recv_request_packet(rdpAutoDetect* autodetect, wStream* s)
state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, wStream* s)
{
AUTODETECT_REQ_PDU autodetectReqPdu = { 0 };
const rdpSettings* settings;
@ -748,7 +748,7 @@ int autodetect_recv_request_packet(rdpAutoDetect* autodetect, wStream* s)
WINPR_ASSERT(settings);
if (!Stream_CheckAndLogRequiredLength(AUTODETECT_TAG, s, 6))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT8(s, autodetectReqPdu.headerLength); /* headerLength (1 byte) */
Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId); /* headerTypeId (1 byte) */
@ -823,10 +823,10 @@ fail:
autodetect->state = AUTODETECT_STATE_REQUEST;
else
autodetect->state = AUTODETECT_STATE_FAIL;
return success ? 0 : -1;
return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
}
int autodetect_recv_response_packet(rdpAutoDetect* autodetect, wStream* s)
state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, wStream* s)
{
AUTODETECT_RSP_PDU autodetectRspPdu = { 0 };
const rdpSettings* settings;
@ -904,7 +904,7 @@ fail:
else
autodetect->state = AUTODETECT_STATE_FAIL;
return success ? 0 : -1;
return success ? STATE_RUN_SUCCESS : STATE_RUN_FAILED;
}
rdpAutoDetect* autodetect_new(rdpContext* context)

View File

@ -30,6 +30,8 @@
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include "state.h"
typedef enum
{
AUTODETECT_STATE_INITIAL,
@ -41,8 +43,8 @@ typedef enum
FREERDP_LOCAL rdpAutoDetect* autodetect_new(rdpContext* context);
FREERDP_LOCAL void autodetect_free(rdpAutoDetect* autodetect);
FREERDP_LOCAL int autodetect_recv_request_packet(rdpAutoDetect* autodetect, wStream* s);
FREERDP_LOCAL int autodetect_recv_response_packet(rdpAutoDetect* autodetect, wStream* s);
FREERDP_LOCAL state_run_t autodetect_recv_request_packet(rdpAutoDetect* autodetect, wStream* s);
FREERDP_LOCAL state_run_t autodetect_recv_response_packet(rdpAutoDetect* autodetect, wStream* s);
FREERDP_LOCAL AUTODETECT_STATE autodetect_get_state(rdpAutoDetect* autodetect);

View File

@ -4505,7 +4505,8 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
* We can receive a Save Session Info Data PDU containing a LogonErrorInfo
* structure at this point from the server to indicate a connection error.
*/
if (rdp_recv_data_pdu(rdp, s) < 0)
state_run_t rc = rdp_recv_data_pdu(rdp, s);
if (state_run_failed(rc))
return FALSE;
return FALSE;

View File

@ -185,7 +185,7 @@
*channel messages (exchanged between client-side plug-ins and server-side applications).
*/
static int rdp_client_connect_finalize(rdpRdp* rdp);
static state_run_t rdp_client_connect_finalize(rdpRdp* rdp);
static BOOL rdp_set_state(rdpRdp* rdp, CONNECTION_STATE state);
static BOOL rdp_client_reset_codecs(rdpContext* context)
@ -383,7 +383,8 @@ BOOL rdp_client_connect(rdpRdp* rdp)
}
/* everything beyond this point is event-driven and non blocking */
transport_set_recv_callbacks(rdp->transport, rdp_recv_callback, rdp);
if (!transport_set_recv_callbacks(rdp->transport, rdp_recv_callback, rdp))
return FALSE;
now = GetTickCount64();
dueDate = now + freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
@ -1098,30 +1099,30 @@ BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s)
return FALSE;
}
int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
state_run_t rdp_client_connect_license(rdpRdp* rdp, wStream* s)
{
int status;
state_run_t status = STATE_RUN_FAILED;
LICENSE_STATE state;
UINT16 length, channelId, securityFlags;
if (!rdp_read_header(rdp, s, &length, &channelId))
return -1;
return STATE_RUN_FAILED;
if (!rdp_read_security_header(s, &securityFlags, &length))
return -1;
return STATE_RUN_FAILED;
if (securityFlags & SEC_ENCRYPT)
{
if (!rdp_decrypt(rdp, s, &length, securityFlags))
return -1;
return STATE_RUN_FAILED;
}
if ((securityFlags & SEC_LICENSE_PKT) == 0)
return -1;
return STATE_RUN_FAILED;
status = license_recv(rdp->license, s);
if (status < 0)
if (state_run_failed(status))
return status;
state = license_get_state(rdp->license);
@ -1129,7 +1130,7 @@ int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
{
case LICENSE_STATE_ABORTED:
WLog_ERR(TAG, "license connection sequence aborted.");
return -1;
return STATE_RUN_FAILED;
case LICENSE_STATE_COMPLETED:
if (rdp->settings->MultitransportFlags)
{
@ -1141,13 +1142,13 @@ int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
rdp_client_transition_to_state(
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
}
return 0;
return STATE_RUN_SUCCESS;
default:
return 0;
return STATE_RUN_SUCCESS;
}
}
int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
state_run_t rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
{
size_t pos;
UINT16 length;
@ -1160,28 +1161,28 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
if (!rdp_recv_demand_active(rdp, s))
{
int rc;
state_run_t rc;
UINT16 channelId;
Stream_SetPosition(s, pos);
if (!rdp_recv_get_active_header(rdp, s, &channelId, &length))
return -1;
return STATE_RUN_FAILED;
/* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH);
* but the headers aren't always that length,
* so that could result in a bad offset.
*/
rc = rdp_recv_out_of_sequence_pdu(rdp, s);
if (rc < 0)
if (state_run_failed(rc))
return rc;
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return STATE_RUN_FAILED;
return rc;
}
return 0;
return STATE_RUN_SUCCESS;
}
int rdp_client_connect_finalize(rdpRdp* rdp)
state_run_t rdp_client_connect_finalize(rdpRdp* rdp)
{
/**
* [MS-RDPBCGR] 1.3.1.1 - 8.
@ -1191,15 +1192,15 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
*/
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_SYNC);
if (!rdp_send_client_synchronize_pdu(rdp))
return -1;
return STATE_RUN_FAILED;
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_COOPERATE);
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_COOPERATE))
return -1;
return STATE_RUN_FAILED;
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL);
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL))
return -1;
return STATE_RUN_FAILED;
/**
* [MS-RDPBCGR] 2.2.1.17
@ -1213,15 +1214,15 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
{
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST);
if (!rdp_send_client_persistent_key_list_pdu(rdp))
return -1;
return STATE_RUN_FAILED;
}
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_FONT_LIST);
if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST))
return -1;
return STATE_RUN_FAILED;
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_SYNC);
return 0;
return STATE_RUN_SUCCESS;
}
BOOL rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state)
@ -1711,7 +1712,7 @@ BOOL rdp_channels_from_mcs(rdpSettings* settings, const rdpRdp* rdp)
return TRUE;
}
int rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s)
state_run_t rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s)
{
WINPR_ASSERT(rdp);
WINPR_ASSERT(rdp->settings);
@ -1721,12 +1722,12 @@ int rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s)
const UINT32 height = rdp->settings->DesktopHeight;
if (!rdp_send_confirm_active(rdp))
return -1;
return STATE_RUN_FAILED;
if (!input_register_client_callbacks(rdp->input))
{
WLog_ERR(TAG, "error registering client callbacks");
return -1;
return STATE_RUN_FAILED;
}
/**
@ -1746,13 +1747,13 @@ int rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s)
if (!status)
{
WLog_ERR(TAG, "client desktop resize callback failed");
return -1;
return STATE_RUN_FAILED;
}
}
WINPR_ASSERT(rdp->context);
if (freerdp_shall_disconnect_context(rdp->context))
return 0;
return STATE_RUN_SUCCESS;
return rdp_client_connect_finalize(rdp);
}

View File

@ -26,6 +26,7 @@
#include "nego.h"
#include "mcs.h"
#include "activation.h"
#include "state.h"
#include <freerdp/settings.h>
#include <freerdp/api.h>
@ -44,9 +45,9 @@ FREERDP_LOCAL BOOL rdp_client_reconnect(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_client_redirect(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_client_connect_license(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state);
FREERDP_LOCAL CONNECTION_STATE rdp_get_state(const rdpRdp* rdp);

View File

@ -616,13 +616,13 @@ out_fail:
return -1;
}
int fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
state_run_t fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
{
int rc = -2;
state_run_t rc = STATE_RUN_FAILED;
rdpUpdate* update;
if (!fastpath || !fastpath->rdp || !fastpath->rdp->update || !s)
return -1;
return STATE_RUN_FAILED;
update = fastpath->rdp->update;
@ -634,16 +634,16 @@ int fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
if (fastpath_recv_update_data(fastpath, s) < 0)
{
WLog_ERR(TAG, "fastpath_recv_update_data() fail");
rc = -3;
rc = STATE_RUN_FAILED;
goto fail;
}
}
rc = 0;
rc = STATE_RUN_SUCCESS;
fail:
if (!update_end_paint(update))
return -4;
return STATE_RUN_FAILED;
return rc;
}
@ -832,7 +832,7 @@ static BOOL fastpath_recv_input_event(rdpFastPath* fastpath, wStream* s)
return TRUE;
}
int fastpath_recv_inputs(rdpFastPath* fastpath, wStream* s)
state_run_t fastpath_recv_inputs(rdpFastPath* fastpath, wStream* s)
{
BYTE i;
@ -846,7 +846,7 @@ int fastpath_recv_inputs(rdpFastPath* fastpath, wStream* s)
* as one additional byte here.
*/
if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT8(s, fastpath->numberEvents); /* eventHeader (1 byte) */
}
@ -854,10 +854,10 @@ int fastpath_recv_inputs(rdpFastPath* fastpath, wStream* s)
for (i = 0; i < fastpath->numberEvents; i++)
{
if (!fastpath_recv_input_event(fastpath, s))
return -1;
return STATE_RUN_FAILED;
}
return 0;
return STATE_RUN_SUCCESS;
}
static UINT32 fastpath_get_sec_bytes(rdpRdp* rdp)

View File

@ -23,7 +23,7 @@
#include "heartbeat.h"
int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
state_run_t rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
{
BYTE reserved;
BYTE period;
@ -36,7 +36,7 @@ int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
WINPR_ASSERT(s);
if (!Stream_CheckAndLogRequiredLength(AUTODETECT_TAG, s, 4))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT8(s, reserved); /* reserved (1 byte) */
Stream_Read_UINT8(s, period); /* period (1 byte) */
@ -52,10 +52,10 @@ int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
if (!rc)
{
WLog_ERR(HEARTBEAT_TAG, "heartbeat->ServerHeartbeat callback failed!");
return -1;
return STATE_RUN_FAILED;
}
return 0;
return STATE_RUN_SUCCESS;
}
BOOL freerdp_heartbeat_send_heartbeat_pdu(freerdp_peer* peer, BYTE period, BYTE count1, BYTE count2)

View File

@ -29,7 +29,9 @@
#include <winpr/stream.h>
int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s);
#include "state.h"
FREERDP_LOCAL state_run_t rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL rdpHeartbeat* heartbeat_new(void);
FREERDP_LOCAL void heartbeat_free(rdpHeartbeat* heartbeat);

View File

@ -336,8 +336,8 @@ static BOOL license_write_server_upgrade_license(const rdpLicense* license, wStr
static BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
BYTE* signature);
static BOOL license_read_license_info(rdpLicense* license, wStream* s);
static int license_client_recv(rdpLicense* license, wStream* s);
static int license_server_recv(rdpLicense* license, wStream* s);
static state_run_t license_client_recv(rdpLicense* license, wStream* s);
static state_run_t license_server_recv(rdpLicense* license, wStream* s);
#define PLATFORMID (CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT)
@ -422,7 +422,7 @@ static BOOL license_ensure_state(rdpLicense* license, LICENSE_STATE state, UINT3
return TRUE;
}
int license_recv(rdpLicense* license, wStream* s)
state_run_t license_recv(rdpLicense* license, wStream* s)
{
WINPR_ASSERT(license);
WINPR_ASSERT(license->rdp);
@ -837,7 +837,7 @@ int license_client_recv(rdpLicense* license, wStream* s)
WINPR_ASSERT(license);
if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
return -1;
return STATE_RUN_FAILED;
DEBUG_LICENSE("Receiving %s Packet", license_request_type_string(bMsgType));
@ -849,55 +849,55 @@ int license_client_recv(rdpLicense* license, wStream* s)
license_set_state(license, LICENSE_STATE_CONFIGURED);
if (!license_ensure_state(license, LICENSE_STATE_CONFIGURED, bMsgType))
return -1;
return STATE_RUN_FAILED;
if (!license_read_license_request_packet(license, s))
return -1;
return STATE_RUN_FAILED;
if (!license_answer_license_request(license))
return -1;
return STATE_RUN_FAILED;
license_set_state(license, LICENSE_STATE_NEW_REQUEST);
break;
case PLATFORM_CHALLENGE:
if (!license_ensure_state(license, LICENSE_STATE_NEW_REQUEST, bMsgType))
return -1;
return STATE_RUN_FAILED;
if (!license_read_platform_challenge_packet(license, s))
return -1;
return STATE_RUN_FAILED;
if (!license_send_platform_challenge_response(license))
return -1;
return STATE_RUN_FAILED;
license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE);
break;
case NEW_LICENSE:
case UPGRADE_LICENSE:
if (!license_ensure_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE, bMsgType))
return -1;
return STATE_RUN_FAILED;
if (!license_read_new_or_upgrade_license_packet(license, s))
return -1;
return STATE_RUN_FAILED;
break;
case ERROR_ALERT:
if (!license_read_error_alert_packet(license, s))
return -1;
return STATE_RUN_FAILED;
break;
default:
WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
return -1;
return STATE_RUN_FAILED;
}
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return 0;
return STATE_RUN_FAILED;
return STATE_RUN_SUCCESS;
}
int license_server_recv(rdpLicense* license, wStream* s)
state_run_t license_server_recv(rdpLicense* license, wStream* s)
{
int rc = -1;
state_run_t rc = STATE_RUN_FAILED;
BYTE flags;
BYTE bMsgType;
UINT16 wMsgSize;
@ -961,7 +961,7 @@ int license_server_recv(rdpLicense* license, wStream* s)
license->type = LICENSE_TYPE_ISSUED;
license_set_state(license, LICENSE_STATE_COMPLETED);
rc = 2; /* License issued, switch state */
rc = STATE_RUN_CONTINUE; /* License issued, switch state */
}
break;
@ -978,11 +978,11 @@ int license_server_recv(rdpLicense* license, wStream* s)
if (!tpkt_ensure_stream_consumed(s, length))
goto fail;
if (rc < 0)
rc = 0;
if (!state_run_success(rc))
rc = STATE_RUN_SUCCESS;
fail:
if (rc < 0)
if (state_run_failed(rc))
{
if (flags & EXTENDED_ERROR_MSG_SUPPORTED)
license_send_error_alert(license, ERR_INVALID_CLIENT, ST_TOTAL_ABORT, NULL);

View File

@ -23,6 +23,7 @@
#define FREERDP_LIB_CORE_LICENSE_H
#include "rdp.h"
#include "state.h"
#include <freerdp/crypto/crypto.h>
#include <freerdp/crypto/certificate.h>
@ -58,7 +59,7 @@ typedef struct
FREERDP_LOCAL BOOL license_send_valid_client_error_packet(rdpRdp* rdp);
FREERDP_LOCAL int license_recv(rdpLicense* license, wStream* s);
FREERDP_LOCAL state_run_t license_recv(rdpLicense* license, wStream* s);
/* the configuration is applied from settings. Set FreeRDP_ServerLicense* settings */
FREERDP_LOCAL BOOL license_server_configure(rdpLicense* license);

View File

@ -72,12 +72,12 @@ static BOOL multitransport_compare(const rdpMultitransport* srv, const rdpMultit
return TRUE;
}
int multitransport_client_recv_request(rdpMultitransport* multitransport, wStream* s)
state_run_t multitransport_client_recv_request(rdpMultitransport* multitransport, wStream* s)
{
WINPR_ASSERT(multitransport);
if (!Stream_CheckAndLogRequiredLength(TAG, s, 24))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, multitransport->requestId); /* requestId (4 bytes) */
Stream_Read_UINT16(s, multitransport->requestedProtocol); /* requestedProtocol (2 bytes) */
@ -85,7 +85,7 @@ int multitransport_client_recv_request(rdpMultitransport* multitransport, wStrea
Stream_Read(s, multitransport->securityCookie,
sizeof(multitransport->securityCookie)); /* securityCookie (16 bytes) */
return 0;
return STATE_RUN_SUCCESS;
}
BOOL multitransport_server_send_request(rdpMultitransport* multitransport)

View File

@ -23,6 +23,7 @@
typedef struct rdp_multitransport rdpMultitransport;
#include "rdp.h"
#include "state.h"
#include <freerdp/freerdp.h>
#include <freerdp/api.h>
@ -35,7 +36,8 @@ typedef enum
INITIATE_REQUEST_PROTOCOL_UDPFECL = 0x02
} MultitransportRequestProtocol;
FREERDP_LOCAL int multitransport_client_recv_request(rdpMultitransport* multitransport, wStream* s);
FREERDP_LOCAL state_run_t multitransport_client_recv_request(rdpMultitransport* multitransport,
wStream* s);
FREERDP_LOCAL BOOL multitransport_server_send_request(rdpMultitransport* multitransport);
FREERDP_LOCAL BOOL multitransport_server_recv_response(rdpMultitransport* multitransport,

View File

@ -36,7 +36,7 @@
#define TAG FREERDP_TAG("core.peer")
static int peer_recv_pdu(freerdp_peer* client, wStream* s);
static state_run_t peer_recv_pdu(freerdp_peer* client, wStream* s);
static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char* name,
UINT32 flags)
@ -322,7 +322,7 @@ static BOOL freerdp_peer_check_fds(freerdp_peer* peer)
return TRUE;
}
static int peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLength)
static state_run_t peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLength)
{
BYTE type;
UINT16 length;
@ -342,7 +342,7 @@ static int peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLeng
if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type,
&compressed_len))
return -1;
return STATE_RUN_FAILED;
#ifdef WITH_DEBUG_RDP
WLog_DBG(TAG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "",
@ -353,40 +353,40 @@ static int peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLeng
{
case DATA_PDU_TYPE_SYNCHRONIZE:
if (!rdp_recv_client_synchronize_pdu(client->context->rdp, s))
return -1;
return STATE_RUN_FAILED;
break;
case DATA_PDU_TYPE_CONTROL:
if (!rdp_server_accept_client_control_pdu(client->context->rdp, s))
return -1;
return STATE_RUN_FAILED;
break;
case DATA_PDU_TYPE_INPUT:
if (!input_recv(client->context->rdp->input, s))
return -1;
return STATE_RUN_FAILED;
break;
case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST:
if (!rdp_server_accept_client_persistent_key_list_pdu(client->context->rdp, s))
return -1;
return STATE_RUN_FAILED;
break;
case DATA_PDU_TYPE_FONT_LIST:
if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s))
return -1;
return STATE_RUN_FAILED;
return 1; // State changed, trigger rerun
return STATE_RUN_CONTINUE; // State changed, trigger rerun
case DATA_PDU_TYPE_SHUTDOWN_REQUEST:
mcs_send_disconnect_provider_ultimatum(client->context->rdp->mcs);
return -1;
return STATE_RUN_FAILED;
case DATA_PDU_TYPE_FRAME_ACKNOWLEDGE:
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, client->ack_frame_id);
IFCALL(update->SurfaceFrameAcknowledge, update->context, client->ack_frame_id);
@ -394,13 +394,13 @@ static int peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLeng
case DATA_PDU_TYPE_REFRESH_RECT:
if (!update_read_refresh_rect(update, s))
return -1;
return STATE_RUN_FAILED;
break;
case DATA_PDU_TYPE_SUPPRESS_OUTPUT:
if (!update_read_suppress_output(update, s))
return -1;
return STATE_RUN_FAILED;
break;
@ -409,11 +409,12 @@ static int peer_recv_data_pdu(freerdp_peer* client, wStream* s, UINT16 totalLeng
break;
}
return 0;
return STATE_RUN_SUCCESS;
}
static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
static state_run_t peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
{
state_run_t rc = STATE_RUN_SUCCESS;
rdpRdp* rdp;
UINT16 length;
UINT16 pduType;
@ -434,16 +435,16 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
WINPR_ASSERT(settings);
if (!rdp_read_header(rdp, s, &length, &channelId))
return -1;
return STATE_RUN_FAILED;
rdp->inPackets++;
if (freerdp_shall_disconnect_context(rdp->context))
return 0;
return STATE_RUN_SUCCESS;
if (rdp_get_state(rdp) <= CONNECTION_STATE_LICENSING)
{
if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
return STATE_RUN_FAILED;
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
}
@ -451,12 +452,12 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
if (settings->UseRdpSecurityLayer)
{
if (!rdp_read_security_header(s, &securityFlags, &length))
return -1;
return STATE_RUN_FAILED;
if (securityFlags & SEC_ENCRYPT)
{
if (!rdp_decrypt(rdp, s, &length, securityFlags))
return -1;
return STATE_RUN_FAILED;
}
}
@ -464,7 +465,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
{
UINT16 pduLength, remain;
if (!rdp_read_share_control_header(s, &pduLength, &remain, &pduType, &pduSource))
return -1;
return STATE_RUN_FAILED;
settings->PduSource = pduSource;
@ -472,11 +473,12 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
switch (pduType)
{
case PDU_TYPE_DATA:
return peer_recv_data_pdu(client, s, pduLength);
rc = peer_recv_data_pdu(client, s, pduLength);
break;
case PDU_TYPE_CONFIRM_ACTIVE:
if (!rdp_server_accept_confirm_active(rdp, s, pduLength))
return -1;
return STATE_RUN_FAILED;
break;
@ -487,37 +489,39 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
{
WLog_WARN(TAG, "Short PDU, need %" PRIuz " bytes, got %" PRIuz, remain,
Stream_GetRemainingLength(s));
return -1;
return STATE_RUN_FAILED;
}
break;
default:
WLog_ERR(TAG, "Client sent unknown pduType %" PRIu16 "", pduType);
return -1;
return STATE_RUN_FAILED;
}
}
else if ((rdp->mcs->messageChannelId > 0) && (channelId == rdp->mcs->messageChannelId))
{
if (!settings->UseRdpSecurityLayer)
{
if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
return STATE_RUN_FAILED;
}
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
}
else
{
if (!freerdp_channel_peer_process(client, s, channelId))
return -1;
return STATE_RUN_FAILED;
}
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return STATE_RUN_FAILED;
return 0;
return rc;
}
static int peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
static state_run_t peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
{
int ret = -1;
state_run_t ret = STATE_RUN_FAILED;
rdpRdp* rdp;
rdpSettings* settings;
@ -538,7 +542,7 @@ static int peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
{
if (autodetect_send_connecttime_rtt_measure_request(rdp->autodetect, 0x23))
ret = 0;
ret = STATE_RUN_SUCCESS;
rdp_server_transition_to_state(rdp,
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE);
}
@ -546,17 +550,17 @@ static int peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
{
ret = peer_recv_pdu(client, s);
if (ret >= 0)
if (state_run_success(ret))
{
switch (autodetect_get_state(rdp->autodetect))
{
case AUTODETECT_STATE_COMPLETE:
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
ret = 1; /* Rerun in next state */
ret = STATE_RUN_CONTINUE; /* Rerun in next state */
break;
case AUTODETECT_STATE_RESPONSE:
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
ret = 1; /* Rerun in next state */
ret = STATE_RUN_CONTINUE; /* Rerun in next state */
break;
default:
break;
@ -573,15 +577,15 @@ static int peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
{
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
ret = 1; /* Rerun in next state */
ret = STATE_RUN_CONTINUE; /* Rerun in next state */
}
return ret;
}
static int peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
static state_run_t peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
{
int ret = -1;
state_run_t ret = STATE_RUN_FAILED;
rdpRdp* rdp;
rdpSettings* settings;
@ -606,24 +610,24 @@ static int peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
if (required)
{
if (!license_server_configure(rdp->license))
ret = -3;
ret = STATE_RUN_FAILED;
else if (!license_server_send_request(rdp->license))
ret = -2;
ret = STATE_RUN_FAILED;
else
ret = 0;
ret = STATE_RUN_SUCCESS;
}
else
{
if (license_send_valid_client_error_packet(rdp))
ret = 1; /* Rerun in next state, might be capabilities */
ret = STATE_RUN_CONTINUE; /* Rerun in next state, might be capabilities */
}
}
break;
case LICENSE_STATE_COMPLETED:
ret = 1; /* Licensing completed, continue in next state */
ret = STATE_RUN_CONTINUE; /* Licensing completed, continue in next state */
break;
case LICENSE_STATE_ABORTED:
ret = -1;
ret = STATE_RUN_FAILED;
break;
default:
ret = peer_recv_pdu(client, s);
@ -633,7 +637,7 @@ static int peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
return ret;
}
static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
static state_run_t peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
{
rdpRdp* rdp;
UINT16 length;
@ -655,10 +659,10 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
if (!rc || (length == 0))
{
WLog_ERR(TAG, "incorrect FastPath PDU header length %" PRIu16 "", length);
return -1;
return STATE_RUN_FAILED;
}
if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
return -1;
return STATE_RUN_FAILED;
if (fastpath_get_encryption_flags(fastpath) & FASTPATH_OUTPUT_ENCRYPTED)
{
@ -666,7 +670,7 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
(fastpath_get_encryption_flags(fastpath) & FASTPATH_OUTPUT_SECURE_CHECKSUM)
? SEC_SECURE_CHECKSUM
: 0))
return -1;
return STATE_RUN_FAILED;
}
rdp->inPackets++;
@ -674,7 +678,7 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
return fastpath_recv_inputs(fastpath, s);
}
int peer_recv_pdu(freerdp_peer* client, wStream* s)
state_run_t peer_recv_pdu(freerdp_peer* client, wStream* s)
{
int rc = tpkt_verify_header(s);
@ -683,20 +687,20 @@ int peer_recv_pdu(freerdp_peer* client, wStream* s)
else if (rc == 0)
return peer_recv_fastpath_pdu(client, s);
else
return rc;
return STATE_RUN_FAILED;
}
static int peer_unexpected_client_message(rdpRdp* rdp, UINT32 flag)
static state_run_t peer_unexpected_client_message(rdpRdp* rdp, UINT32 flag)
{
char buffer[1024] = { 0 };
WLog_WARN(TAG, "Unexpected client message in state %s, missing flag %s",
rdp_get_state_string(rdp), rdp_finalize_flags_to_str(flag, buffer, sizeof(buffer)));
return 0; /* we ignore this as per spec input PDU are already allowed */
return STATE_RUN_SUCCESS; /* we ignore this as per spec input PDU are already allowed */
}
int rdp_peer_handle_state_demand_active(freerdp_peer* client)
state_run_t rdp_peer_handle_state_demand_active(freerdp_peer* client)
{
int ret = -1;
state_run_t ret = STATE_RUN_FAILED;
WINPR_ASSERT(client);
WINPR_ASSERT(client->context);
@ -716,7 +720,7 @@ int rdp_peer_handle_state_demand_active(freerdp_peer* client)
else
{
rdp_server_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT);
ret = 1;
ret = STATE_RUN_CONTINUE;
}
return ret;
}
@ -727,9 +731,9 @@ int rdp_peer_handle_state_demand_active(freerdp_peer* client)
* \return -1 in case of an error, 0 if no data needs to be processed, 1 to let
* the state machine run again and 2 if peer_recv_pdu must be called.
*/
static int rdp_peer_handle_state_active(freerdp_peer* client)
static state_run_t rdp_peer_handle_state_active(freerdp_peer* client)
{
int ret = -1;
state_run_t ret = STATE_RUN_FAILED;
WINPR_ASSERT(client);
WINPR_ASSERT(client->context);
@ -750,11 +754,11 @@ static int rdp_peer_handle_state_active(freerdp_peer* client)
switch (rdp_get_state(rdp))
{
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
ret = 1;
ret = STATE_RUN_CONTINUE;
break;
case CONNECTION_STATE_ACTIVE:
default:
ret = -24;
ret = STATE_RUN_FAILED;
break;
}
}
@ -763,21 +767,21 @@ static int rdp_peer_handle_state_active(freerdp_peer* client)
IFCALLRET(client->Activate, client->activated, client);
if (!client->activated)
ret = -23;
ret = STATE_RUN_FAILED;
else
ret = 0;
ret = STATE_RUN_SUCCESS;
}
else
ret = 2;
ret = STATE_RUN_ACTIVE;
return ret;
}
static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void* extra)
static state_run_t peer_recv_callback_internal(rdpTransport* transport, wStream* s, void* extra)
{
UINT32 SelectedProtocol;
freerdp_peer* client = (freerdp_peer*)extra;
rdpRdp* rdp;
int ret = -1;
state_run_t ret = STATE_RUN_FAILED;
rdpSettings* settings;
WINPR_ASSERT(transport);
@ -795,7 +799,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
{
case CONNECTION_STATE_INITIAL:
rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO);
ret = 1;
ret = STATE_RUN_CONTINUE;
break;
case CONNECTION_STATE_NEGO:
@ -825,7 +829,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
FALSE);
}
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST);
ret = 0;
ret = STATE_RUN_SUCCESS;
}
break;
@ -842,7 +846,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
__FUNCTION__, rdp_get_state_string(rdp));
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
break;
@ -855,7 +859,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
__FUNCTION__, rdp_get_state_string(rdp));
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
break;
@ -868,7 +872,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
__FUNCTION__, rdp_get_state_string(rdp));
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
break;
@ -881,11 +885,11 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
__FUNCTION__, rdp_get_state_string(rdp));
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
break;
case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
ret = 0;
ret = STATE_RUN_SUCCESS;
if (rdp->settings->UseRdpSecurityLayer)
{
if (!rdp_server_establish_keys(rdp, s))
@ -894,15 +898,15 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
"%s: %s - "
"rdp_server_establish_keys() fail",
__FUNCTION__, rdp_get_state_string(rdp));
ret = -1;
ret = STATE_RUN_FAILED;
}
}
if (ret >= 0)
if (state_run_success(ret))
{
rdp_server_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
if (Stream_GetRemainingLength(s) > 0)
ret = 1; /* Rerun function */
ret = STATE_RUN_CONTINUE; /* Rerun function */
}
break;
@ -918,7 +922,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
{
rdp_server_transition_to_state(rdp,
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST);
ret = 1;
ret = STATE_RUN_CONTINUE;
}
break;
@ -931,13 +935,13 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
else
{
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
ret = 1;
ret = STATE_RUN_CONTINUE;
}
break;
case CONNECTION_STATE_LICENSING:
ret = peer_recv_handle_licensing(client, s);
if (ret > 0)
if (ret == STATE_RUN_CONTINUE)
rdp_server_transition_to_state(
rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST);
break;
@ -946,19 +950,19 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
if (settings->SupportMultitransport)
{
if (!multitransport_server_send_request(rdp->multitransport))
ret = -23;
ret = STATE_RUN_FAILED;
else
{
rdp_server_transition_to_state(
rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE);
ret = 1;
ret = STATE_RUN_CONTINUE;
}
}
else
{
rdp_server_transition_to_state(
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
ret = 1; /* Rerun, initialize next state */
ret = STATE_RUN_CONTINUE; /* Rerun, initialize next state */
}
break;
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE:
@ -977,7 +981,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
IFCALL(client->AdjustMonitorsLayout, client);
/* client supports the monitorLayout PDU, let's send him the monitors if any */
ret = -1;
ret = STATE_RUN_SUCCESS;
if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) == 0)
{
const UINT32 w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
@ -996,27 +1000,29 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
.deviceScaleFactor = 100 } };
if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorDefArray, 0,
&primary))
ret = -2;
ret = STATE_RUN_FAILED;
else if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1))
ret = -3;
ret = STATE_RUN_FAILED;
}
if (ret < -1)
if (state_run_failed(ret))
{
}
else if (!display_convert_rdp_monitor_to_monitor_def(
settings->MonitorCount, settings->MonitorDefArray, &monitors))
{
ret = STATE_RUN_FAILED;
}
else if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount,
monitors))
{
ret = STATE_RUN_FAILED;
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
free(monitors);
}
else
ret = 0;
ret = STATE_RUN_SUCCESS;
rdp_server_transition_to_state(rdp,
CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE);
break;
@ -1035,7 +1041,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
{
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_COOPERATE))
ret = -2;
ret = STATE_RUN_FAILED;
}
else
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
@ -1046,7 +1052,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
{
if (!rdp_server_transition_to_state(rdp,
CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL))
ret = -2;
ret = STATE_RUN_FAILED;
}
else
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
@ -1057,7 +1063,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
{
if (!rdp_server_transition_to_state(
rdp, CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST))
ret = -2;
ret = STATE_RUN_FAILED;
}
else
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
@ -1072,7 +1078,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
{
if (!rdp_server_transition_to_state(rdp,
CONNECTION_STATE_FINALIZATION_FONT_LIST))
ret = -2;
ret = STATE_RUN_FAILED;
}
else
ret = peer_unexpected_client_message(rdp,
@ -1081,21 +1087,21 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
else
{
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_FONT_LIST))
ret = -2;
ret = STATE_RUN_FAILED;
else
ret = 1;
ret = STATE_RUN_CONTINUE;
}
break;
case CONNECTION_STATE_FINALIZATION_FONT_LIST:
ret = peer_recv_pdu(client, s);
if (ret >= 0)
if (state_run_success(ret))
{
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_FONT_LIST_PDU))
{
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
ret = -2;
ret = STATE_RUN_FAILED;
update_reset_state(rdp->update);
ret = 1;
ret = STATE_RUN_CONTINUE;
}
else
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_FONT_LIST_PDU);
@ -1104,7 +1110,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
case CONNECTION_STATE_ACTIVE:
ret = rdp_peer_handle_state_active(client);
if (ret > 1)
if (ret >= STATE_RUN_ACTIVE)
ret = peer_recv_pdu(client, s);
break;
@ -1121,18 +1127,26 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
return ret;
}
static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
static state_run_t peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
{
int rc = 0;
char buffer[64] = { 0 };
state_run_t rc = STATE_RUN_FAILED;
const size_t start = Stream_GetPosition(s);
const rdpContext* context = transport_get_context(transport);
WINPR_ASSERT(context);
do
{
switch (rc)
{
default:
rc = peer_recv_callback_internal(transport, s, extra);
break;
}
} while (rc > 0);
const rdpRdp* rdp = context->rdp;
const char* old = rdp_get_state_string(rdp);
if (rc == STATE_RUN_TRY_AGAIN)
Stream_SetPosition(s, start);
rc = peer_recv_callback_internal(transport, s, extra);
WLog_VRB(TAG, "(server)[%s -> %s] current return %s", old, rdp_get_state_string(rdp),
state_run_result_string(rc, buffer, sizeof(buffer)));
} while ((rc == STATE_RUN_TRY_AGAIN) || (rc == STATE_RUN_CONTINUE) || (rc == STATE_RUN_ACTIVE));
return rc;
}

View File

@ -27,6 +27,7 @@
#include "rdp.h"
#include "state.h"
#include "info.h"
#include "utils.h"
#include "mcs.h"
@ -956,7 +957,7 @@ static BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
return ret;
}
int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
state_run_t rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
{
BYTE type;
wStream* cs;
@ -969,7 +970,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
&compressedLength))
{
WLog_ERR(TAG, "rdp_read_share_data_header() failed");
return -1;
return STATE_RUN_FAILED;
}
cs = s;
@ -984,7 +985,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
{
WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %" PRIu16 "",
compressedLength);
return -1;
return STATE_RUN_FAILED;
}
if (bulk_decompress(rdp->bulk, Stream_Pointer(s), SrcSize, &pDstData, &DstSize,
@ -994,7 +995,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
if (!cs)
{
WLog_ERR(TAG, "Couldn't take stream from pool");
return -1;
return STATE_RUN_FAILED;
}
Stream_SetPosition(cs, 0);
@ -1005,7 +1006,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
else
{
WLog_ERR(TAG, "bulk_decompress() failed");
return -1;
return STATE_RUN_FAILED;
}
Stream_Seek(s, SrcSize);
@ -1161,16 +1162,16 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
if (cs != s)
Stream_Release(cs);
return 0;
return STATE_RUN_SUCCESS;
out_fail:
if (cs != s)
Stream_Release(cs);
return -1;
return STATE_RUN_FAILED;
}
int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
state_run_t rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
{
WINPR_ASSERT(rdp);
WINPR_ASSERT(s);
@ -1198,12 +1199,12 @@ int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
HRESULT hr = E_ABORT;
/* Initiate Multitransport Request PDU */
// TODO: This message is server -> client only
int rc = multitransport_client_recv_request(rdp->multitransport, s);
if (rc < 0)
state_run_t rc = multitransport_client_recv_request(rdp->multitransport, s);
if (state_run_failed(rc))
return rc;
if (!multitransport_client_send_response(rdp->multitransport, hr))
return -1;
return 1;
return STATE_RUN_FAILED;
return STATE_RUN_SUCCESS;
}
if (securityFlags & SEC_TRANSPORT_RSP)
@ -1229,17 +1230,17 @@ int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
return license_recv(rdp->license, s);
}
return 1;
return STATE_RUN_SUCCESS;
}
int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
state_run_t rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 type;
UINT16 length;
UINT16 channelId;
if (!rdp_read_share_control_header(s, &length, NULL, &type, &channelId))
return -1;
return STATE_RUN_FAILED;
if (type == PDU_TYPE_DATA)
{
@ -1252,11 +1253,11 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s)
else if (type == PDU_TYPE_FLOW_RESPONSE || type == PDU_TYPE_FLOW_STOP ||
type == PDU_TYPE_FLOW_TEST)
{
return 0;
return STATE_RUN_SUCCESS;
}
else
{
return -1;
return STATE_RUN_FAILED;
}
}
@ -1420,9 +1421,9 @@ const char* pdu_type_to_str(UINT16 pduType)
* @param s stream
*/
static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
static state_run_t rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
{
int rc = 0;
state_run_t rc = STATE_RUN_SUCCESS;
UINT16 length;
UINT16 pduType;
UINT16 pduSource;
@ -1438,10 +1439,10 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
WINPR_ASSERT(instance);
if (!rdp_read_header(rdp, s, &length, &channelId))
return -1;
return STATE_RUN_FAILED;
if (freerdp_shall_disconnect_context(rdp->context))
return 0;
return STATE_RUN_SUCCESS;
if (rdp->autodetect->bandwidthMeasureStarted)
{
@ -1453,7 +1454,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_read_security_header(s, &securityFlags, &length))
{
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_security_header() fail");
return -1;
return STATE_RUN_FAILED;
}
if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT))
@ -1461,7 +1462,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_decrypt(rdp, s, &length, securityFlags))
{
WLog_ERR(TAG, "rdp_decrypt failed");
return -1;
return STATE_RUN_FAILED;
}
}
@ -1491,12 +1492,12 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_read_share_control_header(s, NULL, &remain, &pduType, &pduSource))
{
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_share_control_header() fail");
return -1;
return STATE_RUN_FAILED;
}
sub = Stream_StaticInit(&subbuffer, Stream_Pointer(s), remain);
if (!Stream_SafeSeek(s, remain))
return -1;
return STATE_RUN_FAILED;
rdp->settings->PduSource = pduSource;
rdp->inPackets++;
@ -1505,7 +1506,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
{
case PDU_TYPE_DATA:
rc = rdp_recv_data_pdu(rdp, sub);
if (rc < 0)
if (state_run_failed(rc))
return rc;
break;
@ -1513,7 +1514,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_recv_deactivate_all(rdp, sub))
{
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_recv_deactivate_all() fail");
return -1;
return STATE_RUN_FAILED;
}
break;
@ -1527,7 +1528,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
WLog_DBG(TAG, "flow message 0x%04" PRIX16 "", pduType);
/* http://msdn.microsoft.com/en-us/library/cc240576.aspx */
if (!Stream_SafeSeek(sub, remain))
return -1;
return STATE_RUN_FAILED;
break;
default:
@ -1549,7 +1550,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
{
if (!rdp->settings->UseRdpSecurityLayer)
if (!rdp_read_security_header(s, &securityFlags, NULL))
return -1;
return STATE_RUN_FAILED;
rdp->inPackets++;
rc = rdp_recv_message_channel_pdu(rdp, s, securityFlags);
}
@ -1558,16 +1559,16 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
rdp->inPackets++;
if (!freerdp_channel_process(instance, s, channelId, length))
return -1;
return STATE_RUN_FAILED;
}
out:
if (!tpkt_ensure_stream_consumed(s, length))
return -1;
return STATE_RUN_FAILED;
return rc;
}
static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
static state_run_t rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 length;
rdpFastPath* fastpath;
@ -1576,13 +1577,13 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
if (!fastpath_read_header_rdp(fastpath, s, &length))
{
WLog_ERR(TAG, "rdp_recv_fastpath_pdu: fastpath_read_header_rdp() fail");
return -1;
return STATE_RUN_FAILED;
}
if ((length == 0) || (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
{
WLog_ERR(TAG, "incorrect FastPath PDU header length %" PRIu16 "", length);
return -1;
return STATE_RUN_FAILED;
}
if (rdp->autodetect->bandwidthMeasureStarted)
@ -1599,14 +1600,14 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
if (!rdp_decrypt(rdp, s, &length, flags))
{
WLog_ERR(TAG, "rdp_recv_fastpath_pdu: rdp_decrypt() fail");
return -1;
return STATE_RUN_FAILED;
}
}
return fastpath_recv_updates(rdp->fastpath, s);
}
static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
static state_run_t rdp_recv_pdu(rdpRdp* rdp, wStream* s)
{
const int rc = tpkt_verify_header(s);
if (rc > 0)
@ -1614,77 +1615,14 @@ static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
else if (rc == 0)
return rdp_recv_fastpath_pdu(rdp, s);
else
return rc;
return STATE_RUN_FAILED;
}
typedef enum
{
STATE_RUN_ACTIVE = 2,
STATE_RUN_REDIRECT = 1,
STATE_RUN_SUCCESS = 0,
STATE_RUN_FAILED = -1,
STATE_RUN_TRY_AGAIN = -23,
STATE_RUN_CONTINUE = -24
} state_run_t;
static BOOL state_run_failed(int status)
{
switch (status)
{
case STATE_RUN_CONTINUE:
case STATE_RUN_TRY_AGAIN:
return FALSE;
default:
break;
}
if (status < STATE_RUN_SUCCESS)
return TRUE;
return FALSE;
}
static BOOL state_run_success(int status)
{
return status >= STATE_RUN_SUCCESS;
}
static const char* state_run_result_string(int status, char* buffer, size_t buffersize)
{
const char* name;
switch (status)
{
case STATE_RUN_ACTIVE:
name = "STATE_RUN_ACTIVE";
break;
case STATE_RUN_REDIRECT:
name = "STATE_RUN_REDIRECT";
break;
case STATE_RUN_SUCCESS:
name = "STATE_RUN_SUCCESS";
break;
case STATE_RUN_FAILED:
name = "STATE_RUN_FAILED";
break;
case STATE_RUN_TRY_AGAIN:
name = "STATE_RUN_TRY_AGAIN";
break;
case STATE_RUN_CONTINUE:
name = "STATE_RUN_CONTINUE";
break;
default:
name = "STATE_RUN_UNKNOWN";
break;
}
_snprintf(buffer, buffersize, "%s [%d]", name, status);
return buffer;
}
static int rdp_recv_callback_int(rdpTransport* transport, wStream* s, void* extra)
static state_run_t rdp_recv_callback_int(rdpTransport* transport, wStream* s, void* extra)
{
const UINT32 mask = FINALIZE_SC_SYNCHRONIZE_PDU | FINALIZE_SC_CONTROL_COOPERATE_PDU |
FINALIZE_SC_CONTROL_GRANTED_PDU | FINALIZE_SC_FONT_MAP_PDU;
int status = STATE_RUN_SUCCESS;
state_run_t status = STATE_RUN_SUCCESS;
rdpRdp* rdp = (rdpRdp*)extra;
WINPR_ASSERT(transport);
@ -2004,15 +1942,25 @@ static int rdp_recv_callback_int(rdpTransport* transport, wStream* s, void* extr
return status;
}
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
state_run_t rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
{
char buffer[64] = { 0 };
state_run_t rc = STATE_RUN_FAILED;
const size_t start = Stream_GetPosition(s);
const rdpContext* context = transport_get_context(transport);
WINPR_ASSERT(context);
do
{
const rdpRdp* rdp = context->rdp;
const char* old = rdp_get_state_string(rdp);
if (rc == STATE_RUN_TRY_AGAIN)
Stream_SetPosition(s, start);
rc = rdp_recv_callback_int(transport, s, extra);
WLog_VRB(TAG, "(client)[%s -> %s] current return %s", old, rdp_get_state_string(rdp),
state_run_result_string(rc, buffer, sizeof(buffer)));
} while ((rc == STATE_RUN_TRY_AGAIN) || (rc == STATE_RUN_CONTINUE));
return rc;
}

View File

@ -230,7 +230,7 @@ FREERDP_LOCAL BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 cha
FREERDP_LOCAL wStream* rdp_data_pdu_init(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id);
FREERDP_LOCAL int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_recv_data_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channelId);
@ -241,11 +241,12 @@ FREERDP_LOCAL BOOL rdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t
FREERDP_LOCAL wStream* rdp_message_channel_pdu_init(rdpRdp* rdp);
FREERDP_LOCAL BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags);
FREERDP_LOCAL int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags);
FREERDP_LOCAL state_run_t rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s,
UINT16 securityFlags);
FREERDP_LOCAL int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
FREERDP_LOCAL state_run_t rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
FREERDP_LOCAL int rdp_check_fds(rdpRdp* rdp);

View File

@ -235,14 +235,14 @@ int rdp_redirection_apply_settings(rdpRdp* rdp)
return 0;
}
static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
static state_run_t rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 flags;
UINT16 length;
rdpRedirection* redirection = rdp->redirection;
if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT16(s, flags); /* flags (2 bytes) */
Stream_Read_UINT16(s, length); /* length (2 bytes) */
@ -269,7 +269,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_TARGET_NET_ADDRESS)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddress), 80))
return -1;
return STATE_RUN_FAILED;
}
if (redirection->flags & LB_LOAD_BALANCE_INFO)
@ -281,17 +281,17 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
* 0020 30 30 0d 0a 00..
*/
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, redirection->LoadBalanceInfoLength);
if (!Stream_CheckAndLogRequiredLength(TAG, s, redirection->LoadBalanceInfoLength))
return -1;
return STATE_RUN_FAILED;
redirection->LoadBalanceInfo = (BYTE*)malloc(redirection->LoadBalanceInfoLength);
if (!redirection->LoadBalanceInfo)
return -1;
return STATE_RUN_FAILED;
Stream_Read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength);
WLog_DBG(TAG, "loadBalanceInfo:");
@ -302,7 +302,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_USERNAME)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->Username), 512))
return -1;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "Username: %s", redirection->Username);
}
@ -310,7 +310,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_DOMAIN)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->Domain), 52))
return FALSE;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "Domain: %s", redirection->Domain);
}
@ -339,7 +339,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
* end of the buffer which won't get counted in PasswordLength.
*/
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, redirection->PasswordLength);
@ -349,15 +349,15 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
*/
if (!Stream_CheckAndLogRequiredLength(TAG, s, redirection->PasswordLength))
return -1;
return STATE_RUN_FAILED;
if (redirection->PasswordLength > LB_PASSWORD_MAX_LENGTH)
return -1;
return STATE_RUN_FAILED;
redirection->Password = (BYTE*)calloc(1, redirection->PasswordLength + sizeof(WCHAR));
if (!redirection->Password)
return -1;
return STATE_RUN_FAILED;
Stream_Read(s, redirection->Password, redirection->PasswordLength);
WLog_DBG(TAG, "PasswordCookie:");
@ -369,7 +369,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_TARGET_FQDN)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetFQDN), 512))
return -1;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "TargetFQDN: %s", redirection->TargetFQDN);
}
@ -377,7 +377,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_TARGET_NETBIOS_NAME)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetBiosName), 32))
return -1;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "TargetNetBiosName: %s", redirection->TargetNetBiosName);
}
@ -385,17 +385,17 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_CLIENT_TSV_URL)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, redirection->TsvUrlLength);
if (!Stream_CheckAndLogRequiredLength(TAG, s, redirection->TsvUrlLength))
return -1;
return STATE_RUN_FAILED;
redirection->TsvUrl = (BYTE*)malloc(redirection->TsvUrlLength);
if (!redirection->TsvUrl)
return -1;
return STATE_RUN_FAILED;
Stream_Read(s, redirection->TsvUrl, redirection->TsvUrlLength);
WLog_DBG(TAG, "TsvUrl:");
@ -409,7 +409,7 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
UINT32 targetNetAddressesLength;
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
return -1;
return STATE_RUN_FAILED;
Stream_Read_UINT32(s, targetNetAddressesLength);
Stream_Read_UINT32(s, redirection->TargetNetAddressesCount);
@ -417,14 +417,14 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
redirection->TargetNetAddresses = (char**)calloc(count, sizeof(char*));
if (!redirection->TargetNetAddresses)
return FALSE;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "TargetNetAddressesCount: %" PRIu32 "", redirection->TargetNetAddressesCount);
for (i = 0; i < count; i++)
{
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddresses[i]), 80))
return FALSE;
return STATE_RUN_FAILED;
WLog_DBG(TAG, "TargetNetAddresses[%" PRIuz "]: %s", i,
redirection->TargetNetAddresses[i]);
@ -438,21 +438,21 @@ static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
}
if (redirection->flags & LB_NOREDIRECT)
return 0;
return STATE_RUN_SUCCESS;
return 1;
return STATE_RUN_REDIRECT;
}
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s)
state_run_t rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s)
{
int status = 0;
state_run_t status = STATE_RUN_SUCCESS;
if (!Stream_SafeSeek(s, 2)) /* pad2Octets (2 bytes) */
return -1;
return STATE_RUN_FAILED;
status = rdp_recv_server_redirection_pdu(rdp, s);
if (status < 0)
if (state_run_failed(status))
return status;
if (Stream_GetRemainingLength(s) >= 1)

View File

@ -31,7 +31,7 @@ typedef struct rdp_redirection rdpRedirection;
#include <winpr/wlog.h>
#include <winpr/stream.h>
FREERDP_LOCAL int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL state_run_t rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_redirection_apply_settings(rdpRdp* rdp);

69
libfreerdp/core/state.c Normal file
View File

@ -0,0 +1,69 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* RDP state machine types and helper functions
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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.
*/
#include "state.h"
#include <winpr/string.h>
BOOL state_run_failed(state_run_t status)
{
return status == STATE_RUN_FAILED;
}
BOOL state_run_success(state_run_t status)
{
if (status == STATE_RUN_CONTINUE)
return TRUE;
return status >= STATE_RUN_SUCCESS;
}
const char* state_run_result_string(state_run_t status, char* buffer, size_t buffersize)
{
const char* name;
switch (status)
{
case STATE_RUN_ACTIVE:
name = "STATE_RUN_ACTIVE";
break;
case STATE_RUN_REDIRECT:
name = "STATE_RUN_REDIRECT";
break;
case STATE_RUN_SUCCESS:
name = "STATE_RUN_SUCCESS";
break;
case STATE_RUN_FAILED:
name = "STATE_RUN_FAILED";
break;
case STATE_RUN_TRY_AGAIN:
name = "STATE_RUN_TRY_AGAIN";
break;
case STATE_RUN_CONTINUE:
name = "STATE_RUN_CONTINUE";
break;
default:
name = "STATE_RUN_UNKNOWN";
break;
}
_snprintf(buffer, buffersize, "%s [%d]", name, status);
return buffer;
}

43
libfreerdp/core/state.h Normal file
View File

@ -0,0 +1,43 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* RDP state machine types and helper functions
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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.
*/
#ifndef FREERDP_LIB_CORE_STATE_H
#define FREERDP_LIB_CORE_STATE_H
#include <winpr/wtypes.h>
#include <freerdp/api.h>
typedef enum
{
STATE_RUN_ACTIVE = 2,
STATE_RUN_REDIRECT = 1,
STATE_RUN_SUCCESS = 0,
STATE_RUN_FAILED = -1,
STATE_RUN_TRY_AGAIN = -23,
STATE_RUN_CONTINUE = -24
} state_run_t;
FREERDP_LOCAL BOOL state_run_failed(state_run_t status);
FREERDP_LOCAL BOOL state_run_success(state_run_t status);
FREERDP_LOCAL const char* state_run_result_string(state_run_t status, char* buffer,
size_t buffersize);
#endif /* FREERDP_LIB_CORE_STATE_H */

View File

@ -52,6 +52,7 @@
#include "rdp.h"
#include "proxy.h"
#include "utils.h"
#include "state.h"
#define TAG FREERDP_TAG("core.transport")
@ -1107,7 +1108,7 @@ int transport_drain_output_buffer(rdpTransport* transport)
int transport_check_fds(rdpTransport* transport)
{
int status;
int recv_status;
state_run_t recv_status;
wStream* received;
UINT64 now = GetTickCount64();
UINT64 dueDate = 0;
@ -1173,15 +1174,17 @@ int transport_check_fds(rdpTransport* transport)
Stream_Release(received);
/* session redirection or activation */
if (recv_status == 1 || recv_status == 2)
if (recv_status == STATE_RUN_REDIRECT || recv_status == STATE_RUN_ACTIVE)
{
return recv_status;
}
if (recv_status < 0)
if (state_run_failed(recv_status))
{
char buffer[64] = { 0 };
WLog_Print(transport->log, WLOG_ERROR,
"transport_check_fds: transport->ReceiveCallback() - %i", recv_status);
"transport_check_fds: transport->ReceiveCallback() - %s",
state_run_result_string(recv_status, buffer, ARRAYSIZE(buffer)));
return -1;
}

View File

@ -50,7 +50,9 @@ typedef enum
#include <freerdp/settings.h>
#include <freerdp/transport_io.h>
typedef int (*TransportRecv)(rdpTransport* transport, wStream* stream, void* extra);
#include "state.h"
typedef state_run_t (*TransportRecv)(rdpTransport* transport, wStream* stream, void* extra);
FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport, size_t size);
FREERDP_LOCAL BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port,