Limit the time passed in transport check loop

This patch make it possible to limit the time that is passed when we call
XXX_check_fds functions. This should smooth the treatment between handling inputs
and handling incoming bitmap updates.
The default maximum time is set to 100 ms.
This commit is contained in:
David Fort 2016-05-03 17:24:07 +02:00
parent 9adc13297b
commit 71fd5cc148
6 changed files with 91 additions and 35 deletions

View File

@ -29,32 +29,33 @@
#include <winpr/sspi.h>
typedef BOOL (*psPeerContextNew)(freerdp_peer* client, rdpContext* context);
typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context);
typedef BOOL (*psPeerContextNew)(freerdp_peer* peer, rdpContext* context);
typedef void (*psPeerContextFree)(freerdp_peer* peer, rdpContext* context);
typedef BOOL (*psPeerInitialize)(freerdp_peer* client);
typedef BOOL (*psPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount);
typedef HANDLE (*psPeerGetEventHandle)(freerdp_peer* client);
typedef HANDLE (*psPeerGetReceiveEventHandle)(freerdp_peer* client);
typedef BOOL (*psPeerCheckFileDescriptor)(freerdp_peer* client);
typedef BOOL (*psPeerIsWriteBlocked)(freerdp_peer* client);
typedef int (*psPeerDrainOutputBuffer)(freerdp_peer* client);
typedef BOOL (*psPeerClose)(freerdp_peer* client);
typedef void (*psPeerDisconnect)(freerdp_peer* client);
typedef BOOL (*psPeerCapabilities)(freerdp_peer* client);
typedef BOOL (*psPeerPostConnect)(freerdp_peer* client);
typedef BOOL (*psPeerActivate)(freerdp_peer* client);
typedef BOOL (*psPeerLogon)(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic);
typedef BOOL (*psPeerInitialize)(freerdp_peer* peer);
typedef BOOL (*psPeerGetFileDescriptor)(freerdp_peer* peer, void** rfds, int* rcount);
typedef HANDLE (*psPeerGetEventHandle)(freerdp_peer* peer);
typedef HANDLE (*psPeerGetReceiveEventHandle)(freerdp_peer* peer);
typedef BOOL (*psPeerCheckFileDescriptor)(freerdp_peer* peer);
typedef BOOL (*psPeerIsWriteBlocked)(freerdp_peer* peer);
typedef int (*psPeerDrainOutputBuffer)(freerdp_peer* peer);
typedef BOOL (*psPeerHasMoreToRead)(freerdp_peer* peer);
typedef BOOL (*psPeerClose)(freerdp_peer* peer);
typedef void (*psPeerDisconnect)(freerdp_peer* peer);
typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
typedef BOOL (*psPeerLogon)(freerdp_peer* peer, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic);
typedef int (*psPeerSendChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size);
typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, UINT16 channelId, BYTE* data, int size, int flags, int totalSize);
typedef int (*psPeerSendChannelData)(freerdp_peer* peer, UINT16 channelId, BYTE* data, int size);
typedef int (*psPeerReceiveChannelData)(freerdp_peer* peer, UINT16 channelId, BYTE* data, int size, int flags, int totalSize);
typedef HANDLE (*psPeerVirtualChannelOpen)(freerdp_peer* client, const char* name, UINT32 flags);
typedef BOOL (*psPeerVirtualChannelClose)(freerdp_peer* client, HANDLE hChannel);
typedef int (*psPeerVirtualChannelRead)(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length);
typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* client, HANDLE hChannel, BYTE* buffer, UINT32 length);
typedef void* (*psPeerVirtualChannelGetData)(freerdp_peer* client, HANDLE hChannel);
typedef int (*psPeerVirtualChannelSetData)(freerdp_peer* client, HANDLE hChannel, void* data);
typedef HANDLE (*psPeerVirtualChannelOpen)(freerdp_peer* peer, const char* name, UINT32 flags);
typedef BOOL (*psPeerVirtualChannelClose)(freerdp_peer* peer, HANDLE hChannel);
typedef int (*psPeerVirtualChannelRead)(freerdp_peer* peer, HANDLE hChannel, BYTE* buffer, UINT32 length);
typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* peer, HANDLE hChannel, BYTE* buffer, UINT32 length);
typedef void* (*psPeerVirtualChannelGetData)(freerdp_peer* peer, HANDLE hChannel);
typedef int (*psPeerVirtualChannelSetData)(freerdp_peer* peer, HANDLE hChannel, void* data);
struct rdp_freerdp_peer
{
@ -106,6 +107,7 @@ struct rdp_freerdp_peer
psPeerIsWriteBlocked IsWriteBlocked;
psPeerDrainOutputBuffer DrainOutputBuffer;
psPeerHasMoreToRead HasMoreToRead;
};
#ifdef __cplusplus

View File

