FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
+ fprintf(stderr, "rcount: %d\n", rcount);
+
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
channels = instance->context->channels;
- freerdp_connect(instance);
+ if (!freerdp_connect(instance))
+ {
+ WLog_ERR(TAG, "connection failure");
+ return NULL;
+ }
while (1)
{
{
int count;
int index;
- int status = 1;
xfGfxSurface* surface;
UINT16* pSurfaceIds = NULL;
xfContext* xfc = (xfContext*) context->custom;
FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount);
FREERDP_API BOOL freerdp_check_fds(freerdp* instance);
-FREERDP_API DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events);
+FREERDP_API UINT32 freerdp_get_event_handles(rdpContext* context, HANDLE* events);
FREERDP_API BOOL freerdp_check_event_handles(rdpContext* context);
FREERDP_API wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id);
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
{
- rdpRdp* rdp;
-
- rdp = instance->context->rdp;
+ rdpRdp* rdp = instance->context->rdp;
transport_get_fds(rdp->transport, rfds, rcount);
-
return TRUE;
}
return TRUE;
}
-DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events)
+UINT32 freerdp_get_event_handles(rdpContext* context, HANDLE* events)
{
- DWORD nCount = 0;
+ UINT32 nCount = 0;
nCount += transport_get_event_handles(context->rdp->transport, events);
return status;
}
-int tsg_check(rdpTsg* tsg)
+int tsg_check_event_handles(rdpTsg* tsg)
{
int status;
return status;
}
+DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events)
+{
+ DWORD nCount = 0;
+ rdpRpc* rpc = tsg->rpc;
+ RpcVirtualConnection* connection = rpc->VirtualConnection;
+
+ if (events)
+ events[nCount] = rpc->client->PipeEvent;
+ nCount++;
+
+ if (connection->DefaultInChannel && connection->DefaultInChannel->tls)
+ {
+ if (events)
+ BIO_get_event(connection->DefaultInChannel->tls->bio, &events[nCount]);
+ nCount++;
+ }
+
+ if (connection->NonDefaultInChannel && connection->NonDefaultInChannel->tls)
+ {
+ if (events)
+ BIO_get_event(connection->NonDefaultInChannel->tls->bio, &events[nCount]);
+ nCount++;
+ }
+
+ if (connection->DefaultOutChannel && connection->DefaultOutChannel->tls)
+ {
+ if (events)
+ BIO_get_event(connection->DefaultOutChannel->tls->bio, &events[nCount]);
+ nCount++;
+ }
+
+ if (connection->NonDefaultOutChannel && connection->NonDefaultOutChannel->tls)
+ {
+ if (events)
+ BIO_get_event(connection->NonDefaultOutChannel->tls->bio, &events[nCount]);
+ nCount++;
+ }
+
+ return nCount;
+}
+
BOOL tsg_set_hostname(rdpTsg* tsg, const char* hostname)
{
free(tsg->Hostname);
BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
{
- HANDLE events[2];
+ DWORD nCount;
+ HANDLE events[64];
rdpRpc* rpc = tsg->rpc;
RpcInChannel* inChannel;
RpcOutChannel* outChannel;
inChannel = connection->DefaultInChannel;
outChannel = connection->DefaultOutChannel;
- BIO_get_event(inChannel->tls->bio, &events[0]);
- BIO_get_event(outChannel->tls->bio, &events[1]);
+ nCount = tsg_get_event_handles(tsg, events);
while (tsg->state != TSG_STATE_PIPE_CREATED)
{
- WaitForMultipleObjects(2, events, FALSE, 100);
+ WaitForMultipleObjects(nCount, events, FALSE, 100);
- if (tsg_check(tsg) < 0)
+ if (tsg_check_event_handles(tsg) < 0)
{
WLog_ERR(TAG, "tsg_check failure");
transport->layer = TRANSPORT_LAYER_CLOSED;
tsg->bio->ptr = (void*) tsg;
- transport->bioIn = inChannel->bio;
- transport->bioOut = outChannel->bio;
-
- transport->GatewayEvent = rpc->client->PipeEvent;
-
return TRUE;
}
{
while (WaitForSingleObject(rpc->client->PipeEvent, 0) != WAIT_OBJECT_0)
{
- if (tsg_check(tsg) < 0)
+ if (tsg_check_event_handles(tsg) < 0)
return -1;
WaitForSingleObject(rpc->client->PipeEvent, 100);
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
+ int status = 0;
+ rdpTsg* tsg = (rdpTsg*) bio->ptr;
+ RpcVirtualConnection* connection = tsg->rpc->VirtualConnection;
+ RpcInChannel* inChannel = connection->DefaultInChannel;
+ RpcOutChannel* outChannel = connection->DefaultOutChannel;
+
if (cmd == BIO_CTRL_FLUSH)
{
- return 1;
+ status = 1;
}
+ else if (cmd == BIO_C_GET_EVENT)
+ {
+ if (arg2)
+ {
+ *((ULONG_PTR*) arg2) = (ULONG_PTR) tsg->rpc->client->PipeEvent;
+ status = 1;
+ }
+ }
+ else if (cmd == BIO_C_SET_NONBLOCK)
+ {
+ status = 1;
+ }
+ else if (cmd == BIO_C_READ_BLOCKED)
+ {
+ BIO* bio = outChannel->bio;
+ status = BIO_read_blocked(bio);
+ }
+ else if (cmd == BIO_C_WRITE_BLOCKED)
+ {
+ BIO* bio = inChannel->bio;
+ status = BIO_write_blocked(bio);
+ }
+ else if (cmd == BIO_C_WAIT_READ)
+ {
+ int timeout = (int) arg1;
+ BIO* bio = outChannel->bio;
+
+ if (BIO_read_blocked(bio))
+ return BIO_wait_read(bio, timeout);
+ else if (BIO_write_blocked(bio))
+ return BIO_wait_write(bio, timeout);
+ else
+ status = 1;
+ }
+ else if (cmd == BIO_C_WAIT_WRITE)
+ {
+ int timeout = (int) arg1;
+ BIO* bio = inChannel->bio;
- return 0;
+ if (BIO_write_blocked(bio))
+ status = BIO_wait_write(bio, timeout);
+ else if (BIO_read_blocked(bio))
+ status = BIO_wait_read(bio, timeout);
+ else
+ status = 1;
+ }
+
+ return status;
}
static int transport_bio_tsg_new(BIO* bio)
int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length);
int tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
-int tsg_check(rdpTsg* tsg);
+
+int tsg_check_event_handles(rdpTsg* tsg);
+UINT32 tsg_get_event_handles(rdpTsg* tsg, HANDLE* events);
rdpTsg* tsg_new(rdpTransport* transport);
void tsg_free(rdpTsg* tsg);
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
-#else
-#define close(_fd) closesocket(_fd)
#endif
#include "listener.h"
ioctlsocket(sockfd, FIONBIO, &arg);
#endif
- status = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
+ status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen);
if (status != 0)
{
-#ifdef _WIN32
- WLog_ERR(TAG, "bind() failed with error: %d", (int) WSAGetLastError());
- WSACleanup();
-#else
- WLog_ERR(TAG, "bind");
- close(sockfd);
-#endif
+ closesocket((SOCKET) sockfd);
continue;
}
- status = listen(sockfd, 10);
+ status = _listen((SOCKET) sockfd, 10);
if (status != 0)
{
WLog_ERR(TAG, "listen");
- close(sockfd);
+ closesocket((SOCKET) sockfd);
continue;
}
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
unlink(path);
- status = bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));
+ status = _bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));
if (status != 0)
{
WLog_ERR(TAG, "bind");
- close(sockfd);
+ closesocket((SOCKET) sockfd);
return FALSE;
}
- status = listen(sockfd, 10);
+ status = _listen(sockfd, 10);
if (status != 0)
{
WLog_ERR(TAG, "listen");
- close(sockfd);
+ closesocket((SOCKET) sockfd);
return FALSE;
}
listener->sockfds[listener->num_sockfds] = sockfd;
listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd);
listener->num_sockfds++;
- WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
+ WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
return TRUE;
#else
return TRUE;
for (i = 0; i < listener->num_sockfds; i++)
{
- close(listener->sockfds[i]);
+ closesocket((SOCKET) listener->sockfds[i]);
CloseHandle(listener->events[i]);
}
{
rdpTransport* transport = client->context->rdp->transport;
- rfds[*rcount] = (void*)(long)(BIO_get_fd(transport->bioIn, NULL));
+ rfds[*rcount] = (void*)(long)(BIO_get_fd(transport->frontBio, NULL));
(*rcount)++;
return TRUE;
HANDLE hEvent = NULL;
rdpTransport* transport = client->context->rdp->transport;
- BIO_get_event(transport->bioIn, &hEvent);
+ BIO_get_event(transport->frontBio, &hEvent);
return hEvent;
}
static void freerdp_peer_disconnect(freerdp_peer* client)
{
- transport_disconnect(client->context->rdp->transport);
+ rdpTransport* transport = client->context->rdp->transport;
+ transport_disconnect(transport);
}
static int freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelId, BYTE* data, int size)
static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
{
- return tranport_is_write_blocked(peer->context->rdp->transport);
+ rdpTransport* transport = peer->context->rdp->transport;
+ return tranport_is_write_blocked(transport);
}
static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
{
rdpTransport* transport = peer->context->rdp->transport;
-
return tranport_drain_output_buffer(transport);
}
{
rdpTsg* tsg = transport->tsg;
- status = tsg_check(tsg);
+ status = tsg_check_event_handles(tsg);
if (status < 0)
return -1;
ringbuffer_destroy(&ptr->xmitBuffer);
+ free(ptr);
+
return 1;
}
bufferedBio = BIO_push(bufferedBio, socketBio);
- transport->bioIn = bufferedBio;
- transport->frontBio = transport->bioIn;
- transport->SplitInputOutput = FALSE;
+ transport->frontBio = bufferedBio;
return TRUE;
}
BOOL transport_connect_tls(rdpTransport* transport)
{
int tlsStatus;
- BIO* bio = NULL;
rdpTls* tls = NULL;
rdpContext* context = transport->context;
rdpSettings* settings = transport->settings;
{
tls = transport->tls = tls_new(settings);
transport->layer = TRANSPORT_LAYER_TSG_TLS;
- bio = transport->frontBio;
}
else
{
tls = transport->tls = tls_new(settings);
transport->layer = TRANSPORT_LAYER_TLS;
- bio = transport->bioIn;
}
transport->tls = tls;
tls->port = 3389;
tls->isGatewayTransport = FALSE;
- tlsStatus = tls_connect(tls, bio);
+ tlsStatus = tls_connect(tls, transport->frontBio);
if (tlsStatus < 1)
{
return FALSE;
transport->frontBio = transport->tsg->bio;
- transport->SplitInputOutput = TRUE;
transport->layer = TRANSPORT_LAYER_TSG;
status = TRUE;
transport->layer = TRANSPORT_LAYER_TLS;
- if (!tls_accept(transport->tls, transport->bioIn, settings->CertificateFile, settings->PrivateKeyFile))
+ if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
return FALSE;
transport->frontBio = transport->tls->bio;
transport->layer = TRANSPORT_LAYER_TLS;
- if (!tls_accept(transport->tls, transport->bioIn, settings->CertificateFile, settings->PrivateKeyFile))
+ if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
return FALSE;
transport->frontBio = transport->tls->bio;
return TRUE;
}
-static int transport_wait_for_read(rdpTransport* transport)
-{
- if (BIO_read_blocked(transport->bioIn))
- {
- return BIO_wait_read(transport->bioIn, 10);
- }
- else if (BIO_write_blocked(transport->bioIn))
- {
- return BIO_wait_write(transport->bioIn, 10);
- }
-
- USleep(1000);
- return 0;
-}
-
-static int transport_wait_for_write(rdpTransport* transport)
-{
- BIO* bio;
-
- bio = transport->SplitInputOutput ? transport->bioOut : transport->bioIn;
-
- if (BIO_write_blocked(bio))
- {
- return BIO_wait_write(bio, 10);
- }
- else if (BIO_read_blocked(bio))
- {
- return BIO_wait_read(bio, 10);
- }
-
- USleep(1000);
- return 0;
-}
-
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
{
int read = 0;
if (!transport->blocking)
return read;
- /* blocking means that we can't continue until we have read the number of
- * requested bytes */
- if (transport_wait_for_read(transport) < 0)
+ /* blocking means that we can't continue until we have read the number of requested bytes */
+ if (BIO_wait_read(transport->frontBio, 100) < 0)
{
WLog_ERR(TAG, "error when selecting for read");
return -1;
int position;
int pduLength;
BYTE* header;
+
position = 0;
pduLength = 0;
if (status != 1)
return status;
-#ifdef WITH_DEBUG_TRANSPORT
-
- /* dump when whole PDU is read */
- if (Stream_GetPosition(s) >= pduLength)
- {
- WLog_DBG(TAG, "Local < Remote");
- winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), pduLength);
- }
-
-#endif
-
if (Stream_GetPosition(s) >= pduLength)
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
{
int length;
int status = -1;
+
EnterCriticalSection(&(transport->WriteLock));
+
length = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
-#ifdef WITH_DEBUG_TRANSPORT
-
- if (length > 0)
- {
- WLog_DBG(TAG, "Local > Remote");
- winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), length);
- }
-
-#endif
if (length > 0)
{
if (!transport->blocking)
return status;
- if (transport_wait_for_write(transport) < 0)
+ if (BIO_wait_write(transport->frontBio, 100) < 0)
{
WLog_ERR(TAG, "error when selecting for write");
return -1;
if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
{
- /* blocking transport, we must ensure the write buffer is really empty */
- BIO* bio = transport->SplitInputOutput ? transport->bioOut : transport->bioIn;
-
- while (BIO_write_blocked(bio))
+ while (BIO_write_blocked(transport->frontBio))
{
- if (transport_wait_for_write(transport) < 0)
+ if (BIO_wait_write(transport->frontBio, 100) < 0)
{
WLog_ERR(TAG, "error when selecting for write");
return -1;
}
- if (BIO_flush(bio) < 1)
+ if (BIO_flush(transport->frontBio) < 1)
{
WLog_ERR(TAG, "error when flushing outputBuffer");
return -1;
return status;
}
-void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
+UINT32 transport_get_event_handles(rdpTransport* transport, HANDLE* events)
{
- void* pfd;
-
-#ifdef _WIN32
- BIO_get_event(transport->bioIn, &rfds[*rcount]);
- (*rcount)++;
-#else
- rfds[*rcount] = (void*)(long)(BIO_get_fd(transport->bioIn, NULL));
- (*rcount)++;
-#endif
-
- pfd = GetEventWaitObject(transport->ReceiveEvent);
+ UINT32 nCount = 0;
- if (pfd)
+ if (!transport->GatewayEnabled)
{
- rfds[*rcount] = pfd;
- (*rcount)++;
+ if (events)
+ BIO_get_event(transport->frontBio, &events[nCount]);
+ nCount++;
}
-
- if (transport->GatewayEvent)
+ else
{
- pfd = GetEventWaitObject(transport->GatewayEvent);
-
- if (pfd)
- {
- rfds[*rcount] = pfd;
- (*rcount)++;
- }
+ nCount += tsg_get_event_handles(transport->tsg, events);
}
+
+ return nCount;
}
-DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events)
+void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
{
- DWORD nCount = 0;
-
- if (events)
- BIO_get_event(transport->bioIn, &events[nCount]);
- nCount++;
+ UINT32 index;
+ UINT32 nCount;
+ HANDLE events[64];
- if (transport->ReceiveEvent)
- {
- if (events)
- events[nCount] = transport->ReceiveEvent;
- nCount++;
- }
+ nCount = transport_get_event_handles(transport, events);
- if (transport->GatewayEvent)
+ for (index = 0; index < nCount; index++)
{
- if (events)
- events[nCount] = transport->GatewayEvent;
- nCount++;
+ rfds[*rcount] = GetEventWaitObject(events[index]);
+ (*rcount)++;
}
-
- return nCount;
}
BOOL tranport_is_write_blocked(rdpTransport* transport)
{
- if (BIO_write_blocked(transport->bioIn))
- return TRUE;
-
- return transport->SplitInputOutput && BIO_write_blocked(transport->bioOut);
+ return BIO_write_blocked(transport->frontBio);
}
int tranport_drain_output_buffer(rdpTransport* transport)
{
BOOL status = FALSE;
- /* First try to send some accumulated bytes in the send buffer */
- if (BIO_write_blocked(transport->bioIn))
- {
- if (BIO_flush(transport->bioIn) < 1)
- return -1;
-
- status |= BIO_write_blocked(transport->bioIn);
- }
-
- if (transport->SplitInputOutput && BIO_write_blocked(transport->bioOut))
+ if (BIO_write_blocked(transport->frontBio))
{
- if (BIO_flush(transport->bioOut) < 1)
+ if (BIO_flush(transport->frontBio) < 1)
return -1;
- status |= BIO_write_blocked(transport->bioOut);
+ status |= BIO_write_blocked(transport->frontBio);
}
return status;
if (!transport)
return -1;
- ResetEvent(transport->ReceiveEvent);
-
/**
* Loop through and read all available PDUs. Since multiple
* PDUs can exist, it's important to deliver them all before
{
transport->blocking = blocking;
- if (!transport->SplitInputOutput)
- {
- if (!BIO_set_nonblock(transport->bioIn, blocking ? FALSE : TRUE))
- return FALSE;
- }
+ if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
+ return FALSE;
return TRUE;
}
tls_free(transport->tls);
transport->tls = NULL;
}
-
- if (transport->bioIn)
- {
- BIO_free(transport->bioIn);
- transport->bioIn = NULL;
- }
}
- transport->bioIn = NULL;
- transport->bioOut = NULL;
+ transport->frontBio = NULL;
transport->layer = TRANSPORT_LAYER_TCP;
transport->context = context;
transport->settings = context->settings;
- /* a small 0.1ms delay when transport is blocking. */
- transport->SleepInterval = 100;
transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
if (!transport->ReceivePool)
if (!transport->ReceiveBuffer)
goto out_free_receivepool;
- transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- if (!transport->ReceiveEvent || transport->ReceiveEvent == INVALID_HANDLE_VALUE)
- goto out_free_receivebuffer;
-
transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
- goto out_free_receiveEvent;
+ goto out_free_receivebuffer;
transport->blocking = TRUE;
transport->GatewayEnabled = FALSE;
DeleteCriticalSection(&(transport->ReadLock));
out_free_connectedEvent:
CloseHandle(transport->connectedEvent);
-out_free_receiveEvent:
- CloseHandle(transport->ReceiveEvent);
out_free_receivebuffer:
StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer);
out_free_receivepool:
Stream_Release(transport->ReceiveBuffer);
StreamPool_Free(transport->ReceivePool);
- CloseHandle(transport->ReceiveEvent);
CloseHandle(transport->connectedEvent);
DeleteCriticalSection(&(transport->ReadLock));
DeleteCriticalSection(&(transport->WriteLock));
BIO* frontBio;
rdpTsg* tsg;
rdpTls* tls;
- BIO* bioIn;
- BIO* bioOut;
rdpContext* context;
rdpCredssp* credssp;
rdpSettings* settings;
- UINT32 SleepInterval;
void* ReceiveExtra;
wStream* ReceiveBuffer;
TransportRecv ReceiveCallback;
- HANDLE ReceiveEvent;
- HANDLE GatewayEvent;
- BOOL blocking;
- BOOL SplitInputOutput;
wStreamPool* ReceivePool;
HANDLE connectedEvent;
HANDLE stopEvent;
HANDLE thread;
BOOL async;
BOOL NlaMode;
+ BOOL blocking;
BOOL GatewayEnabled;
CRITICAL_SECTION ReadLock;
CRITICAL_SECTION WriteLock;
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount);
int transport_check_fds(rdpTransport* transport);
-DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events);
+UINT32 transport_get_event_handles(rdpTransport* transport, HANDLE* events);
BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking);
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled);