Author: cgutman
Date: Sat Nov 21 14:00:37 2009
New Revision: 44250

URL: http://svn.reactos.org/svn/reactos?rev=44250&view=rev
Log:
 - Disassociate the socket context before closing so we don't get signalled 
with a freed context (major cause of crashes)
 - Signal the connection directly from TCPSocketState
 - Remove some unused code
 - Queue completion requests on a separate list so we don't have to keep 
locking and unlocking while completing
 - Add better locking to tcpip (not the lib)
 - Remove some unused variables
 - Don't hold the cancel spin lock longer than necessary
 - Check that we successfully got the device description

Modified:
    trunk/reactos/drivers/network/tcpip/datalink/lan.c
    trunk/reactos/drivers/network/tcpip/include/tcp.h
    trunk/reactos/drivers/network/tcpip/include/titypes.h
    trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c
    trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c
    trunk/reactos/drivers/network/tcpip/tcpip/main.c
    trunk/reactos/lib/drivers/ip/network/ip.c
    trunk/reactos/lib/drivers/ip/transport/tcp/event.c
    trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c
    trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c

Modified: trunk/reactos/drivers/network/tcpip/datalink/lan.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/datalink/lan.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] Sat Nov 21 
14:00:37 2009
@@ -991,6 +991,11 @@
     GetName( RegistryPath, &IF->Name );
 
     Status = FindDeviceDescForAdapter( &IF->Name, &IF->Description );
+    if (!NT_SUCCESS(Status)) {
+        TI_DbgPrint(MIN_TRACE, ("Failed to get device description.\n"));
+        IPDestroyInterface(IF);
+        return FALSE;
+    }
 
     TI_DbgPrint(DEBUG_DATALINK,("Adapter Description: %wZ\n",
                 &IF->Description));

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=44250&r1=44249&r2=44250&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 Nov 21 
14:00:37 2009
@@ -59,6 +59,11 @@
     KEVENT Event;
 } SLEEPING_THREAD, *PSLEEPING_THREAD;
 
+typedef struct _CLIENT_DATA {
+    BOOLEAN Unlocked;
+    KSPIN_LOCK Lock;
+} CLIENT_DATA, *PCLIENT_DATA;
+
 /* Retransmission timeout constants */
 
 /* Lower bound for retransmission timeout in TCP timer ticks */
@@ -84,6 +89,7 @@
 #define SRF_FIN   TCP_FIN
 
 extern LONG TCP_IPIdentification;
+extern CLIENT_DATA ClientInfo;
 
 /* accept.c */
 NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
@@ -105,6 +111,8 @@
 
 NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
                    UINT Family, UINT Type, UINT Proto );
+
+VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection);
 
 PTCP_SEGMENT TCPCreateSegment(
   PIP_PACKET IPPacket,
@@ -156,8 +164,6 @@
 
 NTSTATUS TCPTranslateError( int OskitError );
 
-VOID TCPTimeout();
-
 UINT TCPAllocatePort( UINT HintPort );
 
 VOID TCPFreePort( UINT Port );

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=44250&r1=44249&r2=44250&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 Nov 
21 14:00:37 2009
@@ -263,6 +263,8 @@
     LIST_ENTRY Entry;
     struct _CONNECTION_ENDPOINT *AssociatedEndpoint;
     TDI_REQUEST Request;
+    NTSTATUS Status;
+    ULONG Information;
 } TDI_BUCKET, *PTDI_BUCKET;
 
 /* Transport connection context structure A.K.A. Transmission Control Block
@@ -280,6 +282,7 @@
     LIST_ENTRY ListenRequest;  /* Queued listen requests */
     LIST_ENTRY ReceiveRequest; /* Queued receive requests */
     LIST_ENTRY SendRequest;    /* Queued send requests */
+    LIST_ENTRY CompletionQueue;/* Completed requests to finish */
 
     /* Signals */
     UINT    SignalState;       /* Active signals from oskit */