@ -829,7 +829,8 @@ struct rdp_settings
ALIGN64 char* Domain; /* 23 */
ALIGN64 char* PasswordHash; /* 24 */
ALIGN64 BOOL WaitForOutputBufferFlush; /* 25 */
UINT64 padding0064[64 - 26]; /* 26 */
ALIGN64 UINT32 MaxTimeInCheckLoop; /* 26 */
UINT64 padding0064[64 - 27]; /* 27 */
UINT64 padding0128[128 - 64]; /* 64 */
/**

View File

@ -674,6 +674,10 @@ static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
return transport_drain_output_buffer(transport);
}
static BOOL freerdp_peer_has_more_to_read(freerdp_peer* peer) {
return peer->context->rdp->transport->haveMoreBytesToRead;
}
BOOL freerdp_peer_context_new(freerdp_peer* client)
{
rdpRdp* rdp;
@ -731,6 +735,7 @@ BOOL freerdp_peer_context_new(freerdp_peer* client)
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
client->HasMoreToRead = freerdp_peer_has_more_to_read;
IFCALLRET(client->ContextNew, ret, client, client->context);
@ -803,6 +808,7 @@ freerdp_peer* freerdp_peer_new(int sockfd)
client->SendChannelData = freerdp_peer_send_channel_data;
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
client->HasMoreToRead = freerdp_peer_has_more_to_read;
client->VirtualChannelOpen = freerdp_peer_virtual_channel_open;
client->VirtualChannelClose = freerdp_peer_virtual_channel_close;
client->VirtualChannelWrite = freerdp_peer_virtual_channel_write;

View File

@ -277,6 +277,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->ServerMode = (flags & FREERDP_SETTINGS_SERVER_MODE) ? TRUE : FALSE;
settings->WaitForOutputBufferFlush = TRUE;
settings->MaxTimeInCheckLoop = 100;
settings->DesktopWidth = 1024;
settings->DesktopHeight = 768;
settings->Workarea = FALSE;

View File

@ -756,38 +756,58 @@ out_cleanup:
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events,
DWORD count)
{
DWORD nCount = 0;
DWORD nCount = 1; /* always the reread Event */
DWORD tmp;
if (events)
{
if (count < 1)
{
WLog_ERR(TAG, "%s: provided handles array is too small", __FUNCTION__);
return 0;
}
events[0] = transport->rereadEvent;
}
if (!transport->GatewayEnabled)
{
if (events && (nCount < count))
nCount++;
if (events)
{
if (BIO_get_event(transport->frontBio, &events[nCount]) != 1)
if (nCount > count)
{
WLog_ERR(TAG, "%s: provided handles array is too small (count=%d nCount=%d)",
__FUNCTION__, count, nCount);
return 0;
}
nCount++;
if (BIO_get_event(transport->frontBio, &events[1]) != 1)
{
WLog_ERR(TAG, "%s: error getting the frontBio handle", __FUNCTION__);
return 0;
}
}
}
else
{
if (transport->rdg)
{
tmp = rdg_get_event_handles(transport->rdg, events, nCount - count);
tmp = rdg_get_event_handles(transport->rdg, &events[1], count - 1);
if (tmp == 0)
return 0;
nCount = tmp;
nCount += tmp;
}
else if (transport->tsg)
{
tmp = tsg_get_event_handles(transport->tsg, events, nCount - count);
tmp = tsg_get_event_handles(transport->tsg, &events[1], count - 1);
if (tmp == 0)
return 0;
nCount = tmp;
nCount += tmp;
}
}
@ -800,12 +820,14 @@ void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
DWORD nCount;
HANDLE events[64];
nCount = transport_get_event_handles(transport, events, 64);
*rcount = nCount;
*rcount = nCount + 1;
for (index = 0; index < nCount; index++)
{
rfds[index] = GetEventWaitObject(events[index]);
}
rfds[nCount + 1] = GetEventWaitObject(transport->rereadEvent);
}
BOOL transport_is_write_blocked(rdpTransport* transport)
@ -833,11 +855,19 @@ int transport_check_fds(rdpTransport* transport)
int status;
int recv_status;
wStream* received;
DWORD now = GetTickCount();
DWORD dueDate = now + transport->settings->MaxTimeInCheckLoop;
if (!transport)
return -1;
while (!freerdp_shall_disconnect(transport->context->instance))
if (transport->haveMoreBytesToRead)
{
transport->haveMoreBytesToRead = FALSE;
ResetEvent(transport->rereadEvent);
}
while(!freerdp_shall_disconnect(transport->context->instance) && (now < dueDate))
{
/**
* Note: transport_read_pdu tries to read one PDU from
@ -883,8 +913,15 @@ int transport_check_fds(rdpTransport* transport)
recv_status);
return -1;
}
now = GetTickCount();
}
if (now > dueDate)
{
SetEvent(transport->rereadEvent);
transport->haveMoreBytesToRead = TRUE;
}
return 0;
}
@ -1073,12 +1110,17 @@ rdpTransport* transport_new(rdpContext* context)
|| transport->connectedEvent == INVALID_HANDLE_VALUE)
goto out_free_receivebuffer;
transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
goto out_free_connectedEvent;
transport->haveMoreBytesToRead = FALSE;
transport->blocking = TRUE;
transport->GatewayEnabled = FALSE;
transport->layer = TRANSPORT_LAYER_TCP;
if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
goto out_free_connectedEvent;
goto out_free_rereadEvent;
if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
goto out_free_readlock;
@ -1086,6 +1128,8 @@ rdpTransport* transport_new(rdpContext* context)
return transport;
out_free_readlock:
DeleteCriticalSection(&(transport->ReadLock));
out_free_rereadEvent:
CloseHandle(transport->rereadEvent);
out_free_connectedEvent:
CloseHandle(transport->connectedEvent);
out_free_receivebuffer:

View File

@ -79,6 +79,8 @@ struct rdp_transport
CRITICAL_SECTION ReadLock;
CRITICAL_SECTION WriteLock;
ULONG written;
HANDLE rereadEvent;
BOOL haveMoreBytesToRead;
};
FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport,