libfreerdp-core: move socket event and nonblock options to socket BIO
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 28 Jan 2015 02:18:26 +0000 (21:18 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 28 Jan 2015 02:18:26 +0000 (21:18 -0500)
libfreerdp/core/gateway/rpc_client.c
libfreerdp/core/tcp.c
libfreerdp/core/tcp.h
libfreerdp/core/transport.c

index d88cff8..173cb12 100644 (file)
@@ -470,32 +470,23 @@ RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
 
 static void* rpc_client_thread(void* arg)
 {
-       int fd;
        DWORD status;
        DWORD nCount;
        HANDLE events[3];
        HANDLE ReadEvent;
        rdpRpc* rpc = (rdpRpc*) arg;
 
-       fd = BIO_get_fd(rpc->TlsOut->bio, NULL);
-       ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, fd);
+       if (!BIO_get_event(rpc->TlsOut->bio, &ReadEvent))
+       {
+               WLog_ERR(TAG, "rpc_client_thread: failed to obtain read event from underlying BIO");
+               goto out;
+       }
 
        nCount = 0;
        events[nCount++] = rpc->client->StopEvent;
        events[nCount++] = Queue_Event(rpc->client->SendQueue);
        events[nCount++] = ReadEvent;
 
-       /* Do a first free run in case some bytes were set from the HTTP headers.
-        * We also have to do it because most of the time the underlying socket has notified,
-        * and the ssl layer has eaten all bytes, so we won't be notified any more even if the
-        * bytes are buffered locally
-        */
-       if (rpc_client_on_read_event(rpc) < 0)
-       {
-               WLog_ERR(TAG, "an error occurred when treating first packet");
-               goto out;
-       }
-
        while (rpc->transport->layer != TRANSPORT_LAYER_CLOSED)
        {
                status = WaitForMultipleObjects(nCount, events, FALSE, 100);
@@ -522,7 +513,6 @@ static void* rpc_client_thread(void* arg)
        }
 
 out:
-       CloseHandle(ReadEvent);
        return NULL;
 }
 
index 83d04ed..7563d37 100644 (file)
@@ -174,6 +174,56 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
 {
        int status = -1;
 
+       if (cmd == BIO_C_GET_EVENT)
+       {
+               if (!bio->init || !arg2)
+                       return 0;
+
+#ifndef _WIN32
+               if (!bio->ptr)
+                       bio->ptr = CreateFileDescriptorEvent(NULL, FALSE, FALSE, bio->num);
+#else
+               if (!bio->ptr)
+                       bio->ptr = (void*) WSACreateEvent();
+
+               WSAEventSelect(bio->num, (HANDLE) bio->ptr, FD_READ);
+#endif
+
+               *((ULONG_PTR*) arg2) = (ULONG_PTR) bio->ptr;
+
+               return 1;
+       }
+       else if (cmd == BIO_C_SET_NONBLOCK)
+       {
+#ifndef _WIN32
+               int flags;
+
+               flags = fcntl(bio->num, F_GETFL);
+
+               if (flags == -1)
+                       return 0;
+
+               if (arg1)
+                       fcntl(bio->num, F_SETFL, flags | O_NONBLOCK);
+               else
+                       fcntl(bio->num, F_SETFL, flags & ~(O_NONBLOCK));
+#else
+               if (arg1)
+               {
+                       if (!bio->ptr)
+                               bio->ptr = (void*) WSACreateEvent();
+
+                       WSAEventSelect(bio->num, (HANDLE) bio->ptr, FD_READ);
+               }
+               else
+               {
+                       if (bio->ptr)
+                               WSAEventSelect(bio->num, (HANDLE) bio->ptr, 0);
+               }
+#endif
+               return 1;
+       }
+
        switch (cmd)
        {
                case BIO_C_SET_FD:
@@ -228,6 +278,7 @@ static int transport_bio_simple_new(BIO* bio)
        bio->num = 0;
        bio->ptr = NULL;
        bio->flags = BIO_FLAGS_SHOULD_RETRY;
+
        return 1;
 }
 
@@ -239,7 +290,15 @@ static int transport_bio_simple_free(BIO* bio)
        if (bio->shutdown)
        {
                if (bio->init)
+               {
+                       if (bio->ptr)
+                       {
+                               CloseHandle((HANDLE) bio->ptr);
+                               bio->ptr = NULL;
+                       }
+
                        closesocket((SOCKET) bio->num);
+               }
 
                bio->init = 0;
                bio->flags = 0;
@@ -931,7 +990,7 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
                BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
        }
 
-       SetEventFileDescriptor(tcp->event, tcp->sockfd);
+       BIO_get_event(tcp->socketBio, &tcp->event);
 
        freerdp_tcp_get_ip_address(tcp);
        freerdp_tcp_get_mac_address(tcp);
@@ -994,49 +1053,7 @@ BOOL freerdp_tcp_disconnect(rdpTcp* tcp)
 
 BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking)
 {
-#ifndef _WIN32
-       int flags;
-       flags = fcntl(tcp->sockfd, F_GETFL);
-
-       if (flags == -1)
-       {
-               WLog_ERR(TAG,  "fcntl failed, %s.", strerror(errno));
-               return FALSE;
-       }
-
-       if (blocking == TRUE)
-               fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK));
-       else
-               fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
-#else
-       /**
-        * ioctlsocket function:
-        * msdn.microsoft.com/en-ca/library/windows/desktop/ms738573/
-        * 
-        * The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode.
-        * If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use
-        * ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.
-        * 
-        * To set the socket back to blocking mode, an application must first disable WSAAsyncSelect
-        * by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect
-        * by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.
-        */
-
-       if (blocking == TRUE)
-       {
-               if (tcp->event)
-                       WSAEventSelect(tcp->sockfd, tcp->event, 0);
-       }
-       else
-       {
-               if (!tcp->event)
-                       tcp->event = WSACreateEvent();
-
-               WSAEventSelect(tcp->sockfd, tcp->event, FD_READ);
-       }
-#endif
-
-       return TRUE;
+       return BIO_set_nonblock(tcp->socketBio, blocking ? 0 : 1) ? TRUE : FALSE;
 }
 
 BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