Modified: trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c [iso-8859-1] Sat Nov 21 
14:00:37 2009
@@ -13,6 +13,8 @@
                               PVOID Buffer,
                               UINT BufferSize)
 {
+    //KIRQL OldIrql;
+
     switch (ID->toi_id)
     {
 #if 0
@@ -20,7 +22,10 @@
          if (BufferSize < sizeof(UCHAR))
              return TDI_INVALID_PARAMETER;
 
+         KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
          AddrFile->TTL = *((PUCHAR)Buffer);
+         KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
          return TDI_SUCCESS;
 #endif
       default:

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=44250&r1=44249&r2=44250&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 Nov 
21 14:00:37 2009
@@ -72,7 +72,6 @@
 {
     PIRP Irp;
     PIO_STACK_LOCATION IrpSp;
-    PTRANSPORT_CONTEXT TranContext;
     KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
@@ -80,7 +79,6 @@
 
     Irp         = Context;
     IrpSp       = IoGetCurrentIrpStackLocation(Irp);
-    TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
 
     IoAcquireCancelSpinLock(&OldIrql);
 
@@ -116,6 +114,8 @@
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     UCHAR MinorFunction;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -168,7 +168,6 @@
         break;
     }
 
-    IoReleaseCancelSpinLock(Irp->CancelIrql);
     IRPFinish(Irp, STATUS_CANCELLED);
 
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
@@ -191,6 +190,8 @@
     PCONNECTION_ENDPOINT Connection;
     /*NTSTATUS Status = STATUS_SUCCESS;*/
 
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
     IrpSp         = IoGetCurrentIrpStackLocation(Irp);
@@ -212,8 +213,6 @@
 
     TCPAbortListenForSocket(Connection->AddressFile->Listener,
                             Connection);
-
-    IoReleaseCancelSpinLock(Irp->CancelIrql);
 
     Irp->IoStatus.Information = 0;
     IRPFinish(Irp, STATUS_CANCELLED);
@@ -255,6 +254,7 @@
   PFILE_OBJECT FileObject;
   PADDRESS_FILE AddrFile = NULL;
   NTSTATUS Status;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -271,11 +271,6 @@
   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
   if (!Connection) {
     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-    return STATUS_INVALID_PARAMETER;
-  }
-
-  if (Connection->AddressFile) {
-    TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
@@ -294,8 +289,18 @@
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+  if (Connection->AddressFile) {
+    ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
+    TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
+    return STATUS_INVALID_PARAMETER;
+  }
+
   if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
     ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
       FileObject->FsContext2));
     return STATUS_INVALID_PARAMETER;
@@ -306,17 +311,21 @@
   TranContext = FileObject->FsContext;
   if (!TranContext) {
     ObDereferenceObject(FileObject);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
   AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
   if (!AddrFile) {
+      KeReleaseSpinLock(&Connection->Lock, OldIrql);
       ObDereferenceObject(FileObject);
       TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
       return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLockAtDpcLevel(&AddrFile->Lock);
+
   Connection->AddressFile = AddrFile;
 
   /* Add connection endpoint to the address file */
@@ -324,6 +333,9 @@
 
   /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
   ObDereferenceObject(FileObject);
+
+  KeReleaseSpinLockFromDpcLevel(&AddrFile->Lock);
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
   return Status;
 }
@@ -405,6 +417,7 @@
   PCONNECTION_ENDPOINT Connection;
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -424,16 +437,25 @@
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
   if (!Connection->AddressFile) {
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
     TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
+  KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock);
+
   /* Remove this connection from the address file */
   Connection->AddressFile->Connection = NULL;
 
+  KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock);
+
   /* Remove the address file from this connection */
   Connection->AddressFile = NULL;
+
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
   return STATUS_SUCCESS;
 }
@@ -511,6 +533,7 @@
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status = STATUS_SUCCESS;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -536,14 +559,22 @@
 
   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
 
-  TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n",
-                         Connection->AddressFile ));
-  ASSERT(Connection->AddressFile);
-
   Status = DispPrepareIrpForCancel
       (TranContext->Handle.ConnectionContext,
        Irp,
        (PDRIVER_CANCEL)DispCancelListenRequest);
