libfreerdp-core: update gateway code for Windows

This commit is contained in:
Marc-André Moreau 2015-01-28 14:54:03 -05:00
parent 5bf8b1509e
commit a9df86ab16
8 changed files with 209 additions and 156 deletions

1
.gitignore vendored
View File

@ -79,6 +79,7 @@ RelWithDebInfo
*.resource.txt
*.embed.manifest*
*.intermediate.manifest*
version.rc
# Binaries
*.a

View File

@ -64,7 +64,7 @@ RPC_PDU* rpc_client_receive_pool_take(rdpRpc* rpc)
if (!pdu)
{
pdu = (RPC_PDU*)malloc(sizeof(RPC_PDU));
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
if (!pdu)
return NULL;
@ -311,9 +311,10 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
{
int index;
int count;
RpcClientCall* clientCall;
RpcClientCall* clientCall = NULL;
ArrayList_Lock(rpc->client->ClientCallList);
clientCall = NULL;
count = ArrayList_Count(rpc->client->ClientCallList);
for (index = 0; index < count; index++)
@ -325,13 +326,15 @@ RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
}
ArrayList_Unlock(rpc->client->ClientCallList);
return clientCall;
}
RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
{
RpcClientCall* clientCall;
clientCall = (RpcClientCall*) malloc(sizeof(RpcClientCall));
clientCall = (RpcClientCall*) calloc(1, sizeof(RpcClientCall));
if (!clientCall)
return NULL;
@ -339,6 +342,7 @@ RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
clientCall->CallId = CallId;
clientCall->OpNum = OpNum;
clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
return clientCall;
}
@ -349,8 +353,9 @@ void rpc_client_call_free(RpcClientCall* clientCall)
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
RPC_PDU* pdu;
int status;
RPC_PDU* pdu;
pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
if (!pdu)
@ -465,22 +470,26 @@ RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
if (result != WAIT_OBJECT_0)
return NULL;
return (RPC_PDU*)Queue_Peek(rpc->client->ReceiveQueue);
return (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue);
}
static void* rpc_client_thread(void* arg)
{
DWORD status;
DWORD nCount;
DWORD timeout;
HANDLE events[3];
HANDLE ReadEvent;
HANDLE ReadEvent = NULL;
rdpRpc* rpc = (rdpRpc*) arg;
if (!BIO_get_event(rpc->TlsOut->bio, &ReadEvent))
{
WLog_ERR(TAG, "rpc_client_thread: failed to obtain read event from underlying BIO");
goto out;
}
BIO_get_event(rpc->TlsOut->bio, &ReadEvent);
#ifndef _WIN32
timeout = INFINITE;
#else
timeout = 100;
BIO_set_nonblock(rpc->TlsOut->bio, TRUE);
#endif
nCount = 0;
events[nCount++] = rpc->client->StopEvent;
@ -489,15 +498,12 @@ static void* rpc_client_thread(void* arg)
while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED)
{
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
if (status == WAIT_TIMEOUT)
continue;
status = WaitForMultipleObjects(nCount, events, FALSE, timeout);
if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
break;
if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0)
if ((WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0) || (status == WAIT_TIMEOUT))
{
if (rpc_client_on_read_event(rpc) < 0)
{
@ -512,7 +518,6 @@ static void* rpc_client_thread(void* arg)
}
}
out:
return NULL;
}

View File

@ -1617,3 +1617,109 @@ void tsg_free(rdpTsg* tsg)
free(tsg);
}
}
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
{
return 1;
}
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = tsg_write(tsg, (BYTE*) buf, num);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_WRITE);
}
return status >= 0 ? status : -1;
}
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = tsg_read(tsg, (BYTE*) buf, size);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_READ);
}
return status > 0 ? status : -1;
}
static int transport_bio_tsg_puts(BIO* bio, const char* str)
{
return 1;
}
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
{
return 1;
}
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
if (cmd == BIO_CTRL_FLUSH)
{
return 1;
}
return 0;
}
static int transport_bio_tsg_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
return 1;
}
static int transport_bio_tsg_free(BIO* bio)
{
return 1;
}
static BIO_METHOD transport_bio_tsg_methods =
{
BIO_TYPE_TSG,
"TSGateway",
transport_bio_tsg_write,
transport_bio_tsg_read,
transport_bio_tsg_puts,
transport_bio_tsg_gets,
transport_bio_tsg_ctrl,
transport_bio_tsg_new,
transport_bio_tsg_free,
NULL,
};
BIO_METHOD* BIO_s_tsg(void)
{
return &transport_bio_tsg_methods;
}

