diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index c11743f44..fc0906175 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -631,7 +631,6 @@ void* wf_input_thread(void* arg) DWORD WINAPI wf_client_thread(LPVOID lpParam) { MSG msg; - int index; int width; int height; BOOL msg_ret; @@ -741,8 +740,6 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam) if (quit_msg) break; - - Sleep(100); } /* cleanup */ diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index e17c7c8a1..3a211def2 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -890,34 +890,6 @@ int rpc_out_channel_replacement_connect(RpcOutChannel* outChannel, int timeout) rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY); - /* Receive response. */ - response = http_response_recv(outChannel->tls); - - if (!response) - return -1; - - status = rpc_ncacn_http_recv_out_channel_response(rpc, outChannel, response); - - http_response_free(response); - - if ( status < 0) - { - WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure"); - return -1; - } - - /* Send OUT Channel Request */ - - if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel, TRUE) < 0) - { - WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure"); - return -1; - } - - rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) outChannel); - - rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_NEGOTIATED); - return 1; } diff --git a/libfreerdp/core/gateway/rpc.h b/libfreerdp/core/gateway/rpc.h index d7994c8c3..71c085639 100644 --- a/libfreerdp/core/gateway/rpc.h +++ b/libfreerdp/core/gateway/rpc.h @@ -654,6 +654,7 @@ enum _CLIENT_OUT_CHANNEL_STATE CLIENT_OUT_CHANNEL_STATE_OPENED_A6W, CLIENT_OUT_CHANNEL_STATE_OPENED_A10W, CLIENT_OUT_CHANNEL_STATE_OPENED_B3W, + CLIENT_OUT_CHANNEL_STATE_RECYCLED, CLIENT_OUT_CHANNEL_STATE_FINAL }; typedef enum _CLIENT_OUT_CHANNEL_STATE CLIENT_OUT_CHANNEL_STATE; diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 2093e1292..a7ecb102e 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -445,7 +445,7 @@ int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment) return 1; } -int rpc_client_out_channel_recv(rdpRpc* rpc) +int rpc_client_default_out_channel_recv(rdpRpc* rpc) { int status = -1; HttpResponse* response; @@ -481,10 +481,10 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) return -1; } - rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*) outChannel); + rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*)outChannel); rpc_out_channel_transition_to_state(outChannel, - CLIENT_OUT_CHANNEL_STATE_NEGOTIATED); + CLIENT_OUT_CHANNEL_STATE_NEGOTIATED); /* Send CONN/A1 PDU over OUT channel */ @@ -495,7 +495,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) } rpc_out_channel_transition_to_state(outChannel, - CLIENT_OUT_CHANNEL_STATE_OPENED); + CLIENT_OUT_CHANNEL_STATE_OPENED); if (inChannel->State == CLIENT_IN_CHANNEL_STATE_OPENED) { @@ -535,7 +535,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) http_response_free(response); rpc_virtual_connection_transition_to_state(rpc, - rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_WAIT_A3W); + rpc->VirtualConnection, VIRTUAL_CONNECTION_STATE_WAIT_A3W); status = 1; } @@ -551,7 +551,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) while (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH) { status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment), - RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment)); + RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(fragment)); if (status < 0) return -1; @@ -565,12 +565,12 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) if (Stream_GetPosition(fragment) < RPC_COMMON_FIELDS_LENGTH) return status; - header = (rpcconn_common_hdr_t*) Stream_Buffer(fragment); + header = (rpcconn_common_hdr_t*)Stream_Buffer(fragment); if (header->frag_length > rpc->max_recv_frag) { WLog_ERR(TAG, "rpc_client_recv: invalid fragment size: %d (max: %d)", - header->frag_length, rpc->max_recv_frag); + header->frag_length, rpc->max_recv_frag); winpr_HexDump(TAG, WLOG_ERROR, Stream_Buffer(fragment), Stream_GetPosition(fragment)); return -1; } @@ -578,7 +578,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) while (Stream_GetPosition(fragment) < header->frag_length) { status = rpc_out_channel_read(outChannel, Stream_Pointer(fragment), - header->frag_length - Stream_GetPosition(fragment)); + header->frag_length - Stream_GetPosition(fragment)); if (status < 0) { @@ -604,13 +604,23 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) status = rpc_client_recv_fragment(rpc, fragment); - /* channel recycling may update channel pointers */ - inChannel = connection->DefaultInChannel; - outChannel = connection->DefaultOutChannel; - if (status < 0) return status; + /* channel recycling may update channel pointers */ + inChannel = connection->DefaultInChannel; + if (outChannel->State == CLIENT_OUT_CHANNEL_STATE_RECYCLED && connection->NonDefaultOutChannel) + { + rpc_out_channel_free(connection->DefaultOutChannel); + connection->DefaultOutChannel = connection->NonDefaultOutChannel; + connection->NonDefaultOutChannel = NULL; + + rpc_out_channel_transition_to_state(connection->DefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED); + rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT); + + return 0; + } + Stream_SetPosition(fragment, 0); } } @@ -619,6 +629,83 @@ int rpc_client_out_channel_recv(rdpRpc* rpc) return status; } +int rpc_client_nondefault_out_channel_recv(rdpRpc* rpc) +{ + int status = -1; + HttpResponse* response; + RpcOutChannel* nextOutChannel; + + nextOutChannel = rpc->VirtualConnection->NonDefaultOutChannel; + + response = http_response_recv(nextOutChannel->tls); + if (response) + { + if (nextOutChannel->State == CLIENT_OUT_CHANNEL_STATE_SECURITY) + { + status = rpc_ncacn_http_recv_out_channel_response(rpc, nextOutChannel, response); + if (status >= 0) + { + status = rpc_ncacn_http_send_out_channel_request(rpc, nextOutChannel, TRUE); + if (status >= 0) + { + rpc_ncacn_http_ntlm_uninit(rpc, (RpcChannel*)nextOutChannel); + status = rts_send_OUT_R1_A3_pdu(rpc); + if (status >= 0) + { + rpc_out_channel_transition_to_state(nextOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W); + } + else + { + WLog_ERR(TAG, "rts_send_OUT_R1/A3_pdu failure"); + } + } + else + { + WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure"); + } + } + else + { + WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure"); + } + } + + http_response_free(response); + } + + return status; +} + +int rpc_client_out_channel_recv(rdpRpc* rpc) +{ + RpcOutChannel* outChannel; + RpcOutChannel* nextOutChannel; + RpcVirtualConnection* connection = rpc->VirtualConnection; + HANDLE outChannelEvent = NULL; + HANDLE nextOutChannelEvent = NULL; + + outChannel = connection->DefaultOutChannel; + BIO_get_event(outChannel->tls->bio, &outChannelEvent); + + if (WaitForSingleObject(outChannelEvent, 0) == WAIT_OBJECT_0) + { + return rpc_client_default_out_channel_recv(rpc); + } + + nextOutChannel = connection->NonDefaultOutChannel; + if (nextOutChannel) + { + BIO_get_event(nextOutChannel->tls->bio, &nextOutChannelEvent); + + if (WaitForSingleObject(nextOutChannelEvent, 0) == WAIT_OBJECT_0) + { + return rpc_client_nondefault_out_channel_recv(rpc); + } + } + + return 0; +} + int rpc_client_in_channel_recv(rdpRpc* rpc) { int status = -1; diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 12a04655a..aa775c0a5 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -926,15 +926,6 @@ int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) return -1; } - status = rts_send_OUT_R1_A3_pdu(rpc); - - if (status < 0) - { - WLog_ERR(TAG, "rts_send_OUT_R1/A3_pdu failure"); - return -1; - } - - rpc_out_channel_transition_to_state(connection->NonDefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W); rpc_out_channel_transition_to_state(connection->DefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED_A6W); return 1; @@ -971,26 +962,11 @@ int rts_recv_OUT_R2_A6_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) int rts_recv_OUT_R2_B3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) { - int status; - HttpResponse* response; RpcVirtualConnection* connection = rpc->VirtualConnection; WLog_DBG(TAG, "Receiving OUT R2/B3 RTS PDU"); - rpc_out_channel_free(connection->DefaultOutChannel); - connection->DefaultOutChannel = connection->NonDefaultOutChannel; - connection->NonDefaultOutChannel = NULL; - - rpc_out_channel_transition_to_state(connection->DefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_OPENED); - - response = http_response_recv(connection->DefaultOutChannel->tls); - - if (!response) - return -1; - - status = rpc_ncacn_http_recv_out_channel_response(rpc, connection->DefaultOutChannel, response); - - http_response_free(response); + rpc_out_channel_transition_to_state(connection->DefaultOutChannel, CLIENT_OUT_CHANNEL_STATE_RECYCLED); return 1; } diff --git a/libfreerdp/core/gateway/rts.h b/libfreerdp/core/gateway/rts.h index b3fabafb0..180c27161 100644 --- a/libfreerdp/core/gateway/rts.h +++ b/libfreerdp/core/gateway/rts.h @@ -135,6 +135,8 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc); int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length); +int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc); + int rts_send_keep_alive_pdu(rdpRpc* rpc); int rts_send_flow_control_ack_pdu(rdpRpc* rpc); int rts_send_ping_pdu(rdpRpc* rpc);