+
+  KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+  if (Connection->AddressFile == NULL)
+  {
+     TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
+     KeReleaseSpinLock(&Connection->Lock, OldIrql);
+     Status = STATUS_INVALID_PARAMETER;
+     goto done;
+  }
+
+  KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock);
 
   /* Listening will require us to create a listening socket and store it in
    * the address file.  It will be signalled, and attempt to complete an irp
@@ -580,6 +611,9 @@
            DispDataRequestComplete,
            Irp );
   }
+
+  KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock);
+  KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
 done:
   if (Status != STATUS_PENDING) {
@@ -657,12 +691,10 @@
           case TDI_CONNECTION_FILE:
             Endpoint =
                                
(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
-                       TCPGetSockAddress( Endpoint, 
(PTRANSPORT_ADDRESS)Address, FALSE );
-                       DbgPrint("Returning socket address %x\n", 
Address->Address[0].Address[0].in_addr);
                        RtlZeroMemory(
                                &Address->Address[0].Address[0].sin_zero,
                                
sizeof(Address->Address[0].Address[0].sin_zero));
-                       return STATUS_SUCCESS;
+                       return TCPGetSockAddress( Endpoint, 
(PTRANSPORT_ADDRESS)Address, FALSE );
 
           default:
             TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
@@ -990,8 +1022,10 @@
                 DataBuffer,
                 BufferSize,
                 &Irp->IoStatus.Information);
-        else
+        else {
             Status = STATUS_UNSUCCESSFUL;
+            ASSERT(FALSE);
+        }
     }
 
 done:
@@ -1199,11 +1233,10 @@
  */
 {
     PTI_QUERY_CONTEXT QueryContext;
-    UINT Count = 0;
 
     QueryContext = (PTI_QUERY_CONTEXT)Context;
     if (NT_SUCCESS(Status)) {
-        Count = CopyBufferToBufferChain(
+        CopyBufferToBufferChain(
             QueryContext->InputMdl,
             FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
             (PCHAR)&QueryContext->QueryInfo.Context,

Modified: trunk/reactos/drivers/network/tcpip/tcpip/main.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip/main.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/tcpip/main.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/tcpip/main.c [iso-8859-1] Sat Nov 21 
14:00:37 2009
@@ -322,7 +322,6 @@
 {
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
-  PTRANSPORT_CONTEXT Context;
 
   IRPRemember(Irp, __FILE__, __LINE__);
 
@@ -338,8 +337,7 @@
 
   /* Close an address file, connection endpoint, or control connection */
   case IRP_MJ_CLOSE:
-    Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
-       Status = TiCloseFileObject(DeviceObject, Irp);
+    Status = TiCloseFileObject(DeviceObject, Irp);
     break;
 
   default:

Modified: trunk/reactos/lib/drivers/ip/network/ip.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/ip.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] Sat Nov 21 14:00:37 
2009
@@ -73,9 +73,6 @@
 
     /* Clean possible outdated cached neighbor addresses */
     NBTimeout();
-
-    /* Call upper layer timeout routines */
-    TCPTimeout();
 }
 
 

Modified: trunk/reactos/lib/drivers/ip/transport/tcp/event.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tcp/event.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] Sat Nov 21 
14:00:37 2009
@@ -29,7 +29,8 @@
         return 0;
     }
 
-    KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
+    if (ClientInfo.Unlocked)
+        KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
 
     TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
                NewState, Connection,
@@ -38,7 +39,10 @@
 
     Connection->SignalState |= NewState;
 
-    KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
+    HandleSignalledConnection(Connection);
+
+    if (ClientInfo.Unlocked)
+        KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
 
     return 0;
 }

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=44250&r1=44249&r2=44250&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 Nov 21 
14:00:37 2009
@@ -16,38 +16,44 @@
 static BOOLEAN TCPInitialized = FALSE;
 static NPAGED_LOOKASIDE_LIST TCPSegmentList;
 PORT_SET TCPPorts;
