libfreerdp-core: refactoring of sending/receiving duplicated code

This commit is contained in:
Marc-André Moreau 2012-11-16 18:30:53 -05:00
parent 07d820cf04
commit 25efc0da84
5 changed files with 143 additions and 146 deletions

View File

@ -328,7 +328,7 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
/* Send OUT Channel Request */
DEBUG_RPC("\n%s", s->data);
tls_write_all(rpc->TlsOut, s->data, s->size);
rpc_out_write(rpc, s->data, s->size);
stream_free(s);
/* Receive OUT Channel Response */
@ -351,7 +351,7 @@ BOOL rpc_ntlm_http_out_connect(rdpRpc* rpc)
/* Send OUT Channel Request */
DEBUG_RPC("\n%s", s->data);
tls_write_all(rpc->TlsOut, s->data, s->size);
rpc_out_write(rpc, s->data, s->size);
stream_free(s);
ntlm_client_uninit(ntlm);
@ -391,7 +391,7 @@ BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
/* Send IN Channel Request */
DEBUG_RPC("\n%s", s->data);
tls_write_all(rpc->TlsIn, s->data, s->size);
rpc_in_write(rpc, s->data, s->size);
stream_free(s);
/* Receive IN Channel Response */
@ -414,7 +414,7 @@ BOOL rpc_ntlm_http_in_connect(rdpRpc* rpc)
/* Send IN Channel Request */
DEBUG_RPC("\n%s", s->data);
tls_write_all(rpc->TlsIn, s->data, s->size);
rpc_in_write(rpc, s->data, s->size);
stream_free(s);
ntlm_client_uninit(ntlm);
@ -433,17 +433,18 @@ void rpc_pdu_header_init(rdpRpc* rpc, rpcconn_hdr_t* header)
header->common.packed_drep[3] = rpc->packed_drep[3];
}
int rpc_out_write(rdpRpc* rpc, BYTE* data, int length)
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
{
int status;
rpc_pdu_header_print((rpcconn_hdr_t*) data);
status = tls_read(rpc->TlsOut, data, length);
#ifdef WITH_DEBUG_RPC
printf("rpc_out_write(): length: %d\n", length);
freerdp_hexdump(data, length);
printf("\n");
#endif
return status;
}
int rpc_out_write(rdpRpc* rpc, BYTE* data, int length)
{
int status;
status = tls_write_all(rpc->TlsOut, data, length);
@ -454,14 +455,6 @@ int rpc_in_write(rdpRpc* rpc, BYTE* data, int length)
{
int status;
rpc_pdu_header_print((rpcconn_hdr_t*) data);
#ifdef WITH_DEBUG_RPC
printf("rpc_in_write() length: %d\n", length);
freerdp_hexdump(data, length);
printf("\n");
#endif
status = tls_write_all(rpc->TlsIn, data, length);
if (status > 0)
@ -666,58 +659,6 @@ BOOL rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
return TRUE;
}
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
{
int status;
rpcconn_hdr_t* header;
//if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < 0x00008FFF) /* Just a simple workaround */
// rts_send_flow_control_ack_pdu(rpc); /* Send FlowControlAck every time AvailableWindow reaches the half */
/* Read common header fields */
status = tls_read(rpc->TlsOut, data, RPC_COMMON_FIELDS_LENGTH);
if (status <= 0)
return status;
header = (rpcconn_hdr_t*) data;
rpc_pdu_header_print(header);
status = tls_read(rpc->TlsOut, &data[RPC_COMMON_FIELDS_LENGTH],
header->common.frag_length - RPC_COMMON_FIELDS_LENGTH);
if (status < 0)
return status;
if (header->common.ptype == PTYPE_RTS) /* RTS PDU */
{
printf("rpc_out_read error: Unexpected RTS PDU\n");
return -1;
}
else
{
/* RTS PDUs are not subject to flow control */
rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;
}
if (length < header->common.frag_length)
{
printf("rpc_out_read error! receive buffer is not large enough: %d < %d\n",
length, header->common.frag_length);
return -1;
}
#ifdef WITH_DEBUG_RPC
printf("rpc_out_read(): length: %d\n", header->common.frag_length);
freerdp_hexdump(data, header->common.frag_length);
printf("\n");
#endif
return header->common.frag_length;
}
int rpc_recv_fault_pdu(rpcconn_hdr_t* header)
{
int index;
@ -799,7 +740,7 @@ int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header)
while (bytesRead < RPC_COMMON_FIELDS_LENGTH)
{
status = tls_read(rpc->TlsOut, &header[bytesRead], RPC_COMMON_FIELDS_LENGTH - bytesRead);
status = rpc_out_read(rpc, &header[bytesRead], RPC_COMMON_FIELDS_LENGTH - bytesRead);
if (status < 0)
{
@ -809,14 +750,12 @@ int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header)
bytesRead += status;
}
rpc_pdu_header_print((rpcconn_hdr_t*) header);
rpc_get_stub_data_info(rpc, header, &offset, NULL);
while (bytesRead < offset)
{
status = tls_read(rpc->TlsOut, &header[bytesRead], offset - bytesRead);
status = rpc_out_read(rpc, &header[bytesRead], offset - bytesRead);
if (status < 0)
return status;
@ -855,7 +794,7 @@ int rpc_recv_pdu(rdpRpc* rpc)
while (bytesRead < header->common.frag_length)
{
status = tls_read(rpc->TlsOut, &rpc->buffer[bytesRead], header->common.frag_length - bytesRead);
status = rpc_out_read(rpc, &rpc->buffer[bytesRead], header->common.frag_length - bytesRead);
if (status < 0)
{
@ -868,7 +807,7 @@ int rpc_recv_pdu(rdpRpc* rpc)
if (!(header->common.pfc_flags & PFC_LAST_FRAG))
{
printf("Fragmented PDU\n");
DEBUG_RPC("Fragmented PDU");
}
if (header->common.ptype == PTYPE_RTS) /* RTS PDU */
@ -941,13 +880,8 @@ int rpc_tsg_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
stub_data_pad = 0;
stub_data_pad = rpc_offset_align(&offset, 8);
printf("stub_data_pad: %d\n", stub_data_pad);
offset += length;
request_pdu->auth_verifier.auth_pad_length = rpc_offset_align(&offset, 4);
printf("auth_pad_length: %d\n", request_pdu->auth_verifier.auth_pad_length);
request_pdu->auth_verifier.auth_type = RPC_C_AUTHN_WINNT;
request_pdu->auth_verifier.auth_level = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
request_pdu->auth_verifier.auth_reserved = 0x00;
@ -1039,16 +973,19 @@ BOOL rpc_connect(rdpRpc* rpc)
return TRUE;
}
void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* virtual_connection)
void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* connection)
{
virtual_connection->DefaultInChannel->BytesSent = 0;
virtual_connection->DefaultOutChannel->BytesReceived = 0;
virtual_connection->DefaultOutChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
virtual_connection->DefaultOutChannel->ReceiveWindow = rpc->ReceiveWindow;
virtual_connection->DefaultOutChannel->ReceiveWindowSize = rpc->ReceiveWindow;
virtual_connection->DefaultInChannel->SenderAvailableWindow = rpc->ReceiveWindow;
virtual_connection->DefaultInChannel->PingOriginator.ConnectionTimeout = 30;
virtual_connection->DefaultInChannel->PingOriginator.KeepAliveInterval = 0;
connection->DefaultInChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
connection->DefaultInChannel->BytesSent = 0;
connection->DefaultInChannel->SenderAvailableWindow = rpc->ReceiveWindow;
connection->DefaultInChannel->PingOriginator.ConnectionTimeout = 30;
connection->DefaultInChannel->PingOriginator.KeepAliveInterval = 0;
connection->DefaultOutChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
connection->DefaultOutChannel->BytesReceived = 0;
connection->DefaultOutChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
connection->DefaultOutChannel->ReceiveWindow = rpc->ReceiveWindow;
connection->DefaultOutChannel->ReceiveWindowSize = rpc->ReceiveWindow;
}
RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
@ -1201,7 +1138,10 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->ReceiveWindow = 0x00010000;
rpc->KeepAliveInterval = 30000;
rpc->ChannelLifetime = 0x40000000;
rpc->ChannelLifetimeSet = 0;
rpc->KeepAliveInterval = 300000;
rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
rpc->CurrentKeepAliveTime = 0;

View File

@ -545,10 +545,21 @@ typedef struct rpc_ping_originator RpcPingOriginator;
/* Client In Channel */
enum _CLIENT_IN_CHANNEL_STATE
{
CLIENT_IN_CHANNEL_STATE_INITIAL,
CLIENT_IN_CHANNEL_STATE_OPENED,
CLIENT_IN_CHANNEL_STATE_OPENED_A4W,
CLIENT_IN_CHANNEL_STATE_FINAL
};
typedef enum _CLIENT_IN_CHANNEL_STATE CLIENT_IN_CHANNEL_STATE;
struct rpc_in_channel
{
/* Sending Channel */
CLIENT_IN_CHANNEL_STATE State;
UINT32 PlugState;
void* SendQueue;
UINT32 BytesSent;
@ -563,10 +574,23 @@ typedef struct rpc_in_channel RpcInChannel;
/* Client Out Channel */
enum _CLIENT_OUT_CHANNEL_STATE
{
CLIENT_OUT_CHANNEL_STATE_INITIAL,
CLIENT_OUT_CHANNEL_STATE_OPENED,
CLIENT_OUT_CHANNEL_STATE_OPENED_A6W,
CLIENT_OUT_CHANNEL_STATE_OPENED_A10W,
CLIENT_OUT_CHANNEL_STATE_OPENED_B3W,
CLIENT_OUT_CHANNEL_STATE_FINAL
};
typedef enum _CLIENT_OUT_CHANNEL_STATE CLIENT_OUT_CHANNEL_STATE;
struct rpc_out_channel
{
/* Receiving Channel */
CLIENT_OUT_CHANNEL_STATE State;
UINT32 ReceiveWindow;
UINT32 ReceiveWindowSize;
UINT32 ReceiverAvailableWindow;
@ -651,6 +675,9 @@ struct rdp_rpc
UINT32 ReceiveWindow;
UINT32 ChannelLifetime;
UINT32 ChannelLifetimeSet;
UINT32 KeepAliveInterval;
UINT32 CurrentKeepAliveTime;
UINT32 CurrentKeepAliveInterval;
@ -676,7 +703,6 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* l
int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header);
int rpc_recv_pdu(rdpRpc* rpc);
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length);
int rpc_tsg_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum);

