Author: cgutman
Date: Sat Jul  2 20:36:35 2011
New Revision: 52503

URL: http://svn.reactos.org/svn/reactos?rev=52503&view=rev
Log:
[TCPIP]
- Implement support for timing out disconnects
- Add debug prints for oskittcp errors
[MSAFD]
- Set a disconnect timeout value that actually makes sense (1 second vs 100 
nanoseconds)

Modified:
    trunk/reactos/dll/win32/msafd/misc/dllmain.c
    trunk/reactos/drivers/network/tcpip/include/tcp.h
    trunk/reactos/drivers/network/tcpip/include/titypes.h
    trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c
    trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c

Modified: trunk/reactos/dll/win32/msafd/misc/dllmain.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msafd/misc/dllmain.c?rev=52503&r1=52502&r2=52503&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msafd/misc/dllmain.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msafd/misc/dllmain.c [iso-8859-1] Sat Jul  2 
20:36:35 2011
@@ -1696,7 +1696,7 @@
             break;
     }
 
-    DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1);
+    DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
 
     /* Send IOCTL */
     Status = NtDeviceIoControlFile((HANDLE)Handle,

Modified: trunk/reactos/drivers/network/tcpip/include/tcp.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/tcp.h?rev=52503&r1=52502&r2=52503&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/tcp.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/tcp.h [iso-8859-1] Sat Jul  2 
20:36:35 2011
@@ -138,6 +138,7 @@
 NTSTATUS TCPDisconnect(
   PCONNECTION_ENDPOINT Connection,
   UINT Flags,
+  PLARGE_INTEGER Timeout,
   PTDI_CONNECTION_INFORMATION ConnInfo,
   PTDI_CONNECTION_INFORMATION ReturnInfo,
   PTCP_COMPLETION_ROUTINE Complete,

Modified: trunk/reactos/drivers/network/tcpip/include/titypes.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/titypes.h?rev=52503&r1=52502&r2=52503&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] 
(original)
+++ trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] Sat Jul  
2 20:36:35 2011
@@ -270,6 +270,10 @@
 
     /* Signals */
     UINT    SignalState;       /* Active signals from oskit */
+    
+    /* Disconnect Timer */
+    KTIMER DisconnectTimer;
+    KDPC DisconnectDpc;
 
     struct _CONNECTION_ENDPOINT *Next; /* Next connection in address file list 
*/
 } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;

Modified: trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c?rev=52503&r1=52502&r2=52503&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] Sat Jul  
2 20:36:35 2011
@@ -549,6 +549,7 @@
   Status = TCPDisconnect(
       TranContext->Handle.ConnectionContext,
       DisReq->RequestFlags,
+      DisReq->RequestSpecific,
       DisReq->RequestConnectionInformation,
       DisReq->ReturnConnectionInformation,
       DispDataRequestComplete,

Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c?rev=52503&r1=52502&r2=52503&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Sat Jul  2 
20:36:35 2011
@@ -278,6 +278,11 @@
                 TI_DbgPrint(DEBUG_TCP,
                             ("Completing shutdown request: %x %x\n",
                              Bucket->Request, Status));
+                
+                if (KeCancelTimer(&Connection->DisconnectTimer))
+                {
+                    DereferenceObject(Connection);
+                }
 
                 Bucket->Status = Status;
                 Bucket->Information = 0;
@@ -297,6 +302,49 @@
            UnlockObjectFromDpcLevel(Connection);
 }
 