-
-static VOID DrainSignals() {
-    PCONNECTION_ENDPOINT Connection;
-    PLIST_ENTRY CurrentEntry, NextEntry;
-    KIRQL OldIrql;
-    NTSTATUS Status = STATUS_SUCCESS;
+CLIENT_DATA ClientInfo;
+
+static VOID
+ProcessCompletions(PCONNECTION_ENDPOINT Connection)
+{
+    PLIST_ENTRY CurrentEntry;
+    PTDI_BUCKET Bucket;
     PTCP_COMPLETION_ROUTINE Complete;
-    PTDI_BUCKET Bucket;
-    PLIST_ENTRY Entry;
-    PIRP Irp;
-    PMDL Mdl;
-    ULONG SocketError;
-
-    KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
-    CurrentEntry = ConnectionEndpointListHead.Flink;
-    while (CurrentEntry != &ConnectionEndpointListHead)
+
+    while ((CurrentEntry = 
ExInterlockedRemoveHeadList(&Connection->CompletionQueue,
+                                                       &Connection->Lock)))
     {
-        NextEntry = CurrentEntry->Flink;
-        KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
-        Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
-                                        ListEntry );
-
-        KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+         Bucket = CONTAINING_RECORD(CurrentEntry, TDI_BUCKET, Entry);
+         Complete = Bucket->Request.RequestNotifyObject;
+
+         Complete(Bucket->Request.RequestContext, Bucket->Status, 
Bucket->Information);
+
+         exFreePool(Bucket);
+    }
+
+    if (!Connection->SocketContext)
+        TCPFreeConnectionEndpoint(Connection);
+}
+
+VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection)
+{
+        PTDI_BUCKET Bucket;
+        PLIST_ENTRY Entry;
+        NTSTATUS Status;
+        PIRP Irp;
+        PMDL Mdl;
+        ULONG SocketError;
 
         TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
                                Connection, Connection->SocketContext));
 
         if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) {
             TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
-
-            Connection->SignalState = 0;
 
             /* If OskitTCP initiated the disconnect, try to read the socket 
error that occurred */
             if (Connection->SocketContext)
@@ -57,140 +63,124 @@
             if (!Connection->SocketContext || !SocketError)
                 SocketError = STATUS_CANCELLED;
 
-            KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
-            while ((Entry = ExInterlockedRemoveHeadList( 
&Connection->ReceiveRequest,
-                                                         &Connection->Lock )) 
!= NULL)
+            while (!IsListEmpty(&Connection->ReceiveRequest))
             {
+               Entry = RemoveHeadList( &Connection->ReceiveRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
-
-               Complete( Bucket->Request.RequestContext, SocketError, 0 );
-
-               exFreePool(Bucket);
+
+               Bucket->Status = SocketError;
+               Bucket->Information = 0;
+
+               InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
             }
 
-            while ((Entry = ExInterlockedRemoveHeadList( 
&Connection->SendRequest,
-                                                         &Connection->Lock )) 
!= NULL)
+            while (!IsListEmpty(&Connection->SendRequest))
             {
+               Entry = RemoveHeadList( &Connection->SendRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
-
-               Complete( Bucket->Request.RequestContext, SocketError, 0 );
-
-               exFreePool(Bucket);
+
+               Bucket->Status = SocketError;
+               Bucket->Information = 0;
+
+               InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
             }
 
-            while ((Entry = ExInterlockedRemoveHeadList( 
&Connection->ListenRequest,
-                                                         &Connection->Lock )) 
!= NULL)
+            while (!IsListEmpty(&Connection->ListenRequest))
             {
+               Entry = RemoveHeadList( &Connection->ListenRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
-
-               Complete( Bucket->Request.RequestContext, SocketError, 0 );
-
-               exFreePool(Bucket);
+
+               Bucket->Status = SocketError;
+               Bucket->Information = 0;
+
+               InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
             }
 
-            while ((Entry = ExInterlockedRemoveHeadList( 
&Connection->ConnectRequest,
-                                                         &Connection->Lock )) 
!= NULL)
+            while (!IsListEmpty(&Connection->ConnectRequest))
             {
+               Entry = RemoveHeadList( &Connection->ConnectRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
-
-               Complete( Bucket->Request.RequestContext, SocketError, 0 );
-
-               exFreePool(Bucket);
+
+               Bucket->Status = SocketError;
+               Bucket->Information = 0;
+
+               InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
             }
 
-            KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+            Connection->SignalState = 0;
         }
 
         /* Things that can happen when we try the initial connection */
         if( Connection->SignalState & SEL_CONNECT ) {
-            KeReleaseSpinLock(&Connection->Lock, OldIrql);
-            while( (Entry = ExInterlockedRemoveHeadList( 
&Connection->ConnectRequest,
-                                                         &Connection->Lock )) 
!= NULL ) {
-            
-               TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
+            while (!IsListEmpty(&Connection->ConnectRequest)) {
+               Entry = RemoveHeadList( &Connection->ConnectRequest );
 
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
-               TI_DbgPrint(DEBUG_TCP,
-                           ("Completing Request %x\n", 
Bucket->Request.RequestContext));
-
-               Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
-
-               /* Frees the bucket allocated in TCPConnect */
-               exFreePool( Bucket );
+
+               Bucket->Status = STATUS_SUCCESS;
+               Bucket->Information = 0;
+
+               InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
            }
-           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
        }
 
        if( Connection->SignalState & SEL_ACCEPT ) {
            /* Handle readable on a listening socket --
             * TODO: Implement filtering
             */
-
-           KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
            TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: 
%s)\n",
                                   Connection,
                                   IsListEmpty(&Connection->ListenRequest) ?
                                   "empty" : "nonempty"));
 
-           while( (Entry = ExInterlockedRemoveHeadList( 
&Connection->ListenRequest,
-                                                        &Connection->Lock )) 
!= NULL ) {
+           while (!IsListEmpty(&Connection->ListenRequest)) {
                PIO_STACK_LOCATION IrpSp;
 
+               Entry = RemoveHeadList( &Connection->ListenRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
 
                Irp = Bucket->Request.RequestContext;
                IrpSp = IoGetCurrentIrpStackLocation( Irp );
 
                TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
-
-               KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
                Status = TCPServiceListeningSocket
                    ( Connection->AddressFile->Listener,
                      Bucket->AssociatedEndpoint,
                      (PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
 
-               KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
                TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
 
                if( Status == STATUS_PENDING ) {
-                   ExInterlockedInsertHeadList( &Connection->ListenRequest, 
&Bucket->Entry,
-                                                &Connection->Lock );
+                   InsertHeadList( &Connection->ListenRequest, &Bucket->Entry 
);
                    break;
                } else {
-                   Complete( Bucket->Request.RequestContext, Status, 0 );
-                   exFreePool( Bucket );
+                   Bucket->Status = Status;
+                   Bucket->Information = 0;
+
+                   InsertTailList(&Connection->CompletionQueue, 
&Bucket->Entry);
                }
           }
-
-          KeAcquireSpinLock(&Connection->Lock, &OldIrql);
       }
 
       /* Things that happen after we're connected */
-      if( Connection->SignalState & SEL_READ &&
-          Connection->SignalState & SEL_CONNECT ) {
+      if( Connection->SignalState & SEL_READ ) {
           TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
                                  IsListEmpty(&Connection->ReceiveRequest) ?
                                  "empty" : "nonempty"));
 
-          KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
-           while( (Entry = ExInterlockedRemoveHeadList( 
&Connection->ReceiveRequest,
-                                                        &Connection->Lock )) 
!= NULL ) {
+           while (!IsListEmpty(&Connection->ReceiveRequest)) {
                OSK_UINT RecvLen = 0, Received = 0;
                PVOID RecvBuffer = 0;
 
+               Entry = RemoveHeadList( &Connection->ReceiveRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
 
                Irp = Bucket->Request.RequestContext;
                Mdl = Irp->MdlAddress;
@@ -210,8 +200,6 @@
                      Connection->SocketContext));
                TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
 
-               KeAcquireSpinLock(&Connection->Lock, &OldIrql);
-
                Status = TCPTranslateError
                     ( OskitTCPRecv( Connection->SocketContext,
                                     RecvBuffer,
@@ -219,46 +207,35 @@
                                     &Received,
                                     0 ) );
 
-               KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
                TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
 
-               if( Status == STATUS_SUCCESS ) {
-                   TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n",
-                                          Received, Status));
-                   Complete( Bucket->Request.RequestContext,
-                             STATUS_SUCCESS, Received );
-                   exFreePool( Bucket );
-               } else if( Status == STATUS_PENDING ) {
-                   ExInterlockedInsertHeadList( &Connection->ReceiveRequest, 
&Bucket->Entry,
-                                                &Connection->Lock );
+               if( Status == STATUS_PENDING ) {
+                   InsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry 
);
                    break;
                } else {
                    TI_DbgPrint(DEBUG_TCP,
                                ("Completing Receive request: %x %x\n",
                                 Bucket->Request, Status));
-                   Complete( Bucket->Request.RequestContext, Status, 0 );
-                   exFreePool( Bucket );
+
+                   Bucket->Status = Status;
+                   Bucket->Information = (Status == STATUS_SUCCESS) ? Received 
: 0;
+
+                   InsertTailList(&Connection->CompletionQueue, 
&Bucket->Entry);
                }
            }
-
-           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
        }
-       if( Connection->SignalState & SEL_WRITE &&
-           Connection->SignalState & SEL_CONNECT ) {
+       if( Connection->SignalState & SEL_WRITE ) {
            TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
                                   IsListEmpty(&Connection->SendRequest) ?
                                   "empty" : "nonempty"));
 
-           KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
-           while( (Entry = ExInterlockedRemoveHeadList( 
&Connection->SendRequest,
-                                                        &Connection->Lock )) 
!= NULL ) {
+           while (!IsListEmpty(&Connection->SendRequest)) {
                OSK_UINT SendLen = 0, Sent = 0;
                PVOID SendBuffer = 0;
 
+               Entry = RemoveHeadList( &Connection->SendRequest );
+
                Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-               Complete = Bucket->Request.RequestNotifyObject;
 
                Irp = Bucket->Request.RequestContext;
                Mdl = Irp->MdlAddress;
@@ -276,8 +253,6 @@
                 (DEBUG_TCP,
                  ("Connection->SocketContext: %x\n",
                   Connection->SocketContext));
-
-               KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
                Status = TCPTranslateError
                    ( OskitTCPSend( Connection->SocketContext,
@@ -286,43 +261,55 @@
                                    &Sent,
                                    0 ) );
 
-               KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
                TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
 
-               if( Status == STATUS_SUCCESS ) {
-                   TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
-                                       Sent, Status));
-                   Complete( Bucket->Request.RequestContext,
-                             STATUS_SUCCESS, Sent );
-                   exFreePool( Bucket );
-               } else if( Status == STATUS_PENDING ) {
-                   ExInterlockedInsertHeadList( &Connection->SendRequest, 
&Bucket->Entry,
-                                                &Connection->Lock );
+               if( Status == STATUS_PENDING ) {
+                   InsertHeadList( &Connection->SendRequest, &Bucket->Entry );
                    break;
                } else {
                    TI_DbgPrint(DEBUG_TCP,
                                ("Completing Send request: %x %x\n",
                                Bucket->Request, Status));
-                   Complete( Bucket->Request.RequestContext, Status, 0 );
-                   exFreePool( Bucket );
+
+                   Bucket->Status = Status;
+                   Bucket->Information = (Status == STATUS_SUCCESS) ? Sent : 0;
+
+                   InsertTailList(&Connection->CompletionQueue, 
&Bucket->Entry);
                }
            }
-           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
        }
-
-       KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
-       if (!Connection->SocketContext)
-       {
-           TCPFreeConnectionEndpoint(Connection);
-       }
-
-       CurrentEntry = NextEntry;
-
-       KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
-    }
-
+}
+
+static
+VOID DrainSignals(VOID) {
+    PCONNECTION_ENDPOINT Connection;
+    PLIST_ENTRY CurrentEntry;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+    CurrentEntry = ConnectionEndpointListHead.Flink;
+    while (CurrentEntry != &ConnectionEndpointListHead)
+    {
+        Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
+                                        ListEntry );
+        CurrentEntry = CurrentEntry->Flink;
+        KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
+
+        KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+        if (Connection->SocketContext)
+        {
+            HandleSignalledConnection(Connection);
+            KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
+            ProcessCompletions(Connection);
+        }
+        else
+        {
+            KeReleaseSpinLock(&Connection->Lock, OldIrql);
+        }
+
+        KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+    }
     KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
 }
 