@@ -1102,7 +1119,6 @@ BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
 int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
 {
        tcp->sockfd = sockfd;
-       SetEventFileDescriptor(tcp->event, tcp->sockfd);
 
        ringbuffer_commit_read_bytes(&tcp->xmitBuffer, ringbuffer_used(&tcp->xmitBuffer));
 
@@ -1133,7 +1149,9 @@ int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
                tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
        }
 
-       return 0;
+       BIO_get_event(tcp->socketBio, &tcp->event);
+
+       return 1;
 }
 
 HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp)
@@ -1235,19 +1253,8 @@ rdpTcp* freerdp_tcp_new(rdpSettings* settings)
        tcp->sockfd = -1;
        tcp->settings = settings;
 
-       if (0)
-               goto out_ringbuffer; /* avoid unreferenced label warning on Windows */
-
-#ifndef _WIN32
-       tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd);
-
-       if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE)
-               goto out_ringbuffer;
-#endif
-
        return tcp;
-out_ringbuffer:
-       ringbuffer_destroy(&tcp->xmitBuffer);
+
 out_free:
        free(tcp);
        return NULL;
@@ -1259,6 +1266,18 @@ void freerdp_tcp_free(rdpTcp* tcp)
                return;
 
        ringbuffer_destroy(&tcp->xmitBuffer);
-       CloseHandle(tcp->event);
+
+       if (tcp->socketBio)
+       {
+               BIO_free(tcp->socketBio);
+               tcp->socketBio = NULL;
+       }
+
+       if (tcp->bufferedBio)
+       {
+               BIO_free(tcp->bufferedBio);
+               tcp->bufferedBio = NULL;
+       }
+
        free(tcp);
 }
index d2dd634..b34f82b 100644 (file)
 #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)
+
 typedef struct rdp_tcp rdpTcp;
 
 struct rdp_tcp
index c5e411b..fac237a 100644 (file)
@@ -391,8 +391,10 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
        freerdp* instance;
        rdpContext* context;
        rdpSettings* settings = transport->settings;
+
        instance = (freerdp*) transport->settings->instance;
        context = instance->context;
+
        tsg = tsg_new(transport);
 
        if (!tsg)
@@ -424,6 +426,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
 
        transport->TlsIn->hostname = transport->TlsOut->hostname = settings->GatewayHostname;
        transport->TlsIn->port = transport->TlsOut->port = settings->GatewayPort;
+
        transport->TlsIn->isGatewayTransport = TRUE;
        tls_status = tls_connect(transport->TlsIn, transport->TcpIn->bufferedBio);
 
@@ -467,6 +470,7 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
 
        transport->frontBio = BIO_new(BIO_s_tsg());
        transport->frontBio->ptr = tsg;
+
        return TRUE;
 }