libfreerdp-core: Added support for server initiated shutdown to TSG
authorMartin Fleisz <mfleisz@thinstuff.at>
Wed, 22 May 2013 08:58:11 +0000 (10:58 +0200)
committerMartin Fleisz <mfleisz@thinstuff.at>
Wed, 22 May 2013 08:58:11 +0000 (10:58 +0200)
client/iOS/FreeRDP/ios_freerdp.m
libfreerdp/core/gateway/rpc_client.c
libfreerdp/core/gateway/tsg.c

index ee0cddd..a5aeafd 100644 (file)
@@ -138,11 +138,13 @@ ios_run_freerdp(freerdp * instance)
        void* wfds[32];
        fd_set rfds_set;
        fd_set wfds_set;
+    struct timeval timeout;
+    int select_status;
        
        memset(rfds, 0, sizeof(rfds));
        memset(wfds, 0, sizeof(wfds));
 
-       while (1)
+       while (!freerdp_shall_disconnect(instance))
        {
                rcount = wcount = 0;
                
@@ -179,11 +181,19 @@ ios_run_freerdp(freerdp * instance)
                        
                        FD_SET(fds, &rfds_set);
                }
-               
+        
                if (max_fds == 0)
                        break;
-               
-               if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1)
+       
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+
+        select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);
+        
+        // timeout?
+        if (select_status == 0)
+            continue;
+        else if (select_status == -1)
                {
                        /* these are not really errors */
                        if (!((errno == EAGAIN) ||
@@ -191,7 +201,7 @@ ios_run_freerdp(freerdp * instance)
                                  (errno == EINPROGRESS) ||
                                  (errno == EINTR))) /* signal occurred */
                        {
-                               NSLog(@"%s: max_sck is zero.", __func__);
+                               NSLog(@"%s: select failed!", __func__);
                                break;
                        }
                }
index 3456b60..458bfbe 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "rpc_client.h"
 
+#include "../rdp.h"
+
 wStream* rpc_client_fragment_pool_take(rdpRpc* rpc)
 {
        wStream* fragment = NULL;
@@ -156,6 +158,15 @@ int rpc_client_on_fragment_received_event(rdpRpc* rpc)
        if (StubLength == 4)
        {
                //fprintf(stderr, "Ignoring TsProxySendToServer Response\n");
+        printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id);
+        
+        /* received a disconnect request from the server? */
+        if (header->common.call_id == rpc->PipeCallId && header->common.pfc_flags & PFC_LAST_FRAG)
+        {
+            ((freerdp*)rpc->settings->instance)->context->rdp->disconnect = TRUE;
+            ((freerdp*)rpc->settings->instance)->context->rdp->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;            
+        }
+        
                rpc_client_fragment_pool_return(rpc, fragment);
                return 0;
        }
index 7d2b4a7..c6bb45d 100644 (file)
@@ -1371,8 +1371,14 @@ BOOL tsg_disconnect(rdpTsg* tsg)
 
        tsg->rpc->client->SynchronousReceive = TRUE;
 
-       if (!TsProxyCloseChannel(tsg, NULL))
-               return FALSE;
+    /* if we are already in state pending (i.e. if a server initiated disconnect was issued)
+       we have to skip TsProxyCloseChannel - see Figure 13 in section 3.2.3
+     */
+    if (tsg->state != TSG_STATE_TUNNEL_CLOSE_PENDING)
+    {
+        if (!TsProxyCloseChannel(tsg, NULL))
+            return FALSE;
+    }
 
        if (!TsProxyMakeTunnelCall(tsg, &tsg->TunnelContext, TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST, NULL, NULL))
                return FALSE;