@@ -342,6 +329,7 @@
     InitializeListHead(&Connection->ListenRequest);
     InitializeListHead(&Connection->ReceiveRequest);
     InitializeListHead(&Connection->SendRequest);
+    InitializeListHead(&Connection->CompletionQueue);
 
     /* Save client context pointer */
     Connection->ClientContext = ClientContext;
@@ -402,13 +390,21 @@
  *     This is the low level interface for receiving TCP data
  */
 {
+    KIRQL OldIrql;
+
     TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to oskit\n",
                            IPPacket->TotalSize,
                            IPPacket->HeaderSize));
 
+    KeAcquireSpinLock(&ClientInfo.Lock, &OldIrql);
+    ClientInfo.Unlocked = TRUE;
+
     OskitTCPReceiveDatagram( IPPacket->Header,
                              IPPacket->TotalSize,
                              IPPacket->HeaderSize );
+
+    ClientInfo.Unlocked = FALSE;
+    KeReleaseSpinLock(&ClientInfo.Lock, OldIrql);
 }
 
 /* event.c */
@@ -467,7 +463,7 @@
     while ( 1 ) {
         if (Next == NextFast) {
             NextFast += 2;
-        }
+       }
         if (Next == NextSlow) {
             NextSlow += 5;
         }
@@ -480,9 +476,7 @@
         }
 
         TimerOskitTCP( Next == NextFast, Next == NextSlow );
