libfreerdp-core: started handling flow control, can get further with TSG

This commit is contained in:
Marc-André Moreau 2012-11-16 21:17:04 -05:00
parent 25efc0da84
commit 0073d0baea
3 changed files with 108 additions and 6 deletions

View File

@ -458,7 +458,10 @@ int rpc_in_write(rdpRpc* rpc, BYTE* data, int length)
status = tls_write_all(rpc->TlsIn, data, length);
if (status > 0)
{
rpc->VirtualConnection->DefaultInChannel->BytesSent += status;
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status;
}
return status;
}
@ -812,18 +815,31 @@ int rpc_recv_pdu(rdpRpc* rpc)
if (header->common.ptype == PTYPE_RTS) /* RTS PDU */
{
return header->common.frag_length;
if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
return header->common.frag_length;
printf("Receiving Out-of-Sequence RTS PDU\n");
rts_recv_out_of_sequence_pdu(rpc);
return rpc_recv_pdu(rpc);
}
else if (header->common.ptype == PTYPE_FAULT)
{
rpc_recv_fault_pdu(header);
return -1;
}
else
rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;
/*printf("BytesReceived: %d ReceiverAvailableWindow: %d ReceiveWindow: %d\n",
rpc->VirtualConnection->DefaultOutChannel->BytesReceived,
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow,
rpc->ReceiveWindow);*/
if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2))
{
/* RTS PDUs are not subject to flow control */
rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;
printf("Sending Flow Control Ack PDU\n");
rts_send_flow_control_ack_pdu(rpc);
}
#ifdef WITH_DEBUG_RPC
@ -986,6 +1002,7 @@ void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* conne
connection->DefaultOutChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
connection->DefaultOutChannel->ReceiveWindow = rpc->ReceiveWindow;
connection->DefaultOutChannel->ReceiveWindowSize = rpc->ReceiveWindow;
connection->DefaultOutChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
}
RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)

View File

@ -840,9 +840,12 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc)
DEBUG_RPC("Sending FlowControlAck RTS PDU");
BytesReceived = rpc->VirtualConnection->DefaultOutChannel->BytesReceived;
AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow;
AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised;
ChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultOutChannelCookie);
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow =
rpc->VirtualConnection->DefaultOutChannel->AvailableWindowAdvertised;
buffer = (BYTE*) malloc(header.frag_length);
CopyMemory(buffer, ((BYTE*) &header), 20); /* RTS Header (20 bytes) */
@ -1192,6 +1195,74 @@ BOOL rts_match_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rt
return TRUE;
}
int rts_extract_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature, rpcconn_rts_hdr_t* rts)
{
int i;
int status;
BYTE* buffer;
UINT32 length;
UINT32 offset;
UINT32 CommandType;
UINT32 CommandLength;
signature->Flags = rts->Flags;
signature->NumberOfCommands = rts->NumberOfCommands;
buffer = (BYTE*) rts;
offset = RTS_PDU_HEADER_LENGTH;
length = rts->frag_length - offset;
for (i = 0; i < rts->NumberOfCommands; i++)
{
CommandType = *((UINT32*) &buffer[offset]); /* CommandType (4 bytes) */
offset += 4;
signature->CommandTypes[i] = CommandType;
status = rts_command_length(rpc, CommandType, &buffer[offset], length);
if (status < 0)
return FALSE;
CommandLength = (UINT32) status;
offset += CommandLength;
length = rts->frag_length - offset;
}
return 0;
}
int rts_print_pdu_signature(rdpRpc* rpc, RtsPduSignature* signature)
{
int i, j;
RtsPduSignature* pSignature;
printf("RTS PDU Signature: Flags: 0x%04X NumberOfCommands: %d\n",
signature->Flags, signature->NumberOfCommands);
for (i = 0; RTS_PDU_SIGNATURE_TABLE[i].SignatureId != 0; i++)
{
pSignature = RTS_PDU_SIGNATURE_TABLE[i].Signature;
if (signature->Flags == pSignature->Flags)
{
if (signature->NumberOfCommands == pSignature->NumberOfCommands)
{
for (j = 0; j < signature->NumberOfCommands; j++)
{
if (signature->CommandTypes[j] != pSignature->CommandTypes[j])
continue;
}
printf("Identified %s RTS PDU\n", RTS_PDU_SIGNATURE_TABLE[i].PduName);
}
}
}
return 0;
}
int rts_recv_pdu_commands(rdpRpc* rpc, rpcconn_rts_hdr_t* rts)
{
int i;
@ -1317,3 +1388,16 @@ int rts_recv_pdu(rdpRpc* rpc)
return status;
}
int rts_recv_out_of_sequence_pdu(rdpRpc* rpc)
{
rpcconn_rts_hdr_t* rts;
RtsPduSignature signature;
rts = (rpcconn_rts_hdr_t*) rpc->buffer;
rts_extract_pdu_signature(rpc, &signature, rts);
rts_print_pdu_signature(rpc, &signature);
return 0;
}

View File

@ -222,6 +222,7 @@ int rts_send_flow_control_ack_pdu(rdpRpc* rpc);
int rts_send_ping_pdu(rdpRpc* rpc);
int rts_recv_pdu(rdpRpc* rpc);
int rts_recv_out_of_sequence_pdu(rdpRpc* rpc);
#ifdef WITH_DEBUG_TSG
#define WITH_DEBUG_RTS