libfreerdp-core: Make tsg out channel recycling event driven

This commit is contained in:
Denis Vincent 2015-02-24 15:34:41 -05:00
parent 65b2842792
commit baab23fd14
6 changed files with 104 additions and 69 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);