libfreerdp-core: implement simple RPC PDU send queue according to the MS-TSGU ADM

This commit is contained in:
Marc-André Moreau 2012-11-17 04:47:13 -05:00
parent 25d2533eaa
commit bea9a521ca
4 changed files with 73 additions and 22 deletions

View File

@ -118,7 +118,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-registry winpr-utils winpr-dsparse winpr-sspi winpr-crt)
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-crt)
if(MONOLITHIC_BUILD)
set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)

View File

@ -698,6 +698,42 @@ BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* buffer, UINT32* offset, UINT32* l
return TRUE;
}
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
RPC_PDU_ENTRY* PduEntry;
PduEntry = (RPC_PDU_ENTRY*) _aligned_malloc(sizeof(RPC_PDU_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);
PduEntry->Buffer = buffer;
PduEntry->Length = length;
InterlockedPushEntrySList(rpc->SendQueue, &(PduEntry->ItemEntry));
return 0;
}
int rpc_send_dequeue_pdu(rdpRpc* rpc)
{
int status;
RPC_PDU_ENTRY* PduEntry;
PduEntry = (RPC_PDU_ENTRY*) InterlockedPopEntrySList(rpc->SendQueue);
status = rpc_in_write(rpc, PduEntry->Buffer, PduEntry->Length);
/*
* This protocol specifies that only RPC PDUs are subject to the flow control abstract
* data model. RTS PDUs and the HTTP request and response headers are not subject to flow control.
* Implementations of this protocol MUST NOT include them when computing any of the variables
* specified by this abstract data model.
*/
rpc->VirtualConnection->DefaultInChannel->BytesSent += status;
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status;
_aligned_free(PduEntry);
return status;
}
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length)
{
int status;
@ -722,19 +758,6 @@ int rpc_in_write(rdpRpc* rpc, BYTE* data, int length)
status = tls_write_all(rpc->TlsIn, data, length);
if (status > 0)
{
/*
* This protocol specifies that only RPC PDUs are subject to the flow control abstract
* data model. RTS PDUs and the HTTP request and response headers are not subject to flow control.
* Implementations of this protocol MUST NOT include them when computing any of the variables
* specified by this abstract data model.
*/
rpc->VirtualConnection->DefaultInChannel->BytesSent += status;
rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status;
}
return status;
}
@ -951,16 +974,14 @@ int rpc_tsg_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
CopyMemory(&buffer[offset], Buffers[1].pvBuffer, Buffers[1].cbBuffer);
offset += Buffers[1].cbBuffer;
status = rpc_in_write(rpc, buffer, request_pdu->frag_length);
if (status < 0)
{
printf("rpc_tsg_write(): Error! rpc_tsg_write returned negative value.\n");
return -1;
}
rpc_send_enqueue_pdu(rpc, buffer, request_pdu->frag_length);
status = rpc_send_dequeue_pdu(rpc);
free(buffer);
if (status < 0)
return -1;
return length;
}
@ -1160,6 +1181,9 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->max_xmit_frag = 0x0FF8;
rpc->max_recv_frag = 0x0FF8;
rpc->SendQueue = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
InitializeSListHead(rpc->SendQueue);
rpc->ReceiveWindow = 0x00010000;
rpc->ChannelLifetime = 0x40000000;
@ -1182,8 +1206,16 @@ void rpc_free(rdpRpc* rpc)
{
if (rpc != NULL)
{
RPC_PDU_ENTRY* PduEntry;
ntlm_http_free(rpc->NtlmHttpIn);
ntlm_http_free(rpc->NtlmHttpOut);
while ((PduEntry = (RPC_PDU_ENTRY*) InterlockedPopEntrySList(rpc->SendQueue)) != NULL)
_aligned_free(PduEntry);
_aligned_free(rpc->SendQueue);
rpc_client_virtual_connection_free(rpc->VirtualConnection);
rpc_virtual_connection_cookie_table_free(rpc->VirtualConnectionCookieTable);
free(rpc);

View File

@ -53,7 +53,10 @@ typedef struct
#include "transport.h"
#include <time.h>
#include <winpr/sspi.h>
#include <winpr/interlocked.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
#include <freerdp/crypto/tls.h>
@ -651,6 +654,13 @@ struct rpc_virtual_connection_cookie_table
};
typedef struct rpc_virtual_connection_cookie_table RpcVirtualConnectionCookieTable;
typedef struct _RPC_PDU_ENTRY
{
SLIST_ENTRY ItemEntry;
BYTE* Buffer;
UINT32 Length;
} RPC_PDU_ENTRY, *PRPC_PDU_ENTRY;
struct rdp_rpc
{
rdpTls* TlsIn;
@ -678,6 +688,8 @@ struct rdp_rpc
UINT16 max_xmit_frag;
UINT16 max_recv_frag;
PSLIST_HEADER SendQueue;
UINT32 ReceiveWindow;
UINT32 ChannelLifetime;

View File

@ -376,10 +376,17 @@ void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
{
#ifdef _WIN32
rfds[*rcount] = transport->tcp->wsa_event;
(*rcount)++;
#else
rfds[*rcount] = (void*)(long)(transport->TcpIn->sockfd);
#endif
(*rcount)++;
if (transport->SplitInputOutput)
{
rfds[*rcount] = (void*)(long)(transport->TcpOut->sockfd);
(*rcount)++;
}
#endif
wait_obj_get_fds(transport->recv_event, rfds, rcount);
}