View File

@ -318,4 +318,6 @@ BOOL tsg_set_blocking_mode(rdpTsg* tsg, BOOL blocking);
rdpTsg* tsg_new(rdpTransport* transport);
void tsg_free(rdpTsg* tsg);
BIO_METHOD* BIO_s_tsg(void);
#endif /* FREERDP_CORE_TSG_H */

View File

@ -149,7 +149,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
if (status != 0)
{
#ifdef _WIN32
WLog_ERR("bind() failed with error: %u", WSAGetLastError());
WLog_ERR(TAG, "bind() failed with error: %d", (int) WSAGetLastError());
WSACleanup();
#else
WLog_ERR(TAG, "bind");

View File

@ -87,7 +87,14 @@
/* Simple Socket BIO */
static int transport_bio_simple_init(BIO* bio, int sockfd, int shutdown);
struct _WINPR_BIO_SIMPLE_SOCKET
{
SOCKET socket;
HANDLE hEvent;
};
typedef struct _WINPR_BIO_SIMPLE_SOCKET WINPR_BIO_SIMPLE_SOCKET;
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown);
static int transport_bio_simple_uninit(BIO* bio);
long transport_bio_simple_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
@ -99,13 +106,14 @@ static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (!buf)
return 0;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = _send((SOCKET) bio->num, buf, size, 0);
status = _send(ptr->socket, buf, size, 0);
if (status <= 0)
{
@ -129,13 +137,15 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (!buf)
return 0;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = _recv((SOCKET) bio->num, buf, size, 0);
status = _recv(ptr->socket, buf, size, 0);
if (status > 0)
return status;
@ -173,13 +183,29 @@ static int transport_bio_simple_gets(BIO* bio, char* str, int size)
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = -1;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (cmd == BIO_C_GET_EVENT)
if (cmd == BIO_C_SET_SOCKET)
{
transport_bio_simple_uninit(bio);
transport_bio_simple_init(bio, (SOCKET) arg2, (int) arg1);
return 1;
}
else if (cmd == BIO_C_GET_SOCKET)
{
if (!bio->init || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) bio->ptr;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->socket;
return 1;
}
else if (cmd == BIO_C_GET_EVENT)
{
if (!bio->init || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->hEvent;
return 1;
}
@ -188,20 +214,20 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
#ifndef _WIN32
int flags;
flags = fcntl(bio->num, F_GETFL);
flags = fcntl((int) ptr->socket, F_GETFL);
if (flags == -1)
return 0;
if (arg1)
fcntl(bio->num, F_SETFL, flags | O_NONBLOCK);
fcntl((int) ptr->socket, F_SETFL, flags | O_NONBLOCK);
else
fcntl(bio->num, F_SETFL, flags & ~(O_NONBLOCK));
fcntl((int) ptr->socket, F_SETFL, flags & ~(O_NONBLOCK));
#else
LONG lNetworkEvents = arg1 ? FD_READ : 0;
if (bio->ptr)
WSAEventSelect(bio->num, (HANDLE) bio->ptr, lNetworkEvents);
if (ptr->hEvent)
WSAEventSelect(ptr->socket, ptr->hEvent, lNetworkEvents);
#endif
return 1;
}
@ -212,7 +238,7 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
if (arg2)
{
transport_bio_simple_uninit(bio);
transport_bio_simple_init(bio, *((int*) arg2), (int) arg1);
transport_bio_simple_init(bio, (SOCKET) *((int*) arg2), (int) arg1);
status = 1;
}
break;
@ -221,8 +247,8 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
if (bio->init)
{
if (arg2)
*((int*) arg2) = bio->num;
status = bio->num;
*((int*) arg2) = (int) ptr->socket;
status = (int) ptr->socket;
}
break;
@ -251,17 +277,20 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
return status;
}
static int transport_bio_simple_init(BIO* bio, int sockfd, int shutdown)
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
{
bio->num = sockfd;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
ptr->socket = socket;
bio->shutdown = shutdown;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->init = 1;
#ifdef _WIN32
bio->ptr = (void*) CreateEvent(NULL, FALSE, FALSE, NULL);
ptr->hEvent = (void*) CreateEvent(NULL, FALSE, FALSE, NULL);
#else
bio->ptr = (void*) CreateFileDescriptorEvent(NULL, FALSE, FALSE, bio->num);
ptr->hEvent = (void*) CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket);
#endif
return 1;
@ -269,19 +298,21 @@ static int transport_bio_simple_init(BIO* bio, int sockfd, int shutdown)
static int transport_bio_simple_uninit(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
if (bio->shutdown)
{
if (bio->init)
{
closesocket((SOCKET) bio->num);
bio->num = 0;
closesocket(ptr->socket);
ptr->socket = 0;
}
}
if (bio->ptr)
if (ptr->hEvent)
{
CloseHandle((HANDLE) bio->ptr);
bio->ptr = NULL;
CloseHandle(ptr->hEvent);
ptr->hEvent = NULL;
}
bio->init = 0;
@ -293,10 +324,14 @@ static int transport_bio_simple_uninit(BIO* bio)
static int transport_bio_simple_new(BIO* bio)
{
bio->init = 0;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->ptr = calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
if (!bio->ptr)
return 0;
return 1;
}
@ -307,6 +342,12 @@ static int transport_bio_simple_free(BIO* bio)
transport_bio_simple_uninit(bio);
if (bio->ptr)
{
free(bio->ptr);
bio->ptr = NULL;
}
return 1;
}