+VOID NTAPI
+DisconnectTimeoutDpc(PKDPC Dpc,
+                     PVOID DeferredContext,
+                     PVOID SystemArgument1,
+                     PVOID SystemArgument2)
+{
+    PCONNECTION_ENDPOINT Connection = DeferredContext;
+    PLIST_ENTRY Entry;
+    PTDI_BUCKET Bucket;
+    
+    LockObjectAtDpcLevel(Connection);
+    
+    /* We timed out waiting for pending sends so force it to shutdown */
+    OskitTCPShutdown(Connection->SocketContext, FWRITE);
+    
+    while (!IsListEmpty(&Connection->SendRequest))
+    {
+        Entry = RemoveHeadList(&Connection->SendRequest);
+        
+        Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
+        
+        Bucket->Information = 0;
+        Bucket->Status = STATUS_FILE_CLOSED;
+        
+        CompleteBucket(Connection, Bucket);
+    }
+    
+    while (!IsListEmpty(&Connection->ShutdownRequest)) {
+        Entry = RemoveHeadList( &Connection->ShutdownRequest );
+        
+        Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+        
+        Bucket->Status = STATUS_TIMEOUT;
+        Bucket->Information = 0;
+        
+        CompleteBucket(Connection, Bucket);
+    }
+    
+    UnlockObjectFromDpcLevel(Connection);
+    
+    DereferenceObject(Connection);
+}
+
 VOID ConnectionFree(PVOID Object) {
     PCONNECTION_ENDPOINT Connection = Object;
     KIRQL OldIrql;
@@ -328,10 +376,12 @@
     InitializeListHead(&Connection->ReceiveRequest);
     InitializeListHead(&Connection->SendRequest);
     InitializeListHead(&Connection->ShutdownRequest);
+    
+    KeInitializeTimer(&Connection->DisconnectTimer);
+    KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, 
Connection);
 
     /* Save client context pointer */
     Connection->ClientContext = ClientContext;
-
 
     Connection->RefCount = 2;
     Connection->Free = ConnectionFree;