View File

@ -360,9 +360,10 @@ void rts_pdu_header_init(rpcconn_rts_hdr_t* header)
header->call_id = 0;
}
int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length)
int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, UINT32* ReceiveWindowSize)
{
/* ReceiveWindowSize (4 bytes) */
if (ReceiveWindowSize)
*ReceiveWindowSize = *((UINT32*) &buffer[0]); /* ReceiveWindowSize (4 bytes) */
return 4;
}
@ -467,6 +468,12 @@ int rts_client_keepalive_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length)
int rts_client_keepalive_command_write(BYTE* buffer, UINT32 ClientKeepalive)
{
/**
* An unsigned integer that specifies the keep-alive interval, in milliseconds,
* that this connection is configured to use. This value MUST be 0 or in the inclusive
* range of 60,000 through 4,294,967,295. If it is 0, it MUST be interpreted as 300,000.
*/
if (buffer)
{
*((UINT32*) &buffer[0]) = RTS_CMD_CLIENT_KEEPALIVE; /* CommandType (4 bytes) */
@ -717,6 +724,10 @@ int rts_recv_CONN_A3_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
rts_connection_timeout_command_read(rpc, &buffer[24], length - 24, &ConnectionTimeout);
DEBUG_RTS("ConnectionTimeout:%d", ConnectionTimeout);
rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
return 0;
}
@ -744,16 +755,14 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
INChannelCookie = (BYTE*) &(rpc->VirtualConnection->DefaultInChannelCookie);
AssociationGroupId = (BYTE*) &(rpc->VirtualConnection->AssociationGroupId);
/* TODO: fix hardcoded values */
buffer = (BYTE*) malloc(header.frag_length);
CopyMemory(buffer, ((BYTE*) &header), 20); /* RTS Header (20 bytes) */
rts_version_command_write(&buffer[20]); /* Version (8 bytes) */
rts_cookie_command_write(&buffer[28], VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */
rts_cookie_command_write(&buffer[48], INChannelCookie); /* INChannelCookie (20 bytes) */
rts_channel_lifetime_command_write(&buffer[68], 0x40000000); /* ChannelLifetime (8 bytes) */
rts_client_keepalive_command_write(&buffer[76], 0x000493E0); /* ClientKeepalive (8 bytes) */
rts_channel_lifetime_command_write(&buffer[68], rpc->ChannelLifetime); /* ChannelLifetime (8 bytes) */
rts_client_keepalive_command_write(&buffer[76], rpc->KeepAliveInterval); /* ClientKeepalive (8 bytes) */
rts_association_group_id_command_write(&buffer[84], AssociationGroupId); /* AssociationGroupId (20 bytes) */
rpc_in_write(rpc, buffer, header.frag_length);
@ -767,6 +776,26 @@ int rts_send_CONN_B1_pdu(rdpRpc* rpc)
int rts_recv_CONN_C2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
UINT32 offset;
UINT32 ReceiveWindowSize;
UINT32 ConnectionTimeout;
offset = 24;
offset += rts_version_command_read(rpc, &buffer[offset], length - offset) + 4;
offset += rts_receive_window_size_command_read(rpc, &buffer[offset], length - offset, &ReceiveWindowSize) + 4;
offset += rts_connection_timeout_command_read(rpc, &buffer[offset], length - offset, &ConnectionTimeout) + 4;
DEBUG_RTS("ConnectionTimeout:%d", ConnectionTimeout);
DEBUG_RTS("ReceiveWindowSize:%d", ReceiveWindowSize);
/* TODO: verify if this is the correct protocol variable */
rpc->VirtualConnection->DefaultInChannel->PingOriginator.ConnectionTimeout = ConnectionTimeout;
rpc->VirtualConnection->DefaultInChannel->PeerReceiveWindow = ReceiveWindowSize;
rpc->VirtualConnection->DefaultInChannel->State = CLIENT_IN_CHANNEL_STATE_OPENED;
rpc->VirtualConnection->DefaultOutChannel->State = CLIENT_OUT_CHANNEL_STATE_OPENED;
return 0;
}
@ -1196,7 +1225,7 @@ int rts_recv_pdu_commands(rdpRpc* rpc, rpcconn_rts_hdr_t* rts)
switch (CommandType)
{
case RTS_CMD_RECEIVE_WINDOW_SIZE:
offset += rts_receive_window_size_command_read(rpc, &buffer[offset], length);
offset += rts_receive_window_size_command_read(rpc, &buffer[offset], length, NULL);
break;
case RTS_CMD_FLOW_CONTROL_ACK:

View File

@ -165,7 +165,7 @@ int rts_recv_pdu_commands(rdpRpc* rpc, rpcconn_rts_hdr_t* rts);
BOOL rts_connect(rdpRpc* rpc);
int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length);
int rts_receive_window_size_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length, UINT32* ReceiveWindowSize);
int rts_receive_window_size_command_write(BYTE* buffer, UINT32 ReceiveWindowSize);
int rts_flow_control_ack_command_read(rdpRpc* rpc, BYTE* buffer, UINT32 length);