-        if (Next == NextSlow) {
-            DrainSignals();
-        }
+        DrainSignals();
 
         Current = Next;
         if (10 <= Current) {
@@ -501,7 +495,6 @@
     PsCreateSystemThread(&TimerThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0,
                          TimerThread, NULL);
 }
-
 
 NTSTATUS TCPStartup(VOID)
 /*
@@ -522,6 +515,9 @@
         TCPMemShutdown();
         return Status;
     }
+
+    KeInitializeSpinLock(&ClientInfo.Lock);
+    ClientInfo.Unlocked = FALSE;
 
     RegisterOskitTCPEventHandlers( &EventHandlers );
     InitOskitTCP();
@@ -862,10 +858,6 @@
     return Status;
 }
 
-VOID TCPTimeout(VOID) {
-    /* Now handled by TimerThread */
-}
-
 UINT TCPAllocatePort( UINT HintPort ) {
     if( HintPort ) {
         if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort;

Modified: trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c?rev=44250&r1=44249&r2=44250&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] 
(original)
+++ trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] Sat 
Nov 21 14:00:37 2009
@@ -285,11 +285,16 @@
 
 int OskitTCPClose( void *socket ) {
     int error;
-
-    if (!socket)
-        return OSK_ESHUTDOWN;
-
-    OSKLock();
+    struct socket *so = socket;
+
+    if (!socket)
+        return OSK_ESHUTDOWN;
+
+    OSKLock();
+    /* We have to remove the socket context here otherwise we end up
+     * back in HandleSignalledConnection with a freed connection context
+     */
+    so->so_connection = NULL;
     error = soclose( socket );
     OSKUnlock();
 
@@ -435,16 +440,12 @@
                              OSK_UINT IpHeaderLen ) {
     struct mbuf *Ip;
     struct ip *iph;
-    KIRQL OldIrql;
-
-    /* This function is a special case in which we cannot use 
OSKLock/OSKUnlock 
-     * because we don't enter with the connection lock held */
-
-    OSKLockAndRaise(&OldIrql);
+
+    OSKLock();
     Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
     if( !Ip )
     {
-       OSKUnlockAndLower(OldIrql);
+       OSKUnlock();
        return; /* drop the segment */
     }
 
@@ -461,7 +462,7 @@
                 IpHeaderLen));
 
     tcp_input(Ip, IpHeaderLen);
-    OSKUnlockAndLower(OldIrql);
+    OSKUnlock();
 
     /* The buffer Ip is freed by tcp_input */
 }


Reply via email to