@@ -569,22 +619,61 @@
 
     switch( OskitError ) {
     case 0: Status = STATUS_SUCCESS; break;
-    case OSK_EADDRNOTAVAIL: Status = STATUS_INVALID_ADDRESS; break;
-    case OSK_EADDRINUSE: Status = STATUS_ADDRESS_ALREADY_EXISTS; break;
-    case OSK_EAFNOSUPPORT: Status = STATUS_INVALID_CONNECTION; break;
-    case OSK_ECONNREFUSED: Status = STATUS_REMOTE_NOT_LISTENING; break;
-    case OSK_ECONNRESET: Status = STATUS_REMOTE_DISCONNECT; break;
-    case OSK_ECONNABORTED: Status = STATUS_LOCAL_DISCONNECT; break;
+    case OSK_EADDRNOTAVAIL:
+        Status = STATUS_INVALID_ADDRESS;
+        DbgPrint("OskitTCP: EADDRNOTAVAIL\n");
+        break;
+    case OSK_EADDRINUSE:
+        Status = STATUS_ADDRESS_ALREADY_EXISTS;
+        DbgPrint("OskitTCP: EADDRINUSE\n");
+        break;
+    case OSK_EAFNOSUPPORT:
+        Status = STATUS_INVALID_CONNECTION;
+        DbgPrint("OskitTCP: EAFNOSUPPORT\n");
+        break;
+    case OSK_ECONNREFUSED:
+        Status = STATUS_REMOTE_NOT_LISTENING;
+        DbgPrint("OskitTCP: ECONNREFUSED\n");
+        break;
+    case OSK_ECONNRESET:
+        Status = STATUS_REMOTE_DISCONNECT;
+        DbgPrint("OskitTCP: ECONNRESET\n");
+        break;
+    case OSK_ECONNABORTED:
+        Status = STATUS_LOCAL_DISCONNECT;
+        DbgPrint("OskitTCP: ECONNABORTED\n");
+        break;
     case OSK_EWOULDBLOCK:
     case OSK_EINPROGRESS: Status = STATUS_PENDING; break;
-    case OSK_EINVAL: Status = STATUS_INVALID_PARAMETER; break;
+    case OSK_EINVAL:
+        Status = STATUS_INVALID_PARAMETER;
+        DbgPrint("OskitTCP: EINVAL\n");
+        break;
     case OSK_ENOMEM:
-    case OSK_ENOBUFS: Status = STATUS_INSUFFICIENT_RESOURCES; break;
-    case OSK_ESHUTDOWN: Status = STATUS_FILE_CLOSED; break;
-    case OSK_EMSGSIZE: Status = STATUS_BUFFER_TOO_SMALL; break;
-    case OSK_ETIMEDOUT: Status = STATUS_TIMEOUT; break;
-    case OSK_ENETUNREACH: Status = STATUS_NETWORK_UNREACHABLE; break;
-    case OSK_EFAULT: Status = STATUS_ACCESS_VIOLATION; break;
+    case OSK_ENOBUFS:
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        DbgPrint("OskitTCP: ENOMEM/ENOBUFS\n");
+        break;
+    case OSK_ESHUTDOWN:
+        Status = STATUS_FILE_CLOSED;
+        DbgPrint("OskitTCP: ESHUTDOWN\n");
+        break;
+    case OSK_EMSGSIZE:
+        Status = STATUS_BUFFER_TOO_SMALL;
+        DbgPrint("OskitTCP: EMSGSIZE\n");
+        break;
+    case OSK_ETIMEDOUT:
+        Status = STATUS_TIMEOUT;
+        DbgPrint("OskitTCP: ETIMEDOUT\n");
+        break;
+    case OSK_ENETUNREACH:
+        Status = STATUS_NETWORK_UNREACHABLE;
+        DbgPrint("OskitTCP: ENETUNREACH\n");
+        break;
+    case OSK_EFAULT:
+        Status = STATUS_ACCESS_VIOLATION;
+        DbgPrint("OskitTCP: EFAULT\n");
+        break;
     default:
        DbgPrint("OskitTCP returned unhandled error code: %d\n", OskitError);
        Status = STATUS_INVALID_CONNECTION;
@@ -714,6 +803,7 @@
 NTSTATUS TCPDisconnect
 ( PCONNECTION_ENDPOINT Connection,
   UINT Flags,
+  PLARGE_INTEGER Timeout,
   PTDI_CONNECTION_INFORMATION ConnInfo,
   PTDI_CONNECTION_INFORMATION ReturnInfo,
   PTCP_COMPLETION_ROUTINE Complete,
@@ -722,6 +812,7 @@
     PTDI_BUCKET Bucket;
     KIRQL OldIrql;
     PLIST_ENTRY Entry;
+    LARGE_INTEGER ActualTimeout;
 
     TI_DbgPrint(DEBUG_TCP,("started\n"));
 
@@ -740,6 +831,28 @@
             return Status;
         }
         
+        /* Check if the timeout was 0 */
+        if (Timeout && Timeout->QuadPart == 0)
+        {
+            OskitTCPShutdown(Connection->SocketContext, FWRITE);
+            
+            while (!IsListEmpty(&Connection->SendRequest))
+            {
+                Entry = RemoveHeadList(&Connection->SendRequest);
+                
+                Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
+                
+                Bucket->Information = 0;
+                Bucket->Status = STATUS_FILE_CLOSED;
+                
+                CompleteBucket(Connection, Bucket);
+            }
+            
+            UnlockObject(Connection, OldIrql);
+            
+            return STATUS_TIMEOUT;
+        }
+        
         /* Otherwise we wait for the send queue to be empty */
     }
 
@@ -803,6 +916,19 @@
     Bucket->Request.RequestContext = Context;
 
     InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
+    
+    /* Use the timeout specified or 1 second if none was specified */
+    if (Timeout)
+    {
+        ActualTimeout = *Timeout;
+    }
+    else
+    {
+        ActualTimeout.QuadPart = -1000000;
+    }
+    
+    ReferenceObject(Connection);
+    KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, 
&Connection->DisconnectDpc);
 
     UnlockObject(Connection, OldIrql);
 


Reply via email to