View File

@ -38,13 +38,19 @@
#define MSG_NOSIGNAL 0
#endif
#define BIO_TYPE_SIMPLE 66
#define BIO_TYPE_BUFFERED 67
#define BIO_TYPE_TSG 65
#define BIO_TYPE_SIMPLE 66
#define BIO_TYPE_BUFFERED 67
#define BIO_C_GET_EVENT 1101
#define BIO_C_SET_NONBLOCK 1102
#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*) c)
#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL)
#define BIO_C_SET_SOCKET 1101
#define BIO_C_GET_SOCKET 1102
#define BIO_C_GET_EVENT 1103
#define BIO_C_SET_NONBLOCK 1104
#define BIO_set_socket(b, s, c) BIO_ctrl(b, BIO_C_SET_SOCKET, c, s);
#define BIO_get_socket(b, c) BIO_ctrl(b, BIO_C_GET_SOCKET, 0, (char*) c)
#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*) c)
#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL)
typedef struct rdp_tcp rdpTcp;

View File

@ -139,114 +139,6 @@ BOOL transport_connect_rdp(rdpTransport* transport)
return TRUE;
}
long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
{
return 1;
}
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
status = tsg_write(tsg, (BYTE*) buf, num);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_WRITE);
}
return status >= 0 ? status : -1;
}
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = tsg_read(tsg, (BYTE*) buf, size);
if (status < 0)
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
else if (status == 0)
{
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WSASetLastError(WSAEWOULDBLOCK);
}
else
{
BIO_set_flags(bio, BIO_FLAGS_READ);
}
return status > 0 ? status : -1;
}
static int transport_bio_tsg_puts(BIO* bio, const char* str)
{
return 1;
}
static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
{
return 1;
}
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
if (cmd == BIO_CTRL_FLUSH)
{
return 1;
}
return 0;
}
static int transport_bio_tsg_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
return 1;
}
static int transport_bio_tsg_free(BIO* bio)
{
return 1;
}
#define BIO_TYPE_TSG 65
static BIO_METHOD transport_bio_tsg_methods =
{
BIO_TYPE_TSG,
"TSGateway",
transport_bio_tsg_write,
transport_bio_tsg_read,
transport_bio_tsg_puts,
transport_bio_tsg_gets,
transport_bio_tsg_ctrl,
transport_bio_tsg_new,
transport_bio_tsg_free,
NULL,
};
BIO_METHOD* BIO_s_tsg(void)
{
return &transport_bio_tsg_methods;
}
BOOL transport_connect_tls(rdpTransport* transport)
{
rdpSettings* settings = transport->settings;