libfreerdp-core: implement simple RPC PDU send queue according to the MS-TSGU ADM
This commit is contained in:
parent
25d2533eaa
commit
bea9a521ca
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user