From bc31bae2b5e400df7f97c88c314b986d8e6b4d83 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 11 Nov 2022 12:26:28 +0100 Subject: [PATCH] [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 --- libfreerdp/core/CMakeLists.txt | 2 + libfreerdp/core/autodetect.c | 10 +- libfreerdp/core/autodetect.h | 6 +- libfreerdp/core/capabilities.c | 3 +- libfreerdp/core/connection.c | 61 ++++----- libfreerdp/core/connection.h | 7 +- libfreerdp/core/fastpath.c | 20 +-- libfreerdp/core/heartbeat.c | 8 +- libfreerdp/core/heartbeat.h | 4 +- libfreerdp/core/license.c | 44 +++--- libfreerdp/core/license.h | 3 +- libfreerdp/core/multitransport.c | 6 +- libfreerdp/core/multitransport.h | 4 +- libfreerdp/core/peer.c | 224 ++++++++++++++++--------------- libfreerdp/core/rdp.c | 154 +++++++-------------- libfreerdp/core/rdp.h | 9 +- libfreerdp/core/redirection.c | 52 +++---- libfreerdp/core/redirection.h | 2 +- libfreerdp/core/state.c | 69 ++++++++++ libfreerdp/core/state.h | 43 ++++++ libfreerdp/core/transport.c | 11 +- libfreerdp/core/transport.h | 4 +- 22 files changed, 419 insertions(+), 327 deletions(-) create mode 100644 libfreerdp/core/state.c create mode 100644 libfreerdp/core/state.h diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index e50154007..1f9a3d3f3 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -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 diff --git a/libfreerdp/core/autodetect.c b/libfreerdp/core/autodetect.c index e9f8a778b..252b3fe75 100644 --- a/libfreerdp/core/autodetect.c +++ b/libfreerdp/core/autodetect.c @@ -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) diff --git a/libfreerdp/core/autodetect.h b/libfreerdp/core/autodetect.h index cb712aaeb..f7e29b376 100644 --- a/libfreerdp/core/autodetect.h +++ b/libfreerdp/core/autodetect.h @@ -30,6 +30,8 @@ #include #include +#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); diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index c1a71b7d9..186538274 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -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; diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 15682890a..7065c8cd7 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -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); } diff --git a/libfreerdp/core/connection.h b/libfreerdp/core/connection.h index 4b8205250..1890135a8 100644 --- a/libfreerdp/core/connection.h +++ b/libfreerdp/core/connection.h @@ -26,6 +26,7 @@ #include "nego.h" #include "mcs.h" #include "activation.h" +#include "state.h" #include #include @@ -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); diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 818aa781f..f179d683c 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -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) diff --git a/libfreerdp/core/heartbeat.c b/libfreerdp/core/heartbeat.c index d2662a55f..d45400deb 100644 --- a/libfreerdp/core/heartbeat.c +++ b/libfreerdp/core/heartbeat.c @@ -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) diff --git a/libfreerdp/core/heartbeat.h b/libfreerdp/core/heartbeat.h index f7cf63451..56ebc41cf 100644 --- a/libfreerdp/core/heartbeat.h +++ b/libfreerdp/core/heartbeat.h @@ -29,7 +29,9 @@ #include -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); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 69a34b260..ca8468063 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -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); diff --git a/libfreerdp/core/license.h b/libfreerdp/core/license.h index d2d3c0b00..e7d14601e 100644 --- a/libfreerdp/core/license.h +++ b/libfreerdp/core/license.h @@ -23,6 +23,7 @@ #define FREERDP_LIB_CORE_LICENSE_H #include "rdp.h" +#include "state.h" #include #include @@ -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); diff --git a/libfreerdp/core/multitransport.c b/libfreerdp/core/multitransport.c index a4a3fcf66..56d09553f 100644 --- a/libfreerdp/core/multitransport.c +++ b/libfreerdp/core/multitransport.c @@ -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) diff --git a/libfreerdp/core/multitransport.h b/libfreerdp/core/multitransport.h index fac3c93c8..d7ead5aad 100644 --- a/libfreerdp/core/multitransport.h +++ b/libfreerdp/core/multitransport.h @@ -23,6 +23,7 @@ typedef struct rdp_multitransport rdpMultitransport; #include "rdp.h" +#include "state.h" #include #include @@ -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, diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 34f461475..affac7c4a 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -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; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 4dc3d7339..ed6cf4b56 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -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; } diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index d707e8243..df8f86244 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -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); diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c index 80b935add..6932ee1ff 100644 --- a/libfreerdp/core/redirection.c +++ b/libfreerdp/core/redirection.c @@ -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) diff --git a/libfreerdp/core/redirection.h b/libfreerdp/core/redirection.h index 660a4e08a..73864fd48 100644 --- a/libfreerdp/core/redirection.h +++ b/libfreerdp/core/redirection.h @@ -31,7 +31,7 @@ typedef struct rdp_redirection rdpRedirection; #include #include -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); diff --git a/libfreerdp/core/state.c b/libfreerdp/core/state.c new file mode 100644 index 000000000..6178df512 --- /dev/null +++ b/libfreerdp/core/state.c @@ -0,0 +1,69 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * RDP state machine types and helper functions + * + * Copyright 2022 Armin Novak + * 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 + +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; +} diff --git a/libfreerdp/core/state.h b/libfreerdp/core/state.h new file mode 100644 index 000000000..be6cdfa39 --- /dev/null +++ b/libfreerdp/core/state.h @@ -0,0 +1,43 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * RDP state machine types and helper functions + * + * Copyright 2022 Armin Novak + * 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 +#include + +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 */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 78cc2613a..322a252b3 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -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; } diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index 7bc092eb0..55218f98e 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -50,7 +50,9 @@ typedef enum #include #include -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,