From a9df86ab1656e3f05f44f507058d7b6b330fdccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 28 Jan 2015 14:54:03 -0500 Subject: [PATCH] libfreerdp-core: update gateway code for Windows --- .gitignore | 1 + libfreerdp/core/gateway/rpc_client.c | 41 +++++----- libfreerdp/core/gateway/tsg.c | 106 ++++++++++++++++++++++++++ libfreerdp/core/gateway/tsg.h | 2 + libfreerdp/core/listener.c | 2 +- libfreerdp/core/tcp.c | 87 +++++++++++++++------ libfreerdp/core/tcp.h | 18 +++-- libfreerdp/core/transport.c | 108 --------------------------- 8 files changed, 209 insertions(+), 156 deletions(-) diff --git a/.gitignore b/.gitignore index 5b5c8a22c..5aa9ce86b 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ RelWithDebInfo *.resource.txt *.embed.manifest* *.intermediate.manifest* +version.rc # Binaries *.a diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index 173cb125d..98024994a 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -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; } diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index 1e9a082c0..4cf1cf526 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -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; +} diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h index 421beb80d..708c35b28 100644 --- a/libfreerdp/core/gateway/tsg.h +++ b/libfreerdp/core/gateway/tsg.h @@ -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 */ diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index af2f8f07e..5907ed6c4 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -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"); diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index bba57c3f0..9a613a5ae 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -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; } diff --git a/libfreerdp/core/tcp.h b/libfreerdp/core/tcp.h index b34f82b73..1dceeb7a8 100644 --- a/libfreerdp/core/tcp.h +++ b/libfreerdp/core/tcp.h @@ -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; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index cfad8dcf2..1024f4422 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -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;