mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 08:54:38 +09:00
Merge branch 'master' of github.com:awakecoding/FreeRDP into mppc
This commit is contained in:
@@ -379,11 +379,21 @@ int rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
|
||||
int rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
|
||||
|
||||
if (rdpei->SuspendTouch)
|
||||
rdpei->SuspendTouch(rdpei);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
|
||||
|
||||
if (rdpei->ResumeTouch)
|
||||
rdpei->ResumeTouch(rdpei);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -490,7 +500,7 @@ static int rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
|
||||
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener));
|
||||
|
||||
rdpei->listener->pInterface = rdpei->iface.pInterface;
|
||||
|
||||
|
||||
InitializeCriticalSection(&rdpei->lock);
|
||||
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
@@ -675,7 +685,7 @@ int rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y)
|
||||
int i;
|
||||
int contactId = -1;
|
||||
RDPINPUT_CONTACT_DATA contact;
|
||||
RDPINPUT_CONTACT_POINT* contactPoint;
|
||||
RDPINPUT_CONTACT_POINT* contactPoint = NULL;
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
|
||||
|
||||
for (i = 0; i < rdpei->maxTouchContacts; i++)
|
||||
|
||||
@@ -59,8 +59,13 @@ void mac_set_view_size(rdpContext* context, MRDPView* view);
|
||||
|
||||
- (void) applicationWillTerminate:(NSNotification*)notification
|
||||
{
|
||||
NSLog(@"Stopping...\n");
|
||||
freerdp_client_stop(context);
|
||||
|
||||
[mrdpView releaseResources];
|
||||
_singleDelegate = nil;
|
||||
|
||||
NSLog(@"Stopped.\n");
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
|
||||
|
||||
@@ -31,6 +31,8 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} wfreerdp-client)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||
if(VENDOR MATCHES "FreeRDP")
|
||||
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Windows")
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "wf_gdi.h"
|
||||
#include "wf_event.h"
|
||||
#include "freerdp/event.h"
|
||||
|
||||
static HWND g_focus_hWnd;
|
||||
|
||||
@@ -575,6 +576,8 @@ BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSr
|
||||
void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
int ww, wh, dw, dh;
|
||||
rdpContext* context;
|
||||
MouseEventEventArgs eventArgs;
|
||||
|
||||
if (!wfc->client_width)
|
||||
wfc->client_width = wfc->width;
|
||||
@@ -591,4 +594,10 @@ void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16
|
||||
input->MouseEvent(input, flags, x + wfc->xCurrentScroll, y + wfc->yCurrentScroll);
|
||||
else
|
||||
input->MouseEvent(input, flags, x * dw / ww + wfc->xCurrentScroll, y * dh / wh + wfc->yCurrentScroll);
|
||||
|
||||
eventArgs.flags = flags;
|
||||
eventArgs.x = x;
|
||||
eventArgs.y = y;
|
||||
context = (rdpContext*) wfc;
|
||||
PubSub_OnMouseEvent(context->pubSub, context, &eventArgs);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
set(MODULE_NAME "freerdp-client")
|
||||
set(MODULE_PREFIX "FREERDP_CLIENT")
|
||||
|
||||
# Policy CMP0022: INTERFACE_LINK_LIBRARIES defines the link
|
||||
# interface. Run "cmake --help-policy CMP0022" for policy details. Use the
|
||||
# cmake_policy command to set the policy and suppress this warning.
|
||||
if(POLICY CMP0022)
|
||||
cmake_policy(SET CMP0022 NEW)
|
||||
endif()
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
client.c
|
||||
cmdline.c
|
||||
@@ -53,10 +60,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-utils)
|
||||
|
||||
if(NOT WIN32)
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES INTERFACE_LINK_LIBRARIES "")
|
||||
endif()
|
||||
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ typedef int (*pcRdpeiTouchBegin)(RdpeiClientContext* context, int externalId, in
|
||||
typedef int (*pcRdpeiTouchUpdate)(RdpeiClientContext* context, int externalId, int x, int y);
|
||||
typedef int (*pcRdpeiTouchEnd)(RdpeiClientContext* context, int externalId, int x, int y);
|
||||
|
||||
typedef int (*pcRdpeiSuspendTouch)(RdpeiClientContext* context);
|
||||
typedef int (*pcRdpeiResumeTouch)(RdpeiClientContext* context);
|
||||
|
||||
struct _rdpei_client_context
|
||||
{
|
||||
void* handle;
|
||||
@@ -82,6 +85,9 @@ struct _rdpei_client_context
|
||||
pcRdpeiTouchBegin TouchBegin;
|
||||
pcRdpeiTouchUpdate TouchUpdate;
|
||||
pcRdpeiTouchEnd TouchEnd;
|
||||
|
||||
pcRdpeiSuspendTouch SuspendTouch;
|
||||
pcRdpeiResumeTouch ResumeTouch;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIENT_RDPEI_H */
|
||||
|
||||
@@ -146,6 +146,7 @@ extern "C" {
|
||||
#define ERRINFO_ENCRYPT_FAILED 0x00001193
|
||||
#define ERRINFO_ENCRYPTION_PACKAGE_MISMATCH 0x00001194
|
||||
#define ERRINFO_DECRYPT_FAILED2 0x00001195
|
||||
#define ERRINFO_PEER_DISCONNECTED 0x00001196
|
||||
|
||||
#define ERRINFO_SUCCESS 0x00000000
|
||||
#define ERRINFO_NONE 0xFFFFFFFF
|
||||
|
||||
@@ -83,6 +83,12 @@ DEFINE_EVENT_BEGIN(ChannelDisconnected)
|
||||
void* pInterface;
|
||||
DEFINE_EVENT_END(ChannelDisconnected)
|
||||
|
||||
DEFINE_EVENT_BEGIN(MouseEvent)
|
||||
UINT16 flags;
|
||||
UINT16 x;
|
||||
UINT16 y;
|
||||
DEFINE_EVENT_END(MouseEvent)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -385,6 +385,9 @@ int connectErrorCode;
|
||||
#define ERRINFO_DECRYPT_FAILED2_STRING \
|
||||
"Unencrypted data was encountered in a protocol stream which is meant to be encrypted with Standard RDP Security mechanisms (section 5.3.6)."
|
||||
|
||||
#define ERRINFO_PEER_DISCONNECTED_STRING \
|
||||
"The peer connection was lost."
|
||||
|
||||
/* Special codes */
|
||||
#define ERRINFO_SUCCESS_STRING "Success."
|
||||
#define ERRINFO_NONE_STRING ""
|
||||
@@ -507,6 +510,7 @@ static const ERRINFO ERRINFO_CODES[] =
|
||||
ERRINFO_DEFINE(ENCRYPT_FAILED),
|
||||
ERRINFO_DEFINE(ENCRYPTION_PACKAGE_MISMATCH),
|
||||
ERRINFO_DEFINE(DECRYPT_FAILED2),
|
||||
ERRINFO_DEFINE(PEER_DISCONNECTED),
|
||||
|
||||
ERRINFO_DEFINE(NONE)
|
||||
};
|
||||
|
||||
@@ -375,6 +375,7 @@ static wEventType FreeRDP_Events[] =
|
||||
DEFINE_EVENT_ENTRY(ConnectionResult)
|
||||
DEFINE_EVENT_ENTRY(ChannelConnected)
|
||||
DEFINE_EVENT_ENTRY(ChannelDisconnected)
|
||||
DEFINE_EVENT_ENTRY(MouseEvent)
|
||||
};
|
||||
|
||||
/** Allocator function for a rdp context.
|
||||
|
||||
@@ -447,7 +447,9 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum)
|
||||
offset += Buffers[1].cbBuffer;
|
||||
free(Buffers[1].pvBuffer);
|
||||
|
||||
rpc_send_enqueue_pdu(rpc, buffer, request_pdu->frag_length);
|
||||
if (rpc_send_enqueue_pdu(rpc, buffer, request_pdu->frag_length) != 0)
|
||||
length = -1;
|
||||
|
||||
free(request_pdu);
|
||||
|
||||
return length;
|
||||
|
||||
@@ -215,7 +215,8 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
clientCall = rpc_client_call_new(bind_pdu->call_id, 0);
|
||||
ArrayList_Add(rpc->client->ClientCallList, clientCall);
|
||||
|
||||
rpc_send_enqueue_pdu(rpc, buffer, length);
|
||||
if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0)
|
||||
length = -1;
|
||||
|
||||
free(bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes);
|
||||
free(bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes);
|
||||
@@ -330,7 +331,8 @@ int rpc_send_rpc_auth_3_pdu(rdpRpc* rpc)
|
||||
clientCall = rpc_client_call_new(auth_3_pdu->call_id, 0);
|
||||
ArrayList_Add(rpc->client->ClientCallList, clientCall);
|
||||
|
||||
rpc_send_enqueue_pdu(rpc, buffer, length);
|
||||
if (rpc_send_enqueue_pdu(rpc, buffer, length) != 0)
|
||||
length = -1;
|
||||
|
||||
free(auth_3_pdu);
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/tcp.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/synch.h>
|
||||
@@ -37,6 +39,8 @@
|
||||
|
||||
#include "../rdp.h"
|
||||
|
||||
#define SYNCHRONOUS_TIMEOUT 5000
|
||||
|
||||
wStream* rpc_client_fragment_pool_take(rdpRpc* rpc)
|
||||
{
|
||||
wStream* fragment = NULL;
|
||||
@@ -364,6 +368,7 @@ void rpc_client_call_free(RpcClientCall* clientCall)
|
||||
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
int status;
|
||||
|
||||
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
|
||||
pdu->s = Stream_New(buffer, length);
|
||||
@@ -372,7 +377,13 @@ int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
|
||||
|
||||
if (rpc->client->SynchronousSend)
|
||||
{
|
||||
WaitForSingleObject(rpc->client->PduSentEvent, INFINITE);
|
||||
status = WaitForSingleObject(rpc->client->PduSentEvent, SYNCHRONOUS_TIMEOUT);
|
||||
if (status == WAIT_TIMEOUT)
|
||||
{
|
||||
fprintf(stderr, "rpc_send_enqueue_pdu: timed out waiting for pdu sent event\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ResetEvent(rpc->client->PduSentEvent);
|
||||
}
|
||||
|
||||
@@ -427,11 +438,19 @@ RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
DWORD dwMilliseconds;
|
||||
DWORD result;
|
||||
|
||||
pdu = NULL;
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0;
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT : 0;
|
||||
|
||||
if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0)
|
||||
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
fprintf(stderr, "rpc_recv_dequeue_pdu: timed out waiting for receive event\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result == WAIT_OBJECT_0)
|
||||
{
|
||||
pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->ReceiveQueue);
|
||||
|
||||
@@ -454,11 +473,18 @@ RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
|
||||
{
|
||||
RPC_PDU* pdu;
|
||||
DWORD dwMilliseconds;
|
||||
DWORD result;
|
||||
|
||||
pdu = NULL;
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0;
|
||||
dwMilliseconds = rpc->client->SynchronousReceive ? SYNCHRONOUS_TIMEOUT : 0;
|
||||
|
||||
if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0)
|
||||
result = WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds);
|
||||
if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (result == WAIT_OBJECT_0)
|
||||
{
|
||||
pdu = (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue);
|
||||
return pdu;
|
||||
@@ -484,24 +510,27 @@ static void* rpc_client_thread(void* arg)
|
||||
events[nCount++] = Queue_Event(rpc->client->SendQueue);
|
||||
events[nCount++] = ReadEvent;
|
||||
|
||||
while (1)
|
||||
while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
|
||||
|
||||
if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
if (status != WAIT_TIMEOUT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (rpc_client_on_read_event(rpc) < 0)
|
||||
if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(Queue_Event(rpc->client->SendQueue), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
rpc_send_dequeue_pdu(rpc);
|
||||
if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (rpc_client_on_read_event(rpc) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(Queue_Event(rpc->client->SendQueue), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
rpc_send_dequeue_pdu(rpc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1494,6 +1494,12 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
|
||||
|
||||
rpc = tsg->rpc;
|
||||
|
||||
if (rpc->transport->layer == TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
fprintf(stderr, "tsg_read error: connection lost\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tsg->PendingPdu)
|
||||
{
|
||||
CopyLength = (length < tsg->BytesAvailable) ? length : tsg->BytesAvailable;
|
||||
@@ -1546,6 +1552,12 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
|
||||
|
||||
int tsg_write(rdpTsg* tsg, BYTE* data, UINT32 length)
|
||||
{
|
||||
if (tsg->rpc->transport->layer == TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
fprintf(stderr, "tsg_write error: connection lost\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return TsProxySendToServer((handle_t) tsg, data, 1, &length);
|
||||
}
|
||||
|
||||
|
||||
@@ -1220,6 +1220,7 @@ rdpRdp* rdp_new(rdpContext* context)
|
||||
|
||||
rdp->extension = extension_new(context->instance);
|
||||
rdp->transport = transport_new(rdp->settings);
|
||||
rdp->transport->rdp = rdp;
|
||||
rdp->license = license_new(rdp);
|
||||
rdp->input = input_new(rdp);
|
||||
rdp->update = update_new(rdp);
|
||||
@@ -1268,6 +1269,7 @@ void rdp_reset(rdpRdp* rdp)
|
||||
settings->ClientAddress = NULL;
|
||||
|
||||
rdp->transport = transport_new(rdp->settings);
|
||||
rdp->transport->rdp = rdp;
|
||||
rdp->license = license_new(rdp);
|
||||
rdp->nego = nego_new(rdp->transport);
|
||||
rdp->mcs = mcs_new(rdp->transport);
|
||||
|
||||
@@ -223,4 +223,6 @@ void rdp_free(rdpRdp* rdp);
|
||||
|
||||
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags);
|
||||
|
||||
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo);
|
||||
|
||||
#endif /* __RDP_H */
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "tpkt.h"
|
||||
#include "fastpath.h"
|
||||
#include "transport.h"
|
||||
#include "rdp.h"
|
||||
|
||||
#define BUFFER_SIZE 16384
|
||||
|
||||
@@ -82,7 +83,7 @@ BOOL transport_disconnect(rdpTransport* transport)
|
||||
|
||||
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
|
||||
{
|
||||
tsg_disconnect(transport->tsg);
|
||||
status &= tsg_disconnect(transport->tsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -129,12 +130,12 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (status <= 0)
|
||||
if (status == 0)
|
||||
{
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
|
||||
return num;
|
||||
return status < 0 ? 0 : num;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
@@ -147,12 +148,17 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (status <= 0)
|
||||
if (status == 0)
|
||||
{
|
||||
BIO_set_retry_read(bio);
|
||||
status = -1;
|
||||
}
|
||||
else if (status == -1)
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status > 0 ? status : -1;
|
||||
return status >= 0 ? status : -1;
|
||||
}
|
||||
|
||||
static int transport_bio_tsg_puts(BIO* bio, const char* str)
|
||||
@@ -556,7 +562,11 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||
return status;
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
/* A read error indicates that the peer has dropped the connection */
|
||||
transport->layer = TRANSPORT_LAYER_CLOSED;
|
||||
return status;
|
||||
}
|
||||
|
||||
read += status;
|
||||
|
||||
@@ -853,115 +863,125 @@ int transport_check_fds(rdpTransport* transport)
|
||||
#endif
|
||||
ResetEvent(transport->ReceiveEvent);
|
||||
|
||||
status = transport_read_nonblocking(transport);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
while ((pos = Stream_GetPosition(transport->ReceiveBuffer)) > 0)
|
||||
/**
|
||||
* Loop through and read all available PDUs. Since multiple
|
||||
* PDUs can exist, it's important to deliver them all before
|
||||
* returning. Otherwise we run the risk of having a thread
|
||||
* wait for a socket to get signalled that data is available
|
||||
* (which may never happen).
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, 0);
|
||||
status = transport_read_nonblocking(transport);
|
||||
|
||||
if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */
|
||||
{
|
||||
/* Ensure the TPKT header is available. */
|
||||
if (pos <= 4)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = tpkt_read_header(transport->ReceiveBuffer);
|
||||
}
|
||||
else if (nla_verify_header(transport->ReceiveBuffer))
|
||||
{
|
||||
/* TSRequest */
|
||||
|
||||
/* Ensure the TSRequest header is available. */
|
||||
if (pos <= 4)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TSRequest header can be 2, 3 or 4 bytes long */
|
||||
length = nla_header_length(transport->ReceiveBuffer);
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = nla_read_header(transport->ReceiveBuffer);
|
||||
}
|
||||
else /* Fast Path */
|
||||
{
|
||||
/* Ensure the Fast Path header is available. */
|
||||
if (pos <= 2)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fastpath header can be two or three bytes long. */
|
||||
length = fastpath_header_length(transport->ReceiveBuffer);
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = fastpath_read_header(NULL, transport->ReceiveBuffer);
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fprintf(stderr, "transport_check_fds: protocol error, not a TPKT or Fast Path header.\n");
|
||||
winpr_HexDump(Stream_Buffer(transport->ReceiveBuffer), pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0; /* Packet is not yet completely received. */
|
||||
}
|
||||
|
||||
received = transport->ReceiveBuffer;
|
||||
transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
|
||||
|
||||
Stream_SetPosition(received, length);
|
||||
Stream_SealLength(received);
|
||||
Stream_SetPosition(received, 0);
|
||||
|
||||
/**
|
||||
* status:
|
||||
* -1: error
|
||||
* 0: success
|
||||
* 1: redirection
|
||||
*/
|
||||
|
||||
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
||||
|
||||
if (recv_status == 1)
|
||||
{
|
||||
/**
|
||||
* Last call to ReceiveCallback resulted in a session redirection,
|
||||
* which means the current rdpTransport* transport pointer has been freed.
|
||||
* Return 0 for success, the rest of this function is meant for non-redirected cases.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream_Release(received);
|
||||
|
||||
if (recv_status < 0)
|
||||
status = -1;
|
||||
|
||||
if (status < 0)
|
||||
if (status <= 0)
|
||||
return status;
|
||||
|
||||
while ((pos = Stream_GetPosition(transport->ReceiveBuffer)) > 0)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, 0);
|
||||
|
||||
if (tpkt_verify_header(transport->ReceiveBuffer)) /* TPKT */
|
||||
{
|
||||
/* Ensure the TPKT header is available. */
|
||||
if (pos <= 4)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = tpkt_read_header(transport->ReceiveBuffer);
|
||||
}
|
||||
else if (nla_verify_header(transport->ReceiveBuffer))
|
||||
{
|
||||
/* TSRequest */
|
||||
|
||||
/* Ensure the TSRequest header is available. */
|
||||
if (pos <= 4)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TSRequest header can be 2, 3 or 4 bytes long */
|
||||
length = nla_header_length(transport->ReceiveBuffer);
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = nla_read_header(transport->ReceiveBuffer);
|
||||
}
|
||||
else /* Fast Path */
|
||||
{
|
||||
/* Ensure the Fast Path header is available. */
|
||||
if (pos <= 2)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fastpath header can be two or three bytes long. */
|
||||
length = fastpath_header_length(transport->ReceiveBuffer);
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = fastpath_read_header(NULL, transport->ReceiveBuffer);
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fprintf(stderr, "transport_check_fds: protocol error, not a TPKT or Fast Path header.\n");
|
||||
winpr_HexDump(Stream_Buffer(transport->ReceiveBuffer), pos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pos < length)
|
||||
{
|
||||
Stream_SetPosition(transport->ReceiveBuffer, pos);
|
||||
return 0; /* Packet is not yet completely received. */
|
||||
}
|
||||
|
||||
received = transport->ReceiveBuffer;
|
||||
transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
|
||||
|
||||
Stream_SetPosition(received, length);
|
||||
Stream_SealLength(received);
|
||||
Stream_SetPosition(received, 0);
|
||||
|
||||
/**
|
||||
* status:
|
||||
* -1: error
|
||||
* 0: success
|
||||
* 1: redirection
|
||||
*/
|
||||
|
||||
recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
|
||||
|
||||
if (recv_status == 1)
|
||||
{
|
||||
/**
|
||||
* Last call to ReceiveCallback resulted in a session redirection,
|
||||
* which means the current rdpTransport* transport pointer has been freed.
|
||||
* Return 0 for success, the rest of this function is meant for non-redirected cases.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream_Release(received);
|
||||
|
||||
if (recv_status < 0)
|
||||
status = -1;
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1035,13 +1055,21 @@ static void* transport_client_thread(void* arg)
|
||||
|
||||
transport_get_read_handles(transport, (HANDLE*) &handles, &nCount);
|
||||
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
|
||||
if (transport->layer == TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
rdpRdp* rdp = (rdpRdp*) transport->rdp;
|
||||
rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED);
|
||||
break;
|
||||
}
|
||||
else if (status != WAIT_TIMEOUT)
|
||||
{
|
||||
if (WaitForSingleObject(transport->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (!freerdp_check_fds(instance))
|
||||
break;
|
||||
if (!freerdp_check_fds(instance))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Terminating transport thread");
|
||||
|
||||
@@ -78,6 +78,7 @@ struct rdp_transport
|
||||
CRITICAL_SECTION ReadLock;
|
||||
CRITICAL_SECTION WriteLock;
|
||||
wLog* log;
|
||||
void* rdp;
|
||||
};
|
||||
|
||||
wStream* transport_send_stream_init(rdpTransport* transport, int size);
|
||||
|
||||
@@ -464,7 +464,12 @@ int tls_write(rdpTls* tls, BYTE* data, int length)
|
||||
|
||||
status = SSL_write(tls->ssl, data, length);
|
||||
|
||||
if (status <= 0)
|
||||
if (status == 0)
|
||||
{
|
||||
return -1; /* peer disconnected */
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
error = SSL_get_error(tls->ssl, status);
|
||||
|
||||
|
||||
@@ -311,6 +311,10 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
PVOID Object;
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* from http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
|
||||
* lpNumberOfBytesRead can be NULL only when the lpOverlapped parameter is not NULL.
|
||||
@@ -464,6 +468,10 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
PVOID Object;
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!winpr_Handle_GetInfo(hFile, &Type, &Object))
|
||||
return FALSE;
|
||||
|
||||
|
||||
@@ -155,11 +155,8 @@ static void ts_add_ms(struct timespec *ts, DWORD dwMilliseconds)
|
||||
ts->tv_sec += dwMilliseconds / 1000L;
|
||||
ts->tv_nsec += (dwMilliseconds % 1000L) * 1000000L;
|
||||
|
||||
while(ts->tv_nsec >= 1000000000L)
|
||||
{
|
||||
ts->tv_sec ++;
|
||||
ts->tv_nsec -= 1000000000L;
|
||||
}
|
||||
ts->tv_sec += ts->tv_nsec / 1000000000L;
|
||||
ts->tv_nsec = ts->tv_nsec % 1000000000L;
|
||||
}
|
||||
|
||||
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
||||
|
||||
Reference in New Issue
Block a user