View File

@ -287,28 +287,28 @@ BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg)
offset += 4; /* 0x00000001 (4 bytes) */
}
if (packetCapsResponse->pktQuarEncResponse.certChainLen)
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020014 */
offset += 4;
if (packetCapsResponse->pktQuarEncResponse.certChainLen)
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020014 */
offset += 4;
offset += 4; /* MaxCount (4 bytes) */
offset += 4; /* Offset (4 bytes) */
count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */
offset += 4;
offset += 4; /* MaxCount (4 bytes) */
offset += 4; /* Offset (4 bytes) */
count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */
offset += 4;
/*
* CertChainData is a wide character string, and the count is
* given in characters excluding the null terminator, therefore:
* size = ((count + 1) * 2)
*/
offset += ((count + 1) * 2); /* CertChainData */
}
else
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes) */
offset += 4;
}
/*
* CertChainData is a wide character string, and the count is
* given in characters excluding the null terminator, therefore:
* size = ((count + 1) * 2)
*/
offset += ((count + 1) * 2); /* CertChainData */
}
else
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes) */
offset += 4;
}
versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS));
ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS));
@ -321,7 +321,7 @@ BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg)
if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT)
{
printf("Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n",
versionCaps->tsgHeader.ComponentId);
versionCaps->tsgHeader.ComponentId);
return FALSE;
}
@ -388,28 +388,28 @@ BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg)
CopyMemory(&packetQuarEncResponse->nonce, &buffer[52], 16); /* Nonce */
offset = 68;
if (packetQuarEncResponse->certChainLen > 0)
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x0002000C */
offset += 4;
if (packetQuarEncResponse->certChainLen > 0)
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x0002000C */
offset += 4;
offset += 4; /* MaxCount (4 bytes) */
offset += 4; /* Offset (4 bytes) */
count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */
offset += 4;
offset += 4; /* MaxCount (4 bytes) */
offset += 4; /* Offset (4 bytes) */
count = *((UINT32*) &buffer[offset]); /* ActualCount (4 bytes) */
offset += 4;
/*
* CertChainData is a wide character string, and the count is
* given in characters excluding the null terminator, therefore:
* size = ((count + 1) * 2)
*/
offset += ((count + 1) * 2); /* CertChainData */
}
else
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020008 */
offset += 4;
}
/*
* CertChainData is a wide character string, and the count is
* given in characters excluding the null terminator, therefore:
* size = ((count + 1) * 2)
*/
offset += ((count + 1) * 2); /* CertChainData */
}
else
{
Pointer = *((UINT32*) &buffer[offset]); /* Ptr (4 bytes): 0x00020008 */
offset += 4;
}
versionCaps = (PTSG_PACKET_VERSIONCAPS) malloc(sizeof(TSG_PACKET_VERSIONCAPS));
ZeroMemory(versionCaps, sizeof(TSG_PACKET_VERSIONCAPS));
@ -421,8 +421,8 @@ BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg)
if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT)
{
printf("Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n",
versionCaps->tsgHeader.ComponentId);
printf("Unexpected ComponentId: 0x%04X, Expected TS_GATEWAY_TRANSPORT\n",
versionCaps->tsgHeader.ComponentId);
return FALSE;
}
@ -1118,7 +1118,7 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
rpcconn_common_hdr_t* header;
rdpRpc* rpc = tsg->rpc;
printf("tsg_read: %d, pending: %d\n", length, tsg->PendingPdu);
DEBUG_TSG("tsg_read: %d, pending: %d", length, tsg->PendingPdu);
if (tsg->PendingPdu)
{
@ -1146,12 +1146,14 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
return -1;
}
#ifdef WITH_DEBUG_TSG
printf("RPC Stub (offset: %d length: %d):\n", tsg->StubOffset, tsg->StubLength);
freerdp_hexdump(&rpc->buffer[tsg->StubOffset], tsg->StubLength);
#endif
if (header->alloc_hint == 4)
{
printf("Ignoring TsProxySetupReceivePipe Response\n");
DEBUG_TSG("Ignoring TsProxySetupReceivePipe Response");
return tsg_read(tsg, data, length);
}