Updated RDP state machine
* More detailed states * Better transition checks * No more recursive calling of state machine functions
This commit is contained in:
parent
06c2ab76e0
commit
33827cb920
@ -395,7 +395,7 @@ int main(int argc, char* argv[])
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CONNECT, FALSE))
|
||||
if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CREATE_REQUEST, FALSE))
|
||||
goto fail;
|
||||
|
||||
if (freerdp_client_start(context) != 0)
|
||||
|
@ -65,7 +65,7 @@ int main(int argc, char* argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CONNECT, FALSE))
|
||||
if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CREATE_REQUEST, FALSE))
|
||||
goto out;
|
||||
|
||||
if (freerdp_client_start(context) != 0)
|
||||
|
@ -80,17 +80,32 @@ extern "C"
|
||||
CONNECTION_STATE_INITIAL,
|
||||
CONNECTION_STATE_NEGO,
|
||||
CONNECTION_STATE_NLA,
|
||||
CONNECTION_STATE_MCS_CONNECT,
|
||||
CONNECTION_STATE_MCS_CREATE_REQUEST,
|
||||
CONNECTION_STATE_MCS_CREATE_RESPONSE,
|
||||
CONNECTION_STATE_MCS_ERECT_DOMAIN,
|
||||
CONNECTION_STATE_MCS_ATTACH_USER,
|
||||
CONNECTION_STATE_MCS_CHANNEL_JOIN,
|
||||
CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM,
|
||||
CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST,
|
||||
CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE,
|
||||
CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT,
|
||||
CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE,
|
||||
CONNECTION_STATE_LICENSING,
|
||||
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE,
|
||||
CONNECTION_STATE_FINALIZATION,
|
||||
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST,
|
||||
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE,
|
||||
CONNECTION_STATE_FINALIZATION_SYNC,
|
||||
CONNECTION_STATE_FINALIZATION_COOPERATE,
|
||||
CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL,
|
||||
CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST,
|
||||
CONNECTION_STATE_FINALIZATION_FONT_LIST,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_SYNC,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP,
|
||||
CONNECTION_STATE_ACTIVE
|
||||
} CONNECTION_STATE;
|
||||
|
||||
|
@ -625,7 +625,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
|
||||
} while (0);
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
|
||||
for (timeout = 0; timeout < freerdp_settings_get_uint32(rdp->settings, FreeRDP_TcpAckTimeout);
|
||||
timeout += 100)
|
||||
@ -710,8 +710,6 @@ BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
|
||||
GrantId, ControlId);
|
||||
return FALSE;
|
||||
}
|
||||
if (!rdp_send_server_control_granted_pdu(rdp))
|
||||
return FALSE;
|
||||
return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
|
||||
case CTRLACTION_COOPERATE:
|
||||
if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
|
||||
@ -767,26 +765,21 @@ BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if (!rdp_recv_client_font_list_pdu(s))
|
||||
return FALSE;
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_CS_FONT_LIST_PDU);
|
||||
|
||||
if (settings->SupportMonitorLayoutPdu && settings->MonitorCount && peer->AdjustMonitorsLayout &&
|
||||
peer->AdjustMonitorsLayout(peer))
|
||||
{
|
||||
/* client supports the monitorLayout PDU, let's send him the monitors if any */
|
||||
MONITOR_DEF* monitors = NULL;
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_SYNC);
|
||||
if (!rdp_send_server_synchronize_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
if (!display_convert_rdp_monitor_to_monitor_def(settings->MonitorCount,
|
||||
settings->MonitorDefArray, &monitors))
|
||||
return FALSE;
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE);
|
||||
if (!rdp_send_server_control_cooperate_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount, monitors))
|
||||
{
|
||||
free(monitors);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(monitors);
|
||||
}
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL);
|
||||
if (!rdp_send_server_control_granted_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP);
|
||||
if (!rdp_send_server_font_map_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
@ -804,6 +797,7 @@ BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (!rdp_recv_client_persistent_key_list_pdu(s))
|
||||
return FALSE;
|
||||
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU);
|
||||
// TODO: Actually do something with this
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -362,25 +362,28 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
|
||||
if ((SelectedProtocol & PROTOCOL_SSL) || (SelectedProtocol == PROTOCOL_RDP))
|
||||
{
|
||||
wStream s = { 0 };
|
||||
|
||||
if ((settings->Username != NULL) &&
|
||||
((freerdp_settings_get_string(settings, FreeRDP_Password) != NULL) ||
|
||||
(settings->RedirectionPassword != NULL &&
|
||||
settings->RedirectionPasswordLength > 0)))
|
||||
settings->AutoLogonEnabled = TRUE;
|
||||
|
||||
if (rdp_recv_callback(rdp->transport, &s, rdp) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
transport_set_blocking_mode(rdp->transport, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST);
|
||||
}
|
||||
|
||||
/* everything beyond this point is event-driven and non blocking */
|
||||
transport_set_recv_callbacks(rdp->transport, rdp_recv_callback, rdp);
|
||||
|
||||
if (rdp_get_state(rdp) != CONNECTION_STATE_NLA)
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT);
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
now = GetTickCount64();
|
||||
dueDate = now + freerdp_settings_get_uint32(settings, FreeRDP_TcpAckTimeout);
|
||||
|
||||
@ -698,6 +701,8 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT);
|
||||
|
||||
/* encrypt client random */
|
||||
free(settings->ClientRandom);
|
||||
settings->ClientRandomLength = CLIENT_RANDOM_LENGTH;
|
||||
@ -953,8 +958,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
|
||||
mcs->userChannelJoined = TRUE;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(mcs, MCS_GLOBAL_CHANNEL_ID))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
}
|
||||
else if (!mcs->globalChannelJoined)
|
||||
{
|
||||
@ -965,8 +972,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if (mcs->messageChannelId != 0)
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(mcs, mcs->messageChannelId))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
|
||||
allJoined = FALSE;
|
||||
}
|
||||
@ -975,8 +984,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
if (mcs->channelCount > 0)
|
||||
{
|
||||
const rdpMcsChannel* cur = &mcs->channels[0];
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(mcs, cur->ChannelId))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
|
||||
allJoined = FALSE;
|
||||
}
|
||||
@ -992,8 +1003,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
if (mcs->channelCount > 0)
|
||||
{
|
||||
const rdpMcsChannel* cur = &mcs->channels[0];
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(mcs, cur->ChannelId))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
|
||||
allJoined = FALSE;
|
||||
}
|
||||
@ -1016,8 +1029,10 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
if (i + 1 < mcs->channelCount)
|
||||
{
|
||||
const rdpMcsChannel* cur = &mcs->channels[i + 1];
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(mcs, cur->ChannelId))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
|
||||
allJoined = FALSE;
|
||||
}
|
||||
@ -1028,10 +1043,11 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
if (!rdp_client_establish_keys(rdp))
|
||||
return FALSE;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
|
||||
if (!rdp_send_client_info(rdp))
|
||||
return FALSE;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1114,7 +1130,16 @@ int rdp_client_connect_license(rdpRdp* rdp, wStream* s)
|
||||
WLog_ERR(TAG, "license connection sequence aborted.");
|
||||
return -1;
|
||||
case LICENSE_STATE_COMPLETED:
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
if (rdp->settings->MultitransportFlags)
|
||||
{
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
@ -1152,7 +1177,7 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rdp_client_connect_confirm_active(rdp, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
@ -1163,12 +1188,15 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
* server-to- client PDUs; they may be sent as a single batch, provided that sequencing is
|
||||
* maintained.
|
||||
*/
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_SYNC);
|
||||
if (!rdp_send_client_synchronize_pdu(rdp))
|
||||
return -1;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_COOPERATE);
|
||||
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_COOPERATE))
|
||||
return -1;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL);
|
||||
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL))
|
||||
return -1;
|
||||
|
||||
@ -1182,26 +1210,34 @@ int rdp_client_connect_finalize(rdpRdp* rdp)
|
||||
if (!rdp_finalize_is_flag_set(rdp, FINALIZE_DEACTIVATE_REACTIVATE) &&
|
||||
rdp->settings->BitmapCachePersistEnabled)
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST);
|
||||
if (!rdp_send_client_persistent_key_list_pdu(rdp))
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_SYNC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state)
|
||||
{
|
||||
int status = 0;
|
||||
const char* name = rdp_state_string(state);
|
||||
|
||||
WLog_DBG(TAG, "%s %s --> %s", __FUNCTION__, rdp_get_state_string(rdp), rdp_state_string(state));
|
||||
WLog_DBG(TAG, "%s %s --> %s", __FUNCTION__, rdp_get_state_string(rdp), name);
|
||||
rdp_set_state(rdp, state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
case CONNECTION_STATE_FINALIZATION_SYNC:
|
||||
case CONNECTION_STATE_FINALIZATION_COOPERATE:
|
||||
case CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL:
|
||||
case CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST:
|
||||
case CONNECTION_STATE_FINALIZATION_FONT_LIST:
|
||||
update_reset_state(rdp->update);
|
||||
rdp_finalize_reset_flags(rdp, FALSE);
|
||||
break;
|
||||
@ -1334,52 +1370,82 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
return FALSE;
|
||||
|
||||
transport_set_blocking_mode(rdp->transport, FALSE);
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT32 i;
|
||||
rdpMcs* mcs = rdp->mcs;
|
||||
rdpMcs* mcs;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
mcs = rdp->mcs;
|
||||
WINPR_ASSERT(mcs);
|
||||
|
||||
WINPR_ASSERT(rdp_get_state(rdp) == CONNECTION_STATE_MCS_CREATE_REQUEST);
|
||||
if (!mcs_recv_connect_initial(mcs, s))
|
||||
return FALSE;
|
||||
WINPR_ASSERT(rdp->settings);
|
||||
|
||||
if (!mcs_server_apply_to_settings(mcs, rdp->settings))
|
||||
return FALSE;
|
||||
|
||||
WLog_INFO(TAG, "Accepted client: %s", rdp->settings->ClientHostname);
|
||||
WLog_INFO(TAG, "Accepted channels:");
|
||||
|
||||
WINPR_ASSERT(mcs->channels || (mcs->channelCount == 0));
|
||||
for (i = 0; i < mcs->channelCount; i++)
|
||||
{
|
||||
ADDIN_ARGV* arg;
|
||||
rdpMcsChannel* cur = &mcs->channels[i];
|
||||
const char* params[1] = { cur->Name };
|
||||
WLog_INFO(TAG, " %s", cur->Name);
|
||||
arg = freerdp_addin_argv_new(ARRAYSIZE(params), params);
|
||||
if (!arg)
|
||||
return FALSE;
|
||||
|
||||
if (!freerdp_static_channel_collection_add(rdp->settings, arg))
|
||||
{
|
||||
freerdp_addin_argv_free(arg);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_RESPONSE);
|
||||
if (!mcs_send_connect_response(mcs))
|
||||
return FALSE;
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(rdp_get_state(rdp) == CONNECTION_STATE_MCS_ERECT_DOMAIN);
|
||||
|
||||
if (!mcs_recv_erect_domain_request(rdp->mcs, s))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
if (!mcs_recv_attach_user_request(rdp->mcs, s))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM);
|
||||
if (!mcs_send_attach_user_confirm(rdp->mcs))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1388,19 +1454,28 @@ BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s)
|
||||
UINT32 i;
|
||||
UINT16 channelId;
|
||||
BOOL allJoined = TRUE;
|
||||
rdpMcs* mcs = rdp->mcs;
|
||||
rdpMcs* mcs;
|
||||
|
||||
if (!mcs_recv_channel_join_request(mcs, rdp->settings, s, &channelId))
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(rdp->context);
|
||||
|
||||
mcs = rdp->mcs;
|
||||
WINPR_ASSERT(mcs);
|
||||
|
||||
WINPR_ASSERT(rdp_get_state(rdp) == CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
|
||||
if (!mcs_recv_channel_join_request(mcs, rdp->context->settings, s, &channelId))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
if (!mcs_send_channel_join_confirm(mcs, channelId))
|
||||
return FALSE;
|
||||
|
||||
if (channelId == mcs->userId)
|
||||
mcs->userChannelJoined = TRUE;
|
||||
else if (channelId == MCS_GLOBAL_CHANNEL_ID)
|
||||
if (channelId == MCS_GLOBAL_CHANNEL_ID)
|
||||
mcs->globalChannelJoined = TRUE;
|
||||
else if (channelId == mcs->messageChannelId)
|
||||
if (channelId == mcs->messageChannelId)
|
||||
mcs->messageChannelJoined = TRUE;
|
||||
|
||||
for (i = 0; i < mcs->channelCount; i++)
|
||||
@ -1415,19 +1490,36 @@ BOOL rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if ((mcs->userChannelJoined) && (mcs->globalChannelJoined) &&
|
||||
(mcs->messageChannelId == 0 || mcs->messageChannelJoined) && allJoined)
|
||||
{
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT);
|
||||
}
|
||||
else
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength)
|
||||
{
|
||||
freerdp_peer* peer = rdp->context->peer;
|
||||
freerdp_peer* peer;
|
||||
|
||||
if (rdp_get_state(rdp) != CONNECTION_STATE_CAPABILITIES_EXCHANGE)
|
||||
return FALSE;
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(rdp->context);
|
||||
WINPR_ASSERT(rdp->settings);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
peer = rdp->context->peer;
|
||||
WINPR_ASSERT(peer);
|
||||
|
||||
if (rdp_get_state(rdp) != CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE)
|
||||
{
|
||||
if (freerdp_settings_get_bool(rdp->settings, FreeRDP_TransportDumpReplay))
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE);
|
||||
else
|
||||
{
|
||||
WLog_WARN(TAG, "Invalid state, got %s, expected %s", rdp_get_state_string(rdp),
|
||||
rdp_state_string(CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rdp_recv_confirm_active(rdp, s, pduLength))
|
||||
return FALSE;
|
||||
@ -1438,13 +1530,7 @@ BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength)
|
||||
if (rdp->settings->SaltedChecksum)
|
||||
rdp->do_secure_checksum = TRUE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION);
|
||||
|
||||
if (!rdp_send_server_synchronize_pdu(rdp))
|
||||
return FALSE;
|
||||
|
||||
if (!rdp_send_server_control_cooperate_pdu(rdp))
|
||||
return FALSE;
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_SYNC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1462,12 +1548,9 @@ BOOL rdp_server_reactivate(rdpRdp* rdp)
|
||||
if (!rdp_send_deactivate_all(rdp))
|
||||
return FALSE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
|
||||
if (!rdp_send_demand_active(rdp))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE);
|
||||
return rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
}
|
||||
|
||||
BOOL rdp_server_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state)
|
||||
@ -1488,47 +1571,6 @@ BOOL rdp_server_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state)
|
||||
WLog_DBG(TAG, "%s %s --> %s", __FUNCTION__, rdp_get_state_string(rdp), rdp_state_string(state));
|
||||
if (!rdp_set_state(rdp, state))
|
||||
goto fail;
|
||||
switch (state)
|
||||
{
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
if (!rdp_finalize_reset_flags(rdp, FALSE))
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
update_reset_state(rdp->update);
|
||||
|
||||
if (client)
|
||||
{
|
||||
if (!client->connected)
|
||||
{
|
||||
/**
|
||||
* PostConnect should only be called once and should not
|
||||
* be called after a reactivation sequence.
|
||||
*/
|
||||
IFCALLRET(client->PostConnect, client->connected, client);
|
||||
|
||||
if (!client->connected)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (rdp_get_state(rdp) >= CONNECTION_STATE_ACTIVE)
|
||||
{
|
||||
IFCALLRET(client->Activate, client->activated, client);
|
||||
|
||||
if (!client->activated)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
status = TRUE;
|
||||
fail:
|
||||
@ -1560,28 +1602,58 @@ const char* rdp_state_string(CONNECTION_STATE state)
|
||||
return "CONNECTION_STATE_NEGO";
|
||||
case CONNECTION_STATE_NLA:
|
||||
return "CONNECTION_STATE_NLA";
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
return "CONNECTION_STATE_MCS_CONNECT";
|
||||
case CONNECTION_STATE_MCS_CREATE_REQUEST:
|
||||
return "CONNECTION_STATE_MCS_CREATE_REQUEST";
|
||||
case CONNECTION_STATE_MCS_CREATE_RESPONSE:
|
||||
return "CONNECTION_STATE_MCS_CREATE_RESPONSE";
|
||||
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
|
||||
return "CONNECTION_STATE_MCS_ERECT_DOMAIN";
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
return "CONNECTION_STATE_MCS_ATTACH_USER";
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||
return "CONNECTION_STATE_MCS_CHANNEL_JOIN";
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM:
|
||||
return "CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM";
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST:
|
||||
return "CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST";
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE:
|
||||
return "CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE";
|
||||
case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
|
||||
return "CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT";
|
||||
case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
|
||||
return "CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE";
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT:
|
||||
return "CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT";
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
|
||||
return "CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST";
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
|
||||
return "CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE";
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
return "CONNECTION_STATE_LICENSING";
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING:
|
||||
return "CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING";
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
return "CONNECTION_STATE_CAPABILITIES_EXCHANGE";
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
return "CONNECTION_STATE_FINALIZATION";
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST:
|
||||
return "CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST";
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE:
|
||||
return "CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE";
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
|
||||
return "CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE";
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT:
|
||||
return "CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT";
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE:
|
||||
return "CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE";
|
||||
case CONNECTION_STATE_FINALIZATION_SYNC:
|
||||
return "CONNECTION_STATE_FINALIZATION_SYNC";
|
||||
case CONNECTION_STATE_FINALIZATION_COOPERATE:
|
||||
return "CONNECTION_STATE_FINALIZATION_COOPERATE";
|
||||
case CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL:
|
||||
return "CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL";
|
||||
case CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST:
|
||||
return "CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST";
|
||||
case CONNECTION_STATE_FINALIZATION_FONT_LIST:
|
||||
return "CONNECTION_STATE_FINALIZATION_FONT_LIST";
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_SYNC:
|
||||
return "CONNECTION_STATE_FINALIZATION_CLIENT_SYNC";
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE:
|
||||
return "CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE";
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL:
|
||||
return "CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL";
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP:
|
||||
return "CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP";
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
return "CONNECTION_STATE_ACTIVE";
|
||||
default:
|
||||
@ -1679,6 +1751,5 @@ int rdp_client_connect_confirm_active(rdpRdp* rdp, wStream* s)
|
||||
if (freerdp_shall_disconnect_context(rdp->context))
|
||||
return 0;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION);
|
||||
return rdp_client_connect_finalize(rdp);
|
||||
}
|
||||
|
@ -925,6 +925,8 @@ BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s)
|
||||
UINT16 channelId;
|
||||
UINT16 securityFlags = 0;
|
||||
|
||||
WINPR_ASSERT(rdp_get_state(rdp) == CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
|
||||
|
||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||
return FALSE;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include "info.h"
|
||||
#include "display.h"
|
||||
#include "certificate.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
@ -35,6 +36,8 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.peer")
|
||||
|
||||
static int peer_recv_pdu(freerdp_peer* client, wStream* s);
|
||||
|
||||
static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char* name,
|
||||
UINT32 flags)
|
||||
{
|
||||
@ -437,6 +440,14 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
||||
if (freerdp_shall_disconnect_context(rdp->context))
|
||||
return 0;
|
||||
|
||||
if (rdp_get_state(rdp) <= CONNECTION_STATE_LICENSING)
|
||||
{
|
||||
if (!rdp_read_security_header(s, &securityFlags, NULL))
|
||||
return -1;
|
||||
|
||||
return rdp_recv_message_channel_pdu(rdp, s, securityFlags);
|
||||
}
|
||||
|
||||
if (settings->UseRdpSecurityLayer)
|
||||
{
|
||||
if (!rdp_read_security_header(s, &securityFlags, &length))
|
||||
@ -507,6 +518,124 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int peer_recv_handle_auto_detect(freerdp_peer* client, wStream* s)
|
||||
{
|
||||
int ret = -1;
|
||||
rdpRdp* rdp;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(client->context);
|
||||
|
||||
rdp = client->context->rdp;
|
||||
WINPR_ASSERT(rdp);
|
||||
|
||||
settings = rdp->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
|
||||
{
|
||||
switch (rdp_get_state(rdp))
|
||||
{
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
|
||||
{
|
||||
if (autodetect_send_connecttime_rtt_measure_request(rdp->autodetect, 0x23))
|
||||
ret = 0;
|
||||
rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE);
|
||||
}
|
||||
break;
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
|
||||
{
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (ret >= 0)
|
||||
{
|
||||
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 */
|
||||
break;
|
||||
case AUTODETECT_STATE_RESPONSE:
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
ret = 1; /* Rerun in next state */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid autodetect state %s", rdp_get_state_string(rdp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
|
||||
ret = 1; /* Rerun in next state */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int peer_recv_handle_licensing(freerdp_peer* client, wStream* s)
|
||||
{
|
||||
int ret = -1;
|
||||
rdpRdp* rdp;
|
||||
rdpSettings* settings;
|
||||
|
||||
WINPR_ASSERT(client);
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(client->context);
|
||||
|
||||
rdp = client->context->rdp;
|
||||
WINPR_ASSERT(rdp);
|
||||
|
||||
settings = rdp->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
switch (license_get_state(rdp->license))
|
||||
{
|
||||
case LICENSE_STATE_INITIAL:
|
||||
{
|
||||
const rdpSettings* settings = rdp->settings;
|
||||
const BOOL required =
|
||||
freerdp_settings_get_bool(settings, FreeRDP_ServerLicenseRequired);
|
||||
|
||||
if (required)
|
||||
{
|
||||
if (!license_server_configure(rdp->license))
|
||||
ret = -3;
|
||||
else if (!license_server_send_request(rdp->license))
|
||||
ret = -2;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (license_send_valid_client_error_packet(rdp))
|
||||
ret = 1; /* Rerun in next state, might be capabilities */
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LICENSE_STATE_COMPLETED:
|
||||
ret = 1; /* Licensing completed, continue in next state */
|
||||
break;
|
||||
case LICENSE_STATE_ABORTED:
|
||||
ret = -1;
|
||||
break;
|
||||
default:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
|
||||
{
|
||||
rdpRdp* rdp;
|
||||
@ -548,9 +677,10 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
|
||||
return fastpath_recv_inputs(fastpath, s);
|
||||
}
|
||||
|
||||
static int peer_recv_pdu(freerdp_peer* client, wStream* s)
|
||||
int peer_recv_pdu(freerdp_peer* client, wStream* s)
|
||||
{
|
||||
int rc = tpkt_verify_header(s);
|
||||
|
||||
if (rc > 0)
|
||||
return peer_recv_tpkt_pdu(client, s);
|
||||
else if (rc == 0)
|
||||
@ -559,6 +689,14 @@ static int peer_recv_pdu(freerdp_peer* client, wStream* s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int 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 */
|
||||
}
|
||||
|
||||
static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
UINT32 SelectedProtocol;
|
||||
@ -581,6 +719,11 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
switch (rdp_get_state(rdp))
|
||||
{
|
||||
case CONNECTION_STATE_INITIAL:
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_NEGO:
|
||||
if (!rdp_server_accept_nego(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - rdp_server_accept_nego() fail", __FUNCTION__,
|
||||
@ -596,8 +739,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
if (SelectedProtocol & PROTOCOL_HYBRID)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY* identity = nego_get_identity(rdp->nego);
|
||||
sspi_CopyAuthIdentity(&client->identity,
|
||||
(const SEC_WINNT_AUTH_IDENTITY_INFO*)identity);
|
||||
sspi_CopyAuthIdentity(&client->identity, identity);
|
||||
IFCALLRET(client->Logon, client->authenticated, client, &client->identity,
|
||||
TRUE);
|
||||
nego_free_nla(rdp->nego);
|
||||
@ -607,11 +749,16 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
IFCALLRET(client->Logon, client->authenticated, client, &client->identity,
|
||||
FALSE);
|
||||
}
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST);
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_NEGO:
|
||||
case CONNECTION_STATE_NLA:
|
||||
WINPR_ASSERT(FALSE); // TODO
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CREATE_REQUEST:
|
||||
if (!rdp_server_accept_mcs_connect_initial(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
@ -624,7 +771,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
|
||||
if (!rdp_server_accept_mcs_erect_domain_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
@ -637,7 +784,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
if (!rdp_server_accept_mcs_attach_user_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
@ -650,7 +797,7 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST:
|
||||
if (!rdp_server_accept_mcs_channel_join_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
@ -693,126 +840,242 @@ static int peer_recv_callback_internal(rdpTransport* transport, wStream* s, void
|
||||
__FUNCTION__, rdp_get_state_string(rdp));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_RESPONSE:
|
||||
if (settings->EarlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT)
|
||||
{
|
||||
ret = peer_recv_handle_auto_detect(client, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
ret = 2; /* Rerun, NULL stream */
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
{
|
||||
LicenseCallbackResult res;
|
||||
|
||||
if (!client->LicenseCallback)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"%s: LicenseCallback has been removed, assuming "
|
||||
"licensing is ok (please fix your app)",
|
||||
__FUNCTION__);
|
||||
res = LICENSE_CB_COMPLETED;
|
||||
}
|
||||
else
|
||||
res = client->LicenseCallback(client, s);
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case LICENSE_CB_INTERNAL_ERROR:
|
||||
WLog_ERR(TAG,
|
||||
"%s: %s - callback internal "
|
||||
"error, aborting",
|
||||
__FUNCTION__, rdp_get_state_string(rdp));
|
||||
break;
|
||||
|
||||
case LICENSE_CB_ABORT:
|
||||
break;
|
||||
|
||||
case LICENSE_CB_IN_PROGRESS:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case LICENSE_CB_COMPLETED:
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
ret = 2; /* Rerun, NULL stream */
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG,
|
||||
"%s: CONNECTION_STATE_LICENSING - unknown license callback "
|
||||
"result %d",
|
||||
__FUNCTION__, res);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = peer_recv_handle_licensing(client, s);
|
||||
if (ret > 0)
|
||||
rdp_server_transition_to_state(
|
||||
rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST);
|
||||
break;
|
||||
}
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST:
|
||||
if (settings->SupportMultitransport)
|
||||
{
|
||||
if (client->Capabilities && !client->Capabilities(client))
|
||||
{
|
||||
}
|
||||
else if (!rdp_send_demand_active(rdp))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"%s: %s - "
|
||||
"rdp_send_demand_active() fail",
|
||||
__FUNCTION__, rdp_get_state_string(rdp));
|
||||
}
|
||||
if (!multitransport_server_send_request(rdp->multitransport))
|
||||
ret = -23;
|
||||
else
|
||||
{
|
||||
if (s)
|
||||
{
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (ret < 0)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"%s: %s - "
|
||||
"peer_recv_pdu() fail",
|
||||
__FUNCTION__, rdp_get_state_string(rdp));
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
rdp_server_transition_to_state(
|
||||
rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* During reactivation sequence the client might sent some input or channel data
|
||||
* before receiving the Deactivate All PDU. We need to process them as usual.
|
||||
*/
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (ret < 0)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"%s: %s - "
|
||||
"peer_recv_pdu() fail",
|
||||
__FUNCTION__, rdp_get_state_string(rdp));
|
||||
}
|
||||
rdp_server_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
ret = 1; /* Rerun, initialize next state */
|
||||
}
|
||||
|
||||
break;
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_RESPONSE:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (ret < 0)
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
|
||||
if (client->Capabilities && !client->Capabilities(client))
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - peer_recv_pdu() fail", __FUNCTION__,
|
||||
WLog_ERR(TAG, "[%s] freerdp_peer::Capabilities() callback failed",
|
||||
rdp_get_state_string(rdp));
|
||||
}
|
||||
else if (!rdp_send_demand_active(rdp))
|
||||
{
|
||||
WLog_ERR(TAG, "[%s] rdp_send_demand_active() fail", rdp_get_state_string(rdp));
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_server_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT:
|
||||
if (settings->EarlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU)
|
||||
{
|
||||
MONITOR_DEF* monitors = NULL;
|
||||
|
||||
IFCALL(client->AdjustMonitorsLayout, client);
|
||||
|
||||
/* client supports the monitorLayout PDU, let's send him the monitors if any */
|
||||
ret = -1;
|
||||
if (freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount) == 0)
|
||||
{
|
||||
const UINT32 w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
||||
const UINT32 h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
||||
const rdpMonitor primary = { .x = 0,
|
||||
.y = 0,
|
||||
.width = w,
|
||||
.height = h,
|
||||
.is_primary = TRUE,
|
||||
.orig_screen = 0,
|
||||
.attributes = { .physicalWidth = w,
|
||||
.physicalHeight = h,
|
||||
.orientation =
|
||||
ORIENTATION_LANDSCAPE,
|
||||
.desktopScaleFactor = 100,
|
||||
.deviceScaleFactor = 100 } };
|
||||
if (!freerdp_settings_set_pointer_array(settings, FreeRDP_MonitorDefArray, 0,
|
||||
&primary))
|
||||
ret = -2;
|
||||
else if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1))
|
||||
ret = -3;
|
||||
}
|
||||
if (ret < -1)
|
||||
{
|
||||
}
|
||||
else if (!display_convert_rdp_monitor_to_monitor_def(
|
||||
settings->MonitorCount, settings->MonitorDefArray, &monitors))
|
||||
{
|
||||
}
|
||||
else if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount,
|
||||
monitors))
|
||||
{
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
free(monitors);
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE:
|
||||
/**
|
||||
* During reactivation sequence the client might sent some input or channel data
|
||||
* before receiving the Deactivate All PDU. We need to process them as usual.
|
||||
*/
|
||||
ret = peer_recv_pdu(client, s);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION_SYNC:
|
||||
rdp_finalize_reset_flags(rdp, FALSE);
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
|
||||
{
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_COOPERATE))
|
||||
ret = -2;
|
||||
}
|
||||
else
|
||||
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_COOPERATE:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
|
||||
{
|
||||
if (!rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL))
|
||||
ret = -2;
|
||||
}
|
||||
else
|
||||
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_REQUEST_CONTROL:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU))
|
||||
{
|
||||
if (!rdp_server_transition_to_state(
|
||||
rdp, CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST))
|
||||
ret = -2;
|
||||
}
|
||||
else
|
||||
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_PERSISTENT_KEY_LIST:
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_BitmapCachePersistEnabled) &&
|
||||
!rdp_finalize_is_flag_set(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
|
||||
{
|
||||
ret = peer_recv_pdu(client, s);
|
||||
|
||||
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU))
|
||||
{
|
||||
if (!rdp_server_transition_to_state(rdp,
|
||||
CONNECTION_STATE_FINALIZATION_FONT_LIST))
|
||||
ret = -2;
|
||||
}
|
||||
else
|
||||
ret = peer_unexpected_client_message(rdp,
|
||||
CONNECTION_STATE_FINALIZATION_FONT_LIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_FONT_LIST))
|
||||
ret = -2;
|
||||
else
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_FONT_LIST:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (rdp_finalize_is_flag_set(rdp, FINALIZE_CS_FONT_LIST_PDU))
|
||||
{
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
|
||||
ret = -2;
|
||||
update_reset_state(rdp->update);
|
||||
}
|
||||
else
|
||||
ret = peer_unexpected_client_message(rdp, FINALIZE_CS_FONT_LIST_PDU);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
ret = peer_recv_pdu(client, s);
|
||||
if (ret < 0)
|
||||
if (!client->connected)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - peer_recv_pdu() fail", __FUNCTION__,
|
||||
rdp_get_state_string(rdp));
|
||||
/**
|
||||
* PostConnect should only be called once and should not
|
||||
* be called after a reactivation sequence.
|
||||
*/
|
||||
IFCALLRET(client->PostConnect, client->connected, client);
|
||||
}
|
||||
if (!client->connected)
|
||||
{
|
||||
switch (rdp_get_state(rdp))
|
||||
{
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
|
||||
ret = 1;
|
||||
break;
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
default:
|
||||
ret = -24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!client->activated)
|
||||
IFCALLRET(client->Activate, client->activated, client);
|
||||
|
||||
if (!client->activated)
|
||||
ret = -23;
|
||||
else
|
||||
ret = peer_recv_pdu(client, s);
|
||||
}
|
||||
break;
|
||||
|
||||
/* States that must not happen in server state machine */
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_SYNC:
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE:
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL:
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP:
|
||||
default:
|
||||
WLog_ERR(TAG, "%s state %d", rdp_get_state_string(rdp), rdp_get_state(rdp));
|
||||
break;
|
||||
@ -831,9 +1094,6 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
default:
|
||||
rc = peer_recv_callback_internal(transport, s, extra);
|
||||
break;
|
||||
case 2:
|
||||
rc = peer_recv_callback_internal(transport, NULL, extra);
|
||||
break;
|
||||
}
|
||||
} while (rc > 0);
|
||||
|
||||
|
@ -1617,29 +1617,31 @@ static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
/* TODO: Need to properly return:
|
||||
*
|
||||
* -24 ... Rerun state machine, ignore wStream* s reset
|
||||
* -23 ... Rerun state machine, reset wStream* s
|
||||
* -1 ... Failure
|
||||
* 0 ... Success
|
||||
* 2 ... State ACTIVE
|
||||
*/
|
||||
static int 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 = 0;
|
||||
rdpRdp* rdp = (rdpRdp*)extra;
|
||||
|
||||
WINPR_ASSERT(transport);
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(s);
|
||||
/*
|
||||
* At any point in the connection sequence between when all
|
||||
* MCS channels have been joined and when the RDP connection
|
||||
* enters the active state, an auto-detect PDU can be received
|
||||
* on the MCS message channel.
|
||||
*/
|
||||
if ((rdp_get_state(rdp) > CONNECTION_STATE_MCS_CHANNEL_JOIN) &&
|
||||
(rdp_get_state(rdp) < CONNECTION_STATE_ACTIVE))
|
||||
{
|
||||
if (rdp_client_connect_auto_detect(rdp, s))
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (rdp_get_state(rdp))
|
||||
{
|
||||
case CONNECTION_STATE_NEGO:
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST);
|
||||
status = -24;
|
||||
break;
|
||||
case CONNECTION_STATE_NLA:
|
||||
if (nla_get_state(rdp->nla) < NLA_STATE_AUTH_INFO)
|
||||
{
|
||||
@ -1647,7 +1649,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - nla_recv_pdu() fail", __FUNCTION__,
|
||||
rdp_get_state_string(rdp));
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else if (nla_get_state(rdp->nla) == NLA_STATE_POST_NEGO)
|
||||
@ -1658,92 +1660,113 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - nego_recv() fail", __FUNCTION__,
|
||||
rdp_get_state_string(rdp));
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
|
||||
return -1;
|
||||
else if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (nla_get_state(rdp->nla) == NLA_STATE_AUTH_INFO)
|
||||
if (status >= 0)
|
||||
{
|
||||
transport_set_nla_mode(rdp->transport, FALSE);
|
||||
|
||||
if (rdp->settings->VmConnectMode)
|
||||
if (nla_get_state(rdp->nla) == NLA_STATE_AUTH_INFO)
|
||||
{
|
||||
if (!nego_set_state(rdp->nego, NEGO_STATE_NLA))
|
||||
return -1;
|
||||
transport_set_nla_mode(rdp->transport, FALSE);
|
||||
|
||||
if (!nego_set_requested_protocols(rdp->nego, PROTOCOL_HYBRID | PROTOCOL_SSL))
|
||||
return -1;
|
||||
|
||||
nego_send_negotiation_request(rdp->nego);
|
||||
|
||||
if (!nla_set_state(rdp->nla, NLA_STATE_POST_NEGO))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
|
||||
return -1;
|
||||
if (rdp->settings->VmConnectMode)
|
||||
{
|
||||
if (!nego_set_state(rdp->nego, NEGO_STATE_NLA))
|
||||
status = -1;
|
||||
else if (!nego_set_requested_protocols(rdp->nego,
|
||||
PROTOCOL_HYBRID | PROTOCOL_SSL))
|
||||
status = -1;
|
||||
else
|
||||
{
|
||||
if (!nego_send_negotiation_request(rdp->nego))
|
||||
status = -1;
|
||||
else if (!nla_set_state(rdp->nla, NLA_STATE_POST_NEGO))
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nla_get_state(rdp->nla) == NLA_STATE_FINAL)
|
||||
if (status >= 0)
|
||||
{
|
||||
nla_free(rdp->nla);
|
||||
rdp->nla = NULL;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CONNECT);
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
if (nla_get_state(rdp->nla) == NLA_STATE_FINAL)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - mcs_client_begin() fail", __FUNCTION__,
|
||||
rdp_get_state_string(rdp));
|
||||
return -1;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST);
|
||||
status = -23;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
case CONNECTION_STATE_MCS_CREATE_REQUEST:
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s - mcs_client_begin() fail", __FUNCTION__,
|
||||
rdp_get_state_string(rdp));
|
||||
status = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_RESPONSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CREATE_RESPONSE:
|
||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_recv_connect_response failure");
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_erect_domain_request failure");
|
||||
return -1;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
|
||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_erect_domain_request failure");
|
||||
status = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_attach_user_request failure");
|
||||
status = -1;
|
||||
}
|
||||
else
|
||||
rdp_client_transition_to_state(rdp,
|
||||
CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_attach_user_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM:
|
||||
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_recv_attach_user_confirm failure");
|
||||
return -1;
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_channel_join_request failure");
|
||||
return -1;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST);
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_channel_join_request failure");
|
||||
status = -1;
|
||||
}
|
||||
else
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE);
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE:
|
||||
if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
@ -1755,6 +1778,14 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
|
||||
if (!rdp_client_connect_auto_detect(rdp, s))
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
status = -23;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
status = rdp_client_connect_license(rdp, s);
|
||||
|
||||
@ -1764,7 +1795,16 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST:
|
||||
if (!rdp_client_connect_auto_detect(rdp, s))
|
||||
{
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
|
||||
status = -23;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
|
||||
status = rdp_client_connect_demand_active(rdp, s);
|
||||
|
||||
if (status < 0)
|
||||
@ -1772,23 +1812,102 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
"%s: %s - "
|
||||
"rdp_client_connect_demand_active() - %i",
|
||||
__FUNCTION__, rdp_get_state_string(rdp), status);
|
||||
|
||||
else
|
||||
{
|
||||
if (!rdp->settings->SupportMonitorLayoutPdu)
|
||||
{
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE);
|
||||
status = -23;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT:
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
|
||||
if ((status >= 0) && rdp_finalize_is_flag_set(rdp, FINALIZE_SC_COMPLETE))
|
||||
if (status >= 0)
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE);
|
||||
return 2;
|
||||
status = -23;
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE);
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE:
|
||||
status = rdp_client_connect_confirm_active(rdp, s);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_SYNC:
|
||||
{
|
||||
const UINT32 flags = rdp->finalize_sc_pdus & mask;
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 uflags = rdp->finalize_sc_pdus & mask;
|
||||
if (flags != uflags)
|
||||
rdp_client_transition_to_state(rdp,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE);
|
||||
else
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE:
|
||||
{
|
||||
const UINT32 flags = rdp->finalize_sc_pdus & mask;
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 uflags = rdp->finalize_sc_pdus & mask;
|
||||
if (flags != uflags)
|
||||
rdp_client_transition_to_state(
|
||||
rdp, CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL);
|
||||
else
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL:
|
||||
{
|
||||
const UINT32 flags = rdp->finalize_sc_pdus & mask;
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 uflags = rdp->finalize_sc_pdus & mask;
|
||||
if (flags != uflags)
|
||||
rdp_client_transition_to_state(rdp,
|
||||
CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP);
|
||||
else
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP:
|
||||
{
|
||||
const UINT32 flags = rdp->finalize_sc_pdus & mask;
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 uflags = rdp->finalize_sc_pdus & mask;
|
||||
if (flags == uflags)
|
||||
WLog_WARN(TAG, "Did not receive a FINALIZE_SC_FONT_MAP_PDU");
|
||||
|
||||
{
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE);
|
||||
status = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "%s: %s - rdp_recv_pdu() - %i", __FUNCTION__,
|
||||
rdp_get_state_string(rdp), status);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
@ -1806,9 +1925,26 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0 && status > -23)
|
||||
{
|
||||
WLog_ERR(TAG, "%s: %s status %d", __FUNCTION__, rdp_get_state_string(rdp), status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
int rc = -1;
|
||||
const size_t start = Stream_GetPosition(s);
|
||||
do
|
||||
{
|
||||
if (rc == -23)
|
||||
Stream_SetPosition(s, start);
|
||||
rc = rdp_recv_callback_int(transport, s, extra);
|
||||
} while (rc <= -23);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
|
||||
{
|
||||
return freerdp_channel_send(rdp, channelId, data, size);
|
||||
|
Loading…
Reference in New Issue
Block a user