- Use a spin lock to protect OSKit instead of a recursive mutex
authorCameron Gutman <aicommander@gmail.com>
Sat, 14 Nov 2009 18:38:02 +0000 (18:38 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sat, 14 Nov 2009 18:38:02 +0000 (18:38 +0000)
 - Remove the now unused recursive mutex code
 - Don't clear the SS_ISCONNECTING flag when soconnect returns EINPROGRESS because it causes a crash during soreceive
 - Lock CONNECTION_ENDPOINT and ADDRESS_FILE structs better
 - Remove incorrect IoMarkIrpPending calls
 - Remove useless ASSERT_LOCKED
 - Don't destroy so_connection when we close a connection
 - Remove useless FileFindConnectionByContext
 - Remove SignalledConnectionsList and SignalledConnectionsLock and simply loop through ConnectionEndpointList for signalled connections
 - Add connections to ConnectionEndpointList in TCPAllocateConnectionEndpoint instead of FileOpenConnection so we don't miss listeners
 - Remove connections from ConnectionEndpointList in TCPFreeConnectionEndpoint instead of FileCloseConnection so we don't miss listeners
 - Use ExInterlockedRemoveHeadList to remove entries in the address file's request lists
 - Remove useless members, flags, and variables in titypes.h and tcp.h
 - Fixes bug 4955 and 4434

svn path=/trunk/; revision=44163

18 files changed:
reactos/drivers/network/tcpip/include/fileobjs.h
reactos/drivers/network/tcpip/include/tcp.h
reactos/drivers/network/tcpip/include/titypes.h
reactos/drivers/network/tcpip/recmutex/recmutex.c [deleted file]
reactos/drivers/network/tcpip/recmutex/recmutex.h [deleted file]
reactos/drivers/network/tcpip/tcpip.rbuild
reactos/drivers/network/tcpip/tcpip/dispatch.c
reactos/drivers/network/tcpip/tcpip/fileobjs.c
reactos/drivers/network/tcpip/tcpip/lock.c
reactos/drivers/network/tcpip/tcpip/mocklock.c
reactos/lib/drivers/ip/transport/datagram/datagram.c
reactos/lib/drivers/ip/transport/rawip/rawip.c
reactos/lib/drivers/ip/transport/tcp/accept.c
reactos/lib/drivers/ip/transport/tcp/event.c
reactos/lib/drivers/ip/transport/tcp/tcp.c
reactos/lib/drivers/ip/transport/udp/udp.c
reactos/lib/drivers/oskittcp/include/oskittcp.h
reactos/lib/drivers/oskittcp/oskittcp/interface.c

index bff07a6..1232770 100644 (file)
@@ -13,7 +13,6 @@ extern KSPIN_LOCK AddressFileListLock;
 extern LIST_ENTRY ConnectionEndpointListHead;
 extern KSPIN_LOCK ConnectionEndpointListLock;
 
-
 NTSTATUS FileOpenAddress(
   PTDI_REQUEST Request,
   PTA_IP_ADDRESS AddrList,
@@ -27,8 +26,6 @@ NTSTATUS FileOpenConnection(
   PTDI_REQUEST Request,
   PVOID ClientContext);
 
-PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context );
-
 NTSTATUS FileCloseConnection(
   PTDI_REQUEST Request);
 
index e80d17f..32c3ec9 100644 (file)
@@ -84,11 +84,6 @@ typedef struct _SLEEPING_THREAD {
 #define SRF_FIN   TCP_FIN
 
 extern LONG TCP_IPIdentification;
-extern LIST_ENTRY SignalledConnectionsList;
-extern KSPIN_LOCK SignalledConnectionsLock;
-extern LIST_ENTRY SleepingThreadsList;
-extern FAST_MUTEX SleepingThreadsLock;
-extern RECURSIVE_MUTEX TCPLock;
 
 /* accept.c */
 NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
@@ -105,7 +100,6 @@ NTSTATUS TCPAccept
   PVOID Context );
 
 /* tcp.c */
-ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection );
 PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext );
 VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection );
 
index eaac15a..9ac9561 100644 (file)
@@ -153,7 +153,6 @@ typedef struct _ADDRESS_FILE {
     LIST_ENTRY ListEntry;                 /* Entry on list */
     KSPIN_LOCK Lock;                      /* Spin lock to manipulate this structure */
     OBJECT_FREE_ROUTINE Free;             /* Routine to use to free resources for the object */
-    USHORT Flags;                         /* Flags for address file (see below) */
     IP_ADDRESS Address;                   /* Address of this address file */
     USHORT Family;                        /* Address family */
     USHORT Protocol;                      /* Protocol number */
@@ -213,29 +212,6 @@ typedef struct _ADDRESS_FILE {
     BOOLEAN RegisteredChainedReceiveExpeditedHandler;
 } ADDRESS_FILE, *PADDRESS_FILE;
 
-/* Address File Flag constants */
-#define AFF_VALID    0x0001 /* Address file object is valid for use */
-#define AFF_BUSY     0x0002 /* Address file object is exclusive to someone */
-#define AFF_DELETE   0x0004 /* Address file object is sheduled to be deleted */
-#define AFF_SEND     0x0008 /* A send request is pending */
-#define AFF_RECEIVE  0x0010 /* A receive request is pending */
-#define AFF_PENDING  0x001C /* A request is pending */
-
-/* Macros for manipulating address file object flags */
-
-#define AF_IS_VALID(ADF)  ((ADF)->Flags & AFF_VALID)
-#define AF_SET_VALID(ADF) ((ADF)->Flags |= AFF_VALID)
-#define AF_CLR_VALID(ADF) ((ADF)->Flags &= ~AFF_VALID)
-
-#define AF_IS_BUSY(ADF)  ((ADF)->Flags & AFF_BUSY)
-#define AF_SET_BUSY(ADF) ((ADF)->Flags |= AFF_BUSY)
-#define AF_CLR_BUSY(ADF) ((ADF)->Flags &= ~AFF_BUSY)
-
-#define AF_IS_PENDING(ADF, X)  (ADF->Flags & X)
-#define AF_SET_PENDING(ADF, X) (ADF->Flags |= X)
-#define AF_CLR_PENDING(ADF, X) (ADF->Flags &= ~X)
-
-
 /* Structure used to search through Address Files */
 typedef struct _AF_SEARCH {
     PLIST_ENTRY Next;       /* Next address file to check */
@@ -306,8 +282,6 @@ typedef struct _CONNECTION_ENDPOINT {
     LIST_ENTRY SendRequest;    /* Queued send requests */
 
     /* Signals */
-    LIST_ENTRY SignalList;     /* Entry in the list of sockets waiting for
-                               * notification service to the client */
     UINT    SignalState;       /* Active signals from oskit */
 } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
 
diff --git a/reactos/drivers/network/tcpip/recmutex/recmutex.c b/reactos/drivers/network/tcpip/recmutex/recmutex.c
deleted file mode 100644 (file)
index 3450ab8..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <ntddk.h>
-#include "recmutex.h"
-
-VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
-    RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
-    ExInitializeFastMutex( &RecMutex->Mutex );
-    KeInitializeEvent( &RecMutex->StateLockedEvent,
-        NotificationEvent, FALSE );
-}
-
-/* NOTE: When we leave, the FAST_MUTEX must have been released.  The result
-* is that we always exit in the same irql as entering */
-VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
-    NTSTATUS Status = STATUS_SUCCESS;
-    PVOID CurrentThread = KeGetCurrentThread();
-
-    ASSERT(RecMutex);
-    ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
-
-    /* Wait for the previous user to unlock the RecMutex state.  There might be
-    * multiple waiters waiting to change the state.  We need to check each
-    * time we get the event whether somebody still has the state locked */
-
-    ExAcquireFastMutex( &RecMutex->Mutex );
-
-    if( CurrentThread == RecMutex->CurrentThread ) {
-            RecMutex->LockCount++;
-            ExReleaseFastMutex( &RecMutex->Mutex );
-            return;
-    }
-
-    while( RecMutex->LockCount != 0 ) {
-         ExReleaseFastMutex( &RecMutex->Mutex );
-         Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent,
-             UserRequest,
-             KernelMode,
-             FALSE,
-             NULL );
-         ExAcquireFastMutex( &RecMutex->Mutex );
-    }
-    RecMutex->CurrentThread = CurrentThread;
-    RecMutex->LockCount++;
-    ExReleaseFastMutex( &RecMutex->Mutex );
-}
-
-VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
-    ASSERT(RecMutex);
-
-    ExAcquireFastMutex( &RecMutex->Mutex );
-
-    ASSERT(RecMutex->LockCount > 0);
-    RecMutex->LockCount--;
-
-    if( !RecMutex->LockCount ) {
-        KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT,
-            FALSE );
-    }
-
-    ExReleaseFastMutex( &RecMutex->Mutex );
-}
-
diff --git a/reactos/drivers/network/tcpip/recmutex/recmutex.h b/reactos/drivers/network/tcpip/recmutex/recmutex.h
deleted file mode 100644 (file)
index 3479268..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _ROSRTL_RECMUTEX_H
-#define _ROSRTL_RECMUTEX_H
-
-typedef struct _RECURSIVE_MUTEX {
-    /* Lock. */
-    FAST_MUTEX Mutex;
-    /* Number of times this object was locked */
-    SIZE_T LockCount;
-    /* CurrentThread */
-    PVOID CurrentThread;
-    /* Notification event which signals that another thread can take over */
-    KEVENT StateLockedEvent;
-} RECURSIVE_MUTEX, *PRECURSIVE_MUTEX;
-
-extern VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex );
-extern VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex );
-extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex );
-
-#define ASSERT_LOCKED(x)
-
-#endif/*_ROSRTL_RECMUTEX_H*/
index 2a9f91c..4dd14d3 100644 (file)
@@ -21,9 +21,6 @@
        <directory name="datalink">
                <file>lan.c</file>
        </directory>
-       <directory name="recmutex">
-               <file>recmutex.c</file>
-       </directory>
        <directory name="tcpip">
                <file>ainfo.c</file>
                <file>buffer.c</file>
index 1823309..49de2fd 100644 (file)
@@ -210,9 +210,8 @@ VOID NTAPI DispCancelListenRequest(
 
     TCPRemoveIRP(Connection, Irp);
 
-    TCPAbortListenForSocket(
-           Connection->AddressFile->Listener,
-           Connection );
+    TCPAbortListenForSocket(Connection->AddressFile->Listener,
+                            Connection);
 
     IoReleaseCancelSpinLock(Irp->CancelIrql);
 
@@ -1044,7 +1043,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
   Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
   Status     = STATUS_SUCCESS;
 
-  TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+  KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
   /* Set the event handler. if an event handler is associated with
      a specific event, it's flag (RegisteredXxxHandler) is TRUE.
@@ -1165,7 +1164,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
     Status = STATUS_INVALID_PARAMETER;
   }
 
-  TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+  KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
 
   return Status;
 }
index 85808f9..dec7a0c 100644 (file)
@@ -295,9 +295,6 @@ NTSTATUS FileOpenAddress(
   /* Initialize spin lock that protects the address file object */
   KeInitializeSpinLock(&AddrFile->Lock);
 
-  /* Set valid flag so the address can be used */
-  AF_SET_VALID(AddrFile);
-
   /* Return address file object */
   Request->Handle.AddressHandle = AddrFile;
 
@@ -328,7 +325,7 @@ NTSTATUS FileCloseAddress(
   KIRQL OldIrql;
   PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
   PDATAGRAM_SEND_REQUEST SendRequest;
-  PLIST_ENTRY CurrentEntry, NextEntry;
+  PLIST_ENTRY CurrentEntry;
 
   AddrFile = Request->Handle.AddressHandle;
 
@@ -339,8 +336,6 @@ NTSTATUS FileCloseAddress(
   RemoveEntryList(&AddrFile->ListEntry);
   TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
 
-  TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-
   /* FIXME: Kill TCP connections on this address file object */
 
   /* Return pending requests with error */
@@ -348,43 +343,27 @@ NTSTATUS FileCloseAddress(
   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
 
   /* Go through pending receive request list and cancel them all */
-  CurrentEntry = AddrFile->ReceiveQueue.Flink;
-  while (CurrentEntry != &AddrFile->ReceiveQueue) {
-    NextEntry = CurrentEntry->Flink;
+  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
     ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
-    /* Abort the request and free its resources */
-    TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
     (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
-    TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-    CurrentEntry = NextEntry;
+    /* exFreePool(ReceiveRequest); FIXME: WTF? */
   }
 
   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
 
   /* Go through pending send request list and cancel them all */
-  CurrentEntry = AddrFile->TransmitQueue.Flink;
-  while (CurrentEntry != &AddrFile->TransmitQueue) {
-    NextEntry = CurrentEntry->Flink;
-    SendRequest = CONTAINING_RECORD(CurrentEntry,
-                                   DATAGRAM_SEND_REQUEST, ListEntry);
-    /* Abort the request and free its resources */
-    TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
+    SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
     (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
     exFreePool(SendRequest);
-    TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
-    CurrentEntry = NextEntry;
   }
 
-  TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
   /* Protocol specific handling */
   switch (AddrFile->Protocol) {
   case IPPROTO_TCP:
     TCPFreePort( AddrFile->Port );
-    if( AddrFile->Listener ) {
-           TCPClose( AddrFile->Listener );
-           exFreePool( AddrFile->Listener );
-    }
+    if( AddrFile->Listener )
+       TCPClose( AddrFile->Listener );
     break;
 
   case IPPROTO_UDP:
@@ -433,48 +412,11 @@ NTSTATUS FileOpenConnection(
   /* Return connection endpoint file object */
   Request->Handle.ConnectionContext = Connection;
 
-  /* Add connection endpoint to global list */
-  ExInterlockedInsertTailList(
-    &ConnectionEndpointListHead,
-    &Connection->ListEntry,
-    &ConnectionEndpointListLock);
-
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 
   return STATUS_SUCCESS;
 }
 
-
-/*
- * FUNCTION: Find a connection by examining the context field.  This
- * is needed in some situations where a FIN reply is needed after a
- * socket is formally broken.
- * ARGUMENTS:
- *     Request = Pointer to TDI request structure for this request
- * RETURNS:
- *     Status of operation
- */
-PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context ) {
-    PLIST_ENTRY Entry;
-    KIRQL OldIrql;
-    PCONNECTION_ENDPOINT Connection = NULL;
-
-    TcpipAcquireSpinLock( &ConnectionEndpointListLock, &OldIrql );
-
-    for( Entry = ConnectionEndpointListHead.Flink;
-        Entry != &ConnectionEndpointListHead;
-        Entry = Entry->Flink ) {
-       Connection =
-           CONTAINING_RECORD( Entry, CONNECTION_ENDPOINT, ListEntry );
-       if( Connection->SocketContext == Context ) break;
-       else Connection = NULL;
-    }
-
-    TcpipReleaseSpinLock( &ConnectionEndpointListLock, OldIrql );
-
-    return Connection;
-}
-
 /*
  * FUNCTION: Closes an connection file object
  * ARGUMENTS:
@@ -486,20 +428,13 @@ NTSTATUS FileCloseConnection(
   PTDI_REQUEST Request)
 {
   PCONNECTION_ENDPOINT Connection;
-  KIRQL OldIrql;
 
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
 
   Connection = Request->Handle.ConnectionContext;
 
-  TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
-  RemoveEntryList(&Connection->ListEntry);
-  TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
-
   TCPClose( Connection );
 
-  TCPFreeConnectionEndpoint(Connection);
-
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 
   return STATUS_SUCCESS;
index 3f9d823..9a6cdc9 100644 (file)
@@ -44,16 +44,3 @@ VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
     ExReleaseFastMutex( Mutex );
 }
 
-VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
-    RecursiveMutexInit( RecMutex );
-}
-
-VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
-    //TI_DbgPrint(DEBUG_LOCK,("Locking\n"));
-    RecursiveMutexEnter( RecMutex );
-}
-
-VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
-    //TI_DbgPrint(DEBUG_LOCK,("Unlocking\n"));
-    RecursiveMutexLeave( RecMutex );
-}
index 0042ef8..0aa957c 100644 (file)
@@ -45,11 +45,3 @@ VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex ) {
 VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
 }
 
-VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
-}
-
-VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
-}
-
-VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
-}
index 7066060..fafea75 100644 (file)
@@ -79,7 +79,7 @@ VOID DGDeliverData(
 
   TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-  TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+  KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
   if (AddrFile->Protocol == IPPROTO_UDP)
     {
@@ -136,7 +136,7 @@ VOID DGDeliverData(
                             &SrcAddress->Address.IPv4Address,
                             sizeof(SrcAddress->Address.IPv4Address) );
 
-              TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+              KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
 
               /* Complete the receive request */
               if (Current->BufferSize < DataSize)
@@ -144,11 +144,11 @@ VOID DGDeliverData(
               else
                   Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
 
-              TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+              KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
          }
       }
 
-      TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+      KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
     }
   else if (AddrFile->RegisteredReceiveDatagramHandler)
     {
@@ -157,8 +157,6 @@ VOID DGDeliverData(
       ReceiveHandler = AddrFile->ReceiveDatagramHandler;
       HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
 
-      TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
       if (SrcAddress->Type == IP_ADDRESS_V4)
         {
           AddressLength = sizeof(IPv4_RAW_ADDRESS);
@@ -170,6 +168,8 @@ VOID DGDeliverData(
           SourceAddress = SrcAddress->Address.IPv6Address;
         }
 
+      KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
       Status = (*ReceiveHandler)(HandlerContext,
         AddressLength,
         SourceAddress,
@@ -184,7 +184,7 @@ VOID DGDeliverData(
     }
   else
     {
-      TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+      KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
       TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
     }
 
@@ -228,76 +228,67 @@ NTSTATUS DGReceiveDatagram(
  *     This is the high level interface for receiving DG datagrams
  */
 {
-    KIRQL OldIrql;
     NTSTATUS Status;
     PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
+    KIRQL OldIrql;
 
     TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-    TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
+    KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
-    if (AF_IS_VALID(AddrFile))
+    ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST));
+    if (ReceiveRequest)
     {
-       ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST));
-       if (ReceiveRequest)
-        {
-           /* Initialize a receive request */
+       /* Initialize a receive request */
 
-           /* Extract the remote address filter from the request (if any) */
-           if ((ConnInfo->RemoteAddressLength != 0) &&
-               (ConnInfo->RemoteAddress))
-            {
-               Status = AddrGetAddress(ConnInfo->RemoteAddress,
-                                       &ReceiveRequest->RemoteAddress,
-                                       &ReceiveRequest->RemotePort);
-               if (!NT_SUCCESS(Status))
-                {
-                   TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
-                   exFreePool(ReceiveRequest);
-                   return Status;
-                }
-            }
-           else
+       /* Extract the remote address filter from the request (if any) */
+       if ((ConnInfo->RemoteAddressLength != 0) &&
+           (ConnInfo->RemoteAddress))
+        {
+           Status = AddrGetAddress(ConnInfo->RemoteAddress,
+                                   &ReceiveRequest->RemoteAddress,
+                                   &ReceiveRequest->RemotePort);
+           if (!NT_SUCCESS(Status))
             {
-               ReceiveRequest->RemotePort = 0;
-               AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
+               exFreePool(ReceiveRequest);
+               KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+               return Status;
             }
+       }
+       else
+        {
+           ReceiveRequest->RemotePort = 0;
+           AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
+        }
 
-           IoMarkIrpPending(Irp);
+       IoMarkIrpPending(Irp);
 
-           ReceiveRequest->ReturnInfo = ReturnInfo;
-           ReceiveRequest->Buffer = BufferData;
-           ReceiveRequest->BufferSize = ReceiveLength;
-           ReceiveRequest->UserComplete = Complete;
-           ReceiveRequest->UserContext = Context;
-           ReceiveRequest->Complete =
+       ReceiveRequest->ReturnInfo = ReturnInfo;
+       ReceiveRequest->Buffer = BufferData;
+       ReceiveRequest->BufferSize = ReceiveLength;
+       ReceiveRequest->UserComplete = Complete;
+       ReceiveRequest->UserContext = Context;
+       ReceiveRequest->Complete =
                (PDATAGRAM_COMPLETION_ROUTINE)DGReceiveComplete;
-           ReceiveRequest->Context = ReceiveRequest;
-            ReceiveRequest->AddressFile = AddrFile;
-            ReceiveRequest->Irp = Irp;
+       ReceiveRequest->Context = ReceiveRequest;
+        ReceiveRequest->AddressFile = AddrFile;
+        ReceiveRequest->Irp = Irp;
 
-           /* Queue receive request */
-           InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
-           AF_SET_PENDING(AddrFile, AFF_RECEIVE);
+       /* Queue receive request */
+       InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
 
-           TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
+       TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
 
-           TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
 
-           return STATUS_PENDING;
-        }
-       else
-        {
-           Status = STATUS_INSUFFICIENT_RESOURCES;
-        }
+       return STATUS_PENDING;
     }
     else
     {
-       Status = STATUS_INVALID_ADDRESS;
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
-
     TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
 
     return Status;
index f7b9b6d..328337c 100644 (file)
@@ -195,6 +195,9 @@ NTSTATUS RawIPSendDatagram(
     USHORT RemotePort;
     NTSTATUS Status;
     PNEIGHBOR_CACHE_ENTRY NCE;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
     TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
                           AddrFile, ConnInfo, BufferData, DataSize));
@@ -209,13 +212,17 @@ NTSTATUS RawIPSendDatagram(
        break;
 
     default:
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
        return STATUS_UNSUCCESSFUL;
     }
 
     TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
 
     if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
+    {
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
        return STATUS_NETWORK_UNREACHABLE;
+    }
 
     LocalAddress = AddrFile->Address;
     if (AddrIsUnspecified(&LocalAddress))
@@ -237,18 +244,24 @@ NTSTATUS RawIPSendDatagram(
                                DataSize );
 
     if( !NT_SUCCESS(Status) )
+    {
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
        return Status;
+    }
 
     TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
 
     if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, RawIpSendPacketComplete, NULL )))
     {
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
         FreeNdisPacket(Packet.NdisPacket);
         return Status;
     }
 
     TI_DbgPrint(MID_TRACE,("Leaving\n"));
 
+    KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
     return STATUS_SUCCESS;
 }
 
index f44c0c9..b99c03b 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "precomp.h"
 
+/* Listener->Lock MUST be acquired */
 NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
                     PCONNECTION_ENDPOINT Connection,
                     PTDI_REQUEST_KERNEL Request ) {
@@ -26,18 +27,15 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
     WhoIsConnecting = (PTDI_CONNECTION_INFORMATION)
     Request->ReturnConnectionInformation;
 
-    TcpipRecursiveMutexEnter(&TCPLock);
-
     Status = TCPTranslateError
     ( OskitTCPAccept( Listener->SocketContext,
               &Connection->SocketContext,
+              Connection,
               &OutAddr,
               sizeof(OutAddr),
               &OutAddrLen,
               Request->RequestFlags & TDI_QUERY_ACCEPT ? 0 : 1 ) );
 
-    TcpipRecursiveMutexLeave(&TCPLock);
-
     TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
 
     if( NT_SUCCESS(Status) && Status != STATUS_PENDING ) {
@@ -71,11 +69,14 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
 NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
     NTSTATUS Status = STATUS_SUCCESS;
     SOCKADDR_IN AddressToBind;
+    KIRQL OldIrql;
 
     ASSERT(Connection);
     ASSERT_KM_POINTER(Connection->SocketContext);
     ASSERT_KM_POINTER(Connection->AddressFile);
 
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
     TI_DbgPrint(DEBUG_TCP,("TCPListen started\n"));
 
     TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
@@ -89,8 +90,6 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
 
     TI_DbgPrint(DEBUG_TCP,("AddressToBind - %x:%x\n", AddressToBind.sin_addr, AddressToBind.sin_port));
 
-    TcpipRecursiveMutexEnter( &TCPLock );
-
     Status = TCPTranslateError( OskitTCPBind( Connection->SocketContext,
                         &AddressToBind,
                         sizeof(AddressToBind) ) );
@@ -98,7 +97,7 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
     if (NT_SUCCESS(Status))
         Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, Backlog ) );
 
-    TcpipRecursiveMutexLeave( &TCPLock );
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("TCPListen finished %x\n", Status));
 
@@ -137,12 +136,17 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
 {
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
+    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP,("TCPAccept started\n"));
 
+    KeAcquireSpinLock(&Listener->Lock, &OldIrql);
+
     Status = TCPServiceListeningSocket( Listener, Connection,
                        (PTDI_REQUEST_KERNEL)Request );
 
+    KeReleaseSpinLock(&Listener->Lock, OldIrql);
+
     if( Status == STATUS_PENDING ) {
         Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
 
@@ -150,8 +154,8 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
             Bucket->AssociatedEndpoint = Connection;
             Bucket->Request.RequestNotifyObject = Complete;
             Bucket->Request.RequestContext = Context;
-            IoMarkIrpPending((PIRP)Context);
-            ExInterlockedInsertTailList( &Listener->ListenRequest, &Bucket->Entry, &Listener->Lock );
+            ExInterlockedInsertTailList( &Listener->ListenRequest, &Bucket->Entry,
+                                         &Listener->Lock );
         } else
             Status = STATUS_NO_MEMORY;
     }
index ba9e867..a4b2275 100644 (file)
@@ -15,56 +15,30 @@ int TCPSocketState(void *ClientData,
            void *WhichConnection,
            OSK_UINT NewState ) {
     PCONNECTION_ENDPOINT Connection = WhichConnection;
-    ULONG OldState;
-    KIRQL OldIrql;
 
-    ASSERT_LOCKED(&TCPLock);
-
-    TI_DbgPrint(MID_TRACE,("Flags: %c%c%c%c\n",
+    TI_DbgPrint(DEBUG_TCP,("Connection: %x Flags: %c%c%c%c%c\n",
+               Connection,
                NewState & SEL_CONNECT ? 'C' : 'c',
                NewState & SEL_READ    ? 'R' : 'r',
                NewState & SEL_FIN     ? 'F' : 'f',
-               NewState & SEL_ACCEPT  ? 'A' : 'a'));
-
-    TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
-               NewState, Connection,
-               Connection ? Connection->SignalState ^ NewState :
-               NewState));
+               NewState & SEL_ACCEPT  ? 'A' : 'a',
+               NewState & SEL_WRITE   ? 'W' : 'w'));
 
-    if( !Connection ) {
-    TI_DbgPrint(DEBUG_TCP,("Socket closing.\n"));
-    Connection = FileFindConnectionByContext( WhichSocket );
-    if( !Connection )
+    if (!Connection)
+    {
         return 0;
-    else
-        TI_DbgPrint(DEBUG_TCP,("Found socket %x\n", Connection));
     }
 
-    OldState = Connection->SignalState;
-
-    Connection->SignalState |= NewState;
+    KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
 
-    TcpipRecursiveMutexLeave(&TCPLock);
-
-    /* We must not be locked when handling signalled connections 
-     * because a completion could trigger another IOCTL which
-     * would cause a deadlock
-     */
-    NewState = HandleSignalledConnection(Connection);
+    TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
+               NewState, Connection,
+               Connection->SignalState ^ NewState,
+               NewState));
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    Connection->SignalState |= NewState;
 
-    KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
-    if ((NewState == 0 || NewState == SEL_FIN) &&
-        (OldState != 0 && OldState != SEL_FIN))
-    {
-        RemoveEntryList(&Connection->SignalList);
-    }
-    else if (NewState != 0 && NewState != SEL_FIN)
-    {
-        InsertTailList(&SignalledConnectionsList, &Connection->SignalList);
-    }
-    KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
+    KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
 
     return 0;
 }
@@ -86,8 +60,6 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
     IP_ADDRESS RemoteAddress, LocalAddress;
     PIPv4_HEADER Header;
 
-    ASSERT_LOCKED(&TCPLock);
-
     if( *data == 0x45 ) { /* IPv4 */
     Header = (PIPv4_HEADER)data;
     LocalAddress.Type = IP_ADDRESS_V4;
@@ -181,8 +153,6 @@ void *TCPMalloc( void *ClientData,
     void *v;
     ULONG Signature;
 
-    ASSERT_LOCKED(&TCPLock);
-
 #if 0 != MEM_PROFILE
     static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
     static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
@@ -258,8 +228,6 @@ void TCPFree( void *ClientData,
           void *data, OSK_PCHAR File, OSK_UINT Line ) {
     ULONG Signature;
 
-    ASSERT_LOCKED(&TCPLock);
-
     UntrackFL( (PCHAR)File, Line, data, FOURCC('f','b','s','d') );
     data = (void *)((char *) data - sizeof(ULONG));
     Signature = *((ULONG *) data);
index a9907ab..c978beb 100644 (file)
 LONG TCP_IPIdentification = 0;
 static BOOLEAN TCPInitialized = FALSE;
 static NPAGED_LOOKASIDE_LIST TCPSegmentList;
-LIST_ENTRY SignalledConnectionsList;
-KSPIN_LOCK SignalledConnectionsLock;
-RECURSIVE_MUTEX TCPLock;
 PORT_SET TCPPorts;
 
-ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
+static VOID DrainSignals() {
+    PCONNECTION_ENDPOINT Connection;
+    PLIST_ENTRY CurrentEntry, NextEntry;
+    KIRQL OldIrql;
     NTSTATUS Status = STATUS_SUCCESS;
     PTCP_COMPLETION_ROUTINE Complete;
     PTDI_BUCKET Bucket;
@@ -28,279 +28,290 @@ ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
     PIRP Irp;
     PMDL Mdl;
 
-    TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
-                           Connection, Connection->SocketContext));
-
-    if( Connection->SignalState & SEL_FIN ) {
-        TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
-
-        Connection->SignalState &= ~SEL_READ;
-        while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
-                                                     &Connection->Lock )) != NULL)
-        {
-           Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-           Complete = Bucket->Request.RequestNotifyObject;
-
-           Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
-
-           exFreePool(Bucket);
-        }
-
-        Connection->SignalState &= ~SEL_WRITE;
-        while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
-                                                     &Connection->Lock )) != NULL)
-        {
-           Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-           Complete = Bucket->Request.RequestNotifyObject;
-
-           Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
-
-           exFreePool(Bucket);
-        }
-
-        Connection->SignalState &= ~SEL_ACCEPT;
-        while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
-                                                     &Connection->Lock )) != NULL)
-        {
-           Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-           Complete = Bucket->Request.RequestNotifyObject;
-
-           /* We have to notify oskittcp of the abortion */
-           TCPAbortListenForSocket(Connection->AddressFile->Listener,
-                               Connection);
+    KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+    CurrentEntry = ConnectionEndpointListHead.Flink;
+    while (CurrentEntry != &ConnectionEndpointListHead)
+    {
+        NextEntry = CurrentEntry->Flink;
+        KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
 
-           Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
+        Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
+                                        ListEntry );
 
-           exFreePool(Bucket);
-        }
+        KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
-        Connection->SignalState &= ~SEL_CONNECT;
-        while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
-                                                     &Connection->Lock )) != NULL)
-        {
-           Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-           Complete = Bucket->Request.RequestNotifyObject;
+        TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
+                               Connection, Connection->SocketContext));
 
-           Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
+        if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) {
+            KeReleaseSpinLock(&Connection->Lock, OldIrql);
+            TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
 
-           exFreePool(Bucket);
-        }
-    }
+            while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
+                                                         &Connection->Lock )) != NULL)
+            {
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
 
-    /* Things that can happen when we try the initial connection */
-    if( Connection->SignalState & SEL_CONNECT ) {
-        Connection->SignalState &= ~SEL_CONNECT;
-        while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
-                                                     &Connection->Lock )) != NULL ) {
-            
-            TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
+               Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
 
-            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 );
+               exFreePool(Bucket);
+            }
 
-            /* Frees the bucket allocated in TCPConnect */
-            exFreePool( Bucket );
-        }
-    }
+            while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
+                                                         &Connection->Lock )) != NULL)
+            {
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
 
-    if( Connection->SignalState & SEL_ACCEPT ) {
-        /* Handle readable on a listening socket --
-         * TODO: Implement filtering
-         */
+               Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
 
-        TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
-                               Connection,
-                               IsListEmpty(&Connection->ListenRequest) ?
-                               "empty" : "nonempty"));
+               exFreePool(Bucket);
+            }
 
-        Connection->SignalState &= ~SEL_ACCEPT;
-        while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
-                                                     &Connection->Lock )) != NULL ) {
-            PIO_STACK_LOCATION IrpSp;
+            while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
+                                                         &Connection->Lock )) != NULL)
+            {
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
 
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-            Complete = Bucket->Request.RequestNotifyObject;
+               Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
 
-            Irp = Bucket->Request.RequestContext;
-            IrpSp = IoGetCurrentIrpStackLocation( Irp );
+               exFreePool(Bucket);
+            }
 
-            TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
-            Status = TCPServiceListeningSocket
-                ( Connection->AddressFile->Listener,
-                  Bucket->AssociatedEndpoint,
-                  (PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
+            while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
+                                                         &Connection->Lock )) != NULL)
+            {
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
 
-            TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
+               Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
 
-            if( Status == STATUS_PENDING ) {
-                Connection->SignalState |= SEL_ACCEPT;
-                ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry, &Connection->Lock );
-                break;
-            } else {
-                Complete( Bucket->Request.RequestContext, Status, 0 );
-                exFreePool( Bucket );
+               exFreePool(Bucket);
             }
+
+            KeAcquireSpinLock(&Connection->Lock, &OldIrql);
         }
-    }
 
-    /* Things that happen after we're connected */
-    if( Connection->SignalState & SEL_READ ) {
-        TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
-                               IsListEmpty(&Connection->ReceiveRequest) ?
-                               "empty" : "nonempty"));
+        /* 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"));
 
-        Connection->SignalState &= ~SEL_READ;
-        while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
-                                                     &Connection->Lock )) != NULL ) {
-            OSK_UINT RecvLen = 0, Received = 0;
-            PVOID RecvBuffer = 0;
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
+               TI_DbgPrint(DEBUG_TCP,
+                           ("Completing Request %x\n", Bucket->Request.RequestContext));
 
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-            Complete = Bucket->Request.RequestNotifyObject;
+               Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
 
-            Irp = Bucket->Request.RequestContext;
-            Mdl = Irp->MdlAddress;
+               /* Frees the bucket allocated in TCPConnect */
+               exFreePool( Bucket );
+           }
+           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+       }
 
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Getting the user buffer from %x\n", Mdl));
+       if( Connection->SignalState & SEL_ACCEPT ) {
+           /* Handle readable on a listening socket --
+            * TODO: Implement filtering
+            */
 
-            NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
+           KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
+           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 ) {
+               PIO_STACK_LOCATION IrpSp;
+
+               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 );
+                   break;
+               } else {
+                   Complete( Bucket->Request.RequestContext, Status, 0 );
+                   exFreePool( Bucket );
+               }
+          }
+
+          KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+      }
+
+      /* Things that happen after we're connected */
+      if( Connection->SignalState & SEL_READ &&
+          Connection->SignalState & SEL_CONNECT ) {
+          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 ) {
+               OSK_UINT RecvLen = 0, Received = 0;
+               PVOID RecvBuffer = 0;
+
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
+
+               Irp = Bucket->Request.RequestContext;
+               Mdl = Irp->MdlAddress;
+
+               TI_DbgPrint(DEBUG_TCP,
+                           ("Getting the user buffer from %x\n", Mdl));
+
+               NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
+
+               TI_DbgPrint(DEBUG_TCP,
+                           ("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
+
+               TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
+               TI_DbgPrint
+                   (DEBUG_TCP,
+                    ("Connection->SocketContext: %x\n",
+                     Connection->SocketContext));
+               TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
+
+               KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+               Status = TCPTranslateError
+                    ( OskitTCPRecv( Connection->SocketContext,
+                                    RecvBuffer,
+                                    RecvLen,
+                                    &Received,
+                                    0 ) );
 
-            TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
-            TI_DbgPrint
+               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 );
+                   break;
+               } else {
+                   TI_DbgPrint(DEBUG_TCP,
+                               ("Completing Receive request: %x %x\n",
+                                Bucket->Request, Status));
+                   Complete( Bucket->Request.RequestContext, Status, 0 );
+                   exFreePool( Bucket );
+               }
+           }
+
+           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+       }
+       if( Connection->SignalState & SEL_WRITE &&
+           Connection->SignalState & SEL_CONNECT ) {
+           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 ) {
+               OSK_UINT SendLen = 0, Sent = 0;
+               PVOID SendBuffer = 0;
+
+               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+               Complete = Bucket->Request.RequestNotifyObject;
+
+               Irp = Bucket->Request.RequestContext;
+               Mdl = Irp->MdlAddress;
+
+               TI_DbgPrint(DEBUG_TCP,
+                           ("Getting the user buffer from %x\n", Mdl));
+
+               NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
+
+               TI_DbgPrint(DEBUG_TCP,
+                           ("Writing %d bytes to %x\n", SendLen, SendBuffer));
+
+               TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
+               TI_DbgPrint
                 (DEBUG_TCP,
                  ("Connection->SocketContext: %x\n",
                   Connection->SocketContext));
-            TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
-
-            Status = TCPTranslateError
-                ( OskitTCPRecv( Connection->SocketContext,
-                                RecvBuffer,
-                                RecvLen,
-                                &Received,
-                                0 ) );
-
-            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 );
-                Connection->SignalState |= SEL_READ;
-                break;
-            } else {
-                TI_DbgPrint(DEBUG_TCP,
-                            ("Completing Receive request: %x %x\n",
-                             Bucket->Request, Status));
-                Complete( Bucket->Request.RequestContext, Status, 0 );
-                exFreePool( Bucket );
-            }
-        }
-    }
-    if( Connection->SignalState & SEL_WRITE ) {
-        TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
-                               IsListEmpty(&Connection->SendRequest) ?
-                               "empty" : "nonempty"));
-
-        Connection->SignalState &= ~SEL_WRITE;
-        while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
-                                                     &Connection->Lock )) != NULL ) {
-            OSK_UINT SendLen = 0, Sent = 0;
-            PVOID SendBuffer = 0;
-
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-            Complete = Bucket->Request.RequestNotifyObject;
-
-            Irp = Bucket->Request.RequestContext;
-            Mdl = Irp->MdlAddress;
-
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Getting the user buffer from %x\n", Mdl));
-
-            NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
 
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Writing %d bytes to %x\n", SendLen, SendBuffer));
+               KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
-            TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
-            TI_DbgPrint
-                (DEBUG_TCP,
-                 ("Connection->SocketContext: %x\n",
-                  Connection->SocketContext));
+               Status = TCPTranslateError
+                   ( OskitTCPSend( Connection->SocketContext,
+                                   SendBuffer,
+                                   SendLen,
+                                   &Sent,
+                                   0 ) );
 
-            Status = TCPTranslateError
-                ( OskitTCPSend( Connection->SocketContext,
-                                SendBuffer,
-                                SendLen,
-                                &Sent,
-                                0 ) );
+               KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
-            TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
+               TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
 
-            if( Status == STATUS_SUCCESS ) {
-                TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
+               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 );
-                Connection->SignalState |= SEL_WRITE;
-                break;
-            } else {
-                TI_DbgPrint(DEBUG_TCP,
-                            ("Completing Send request: %x %x\n",
-                             Bucket->Request, Status));
-                Complete( Bucket->Request.RequestContext, Status, 0 );
-                exFreePool( Bucket );
-            }
-        }
+                   Complete( Bucket->Request.RequestContext,
+                             STATUS_SUCCESS, Sent );
+                   exFreePool( Bucket );
+               } else if( Status == STATUS_PENDING ) {
+                   ExInterlockedInsertHeadList( &Connection->SendRequest, &Bucket->Entry,
+                                                &Connection->Lock );
+                   break;
+               } else {
+                   TI_DbgPrint(DEBUG_TCP,
+                               ("Completing Send request: %x %x\n",
+                               Bucket->Request, Status));
+                   Complete( Bucket->Request.RequestContext, Status, 0 );
+                   exFreePool( Bucket );
+               }
+           }
+           KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+       }
+
+       KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
+       if (!Connection->SocketContext)
+       {
+           TCPFreeConnectionEndpoint(Connection);
+       }
+
+       CurrentEntry = NextEntry;
+
+       KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
     }
 
-    return Connection->SignalState;
-}
-
-static VOID DrainSignals() {
-    PCONNECTION_ENDPOINT Connection;
-    PLIST_ENTRY CurrentEntry, NextEntry;
-    ULONG NewState;
-    KIRQL OldIrql;
-
-    KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
-    CurrentEntry = SignalledConnectionsList.Flink;
-    while (CurrentEntry != &SignalledConnectionsList)
-    {
-        NextEntry = CurrentEntry->Flink;
-        Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
-                                        SignalList );
-
-        KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
-        NewState = HandleSignalledConnection(Connection);
-        KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
-
-        if (NewState == SEL_FIN || NewState == 0)
-        {
-            RemoveEntryList(CurrentEntry);
-        }
-
-        CurrentEntry = NextEntry;
-    }
-    KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
+    KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
 }
 
 PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
@@ -314,7 +325,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
     RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
 
     /* Initialize spin lock that protects the connection endpoint file object */
-    TcpipInitializeSpinLock(&Connection->Lock);
+    KeInitializeSpinLock(&Connection->Lock);
     InitializeListHead(&Connection->ConnectRequest);
     InitializeListHead(&Connection->ListenRequest);
     InitializeListHead(&Connection->ReceiveRequest);
@@ -323,19 +334,32 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
     /* Save client context pointer */
     Connection->ClientContext = ClientContext;
 
+    /* Add connection endpoint to global list */
+    ExInterlockedInsertTailList(&ConnectionEndpointListHead,
+                                &Connection->ListEntry,
+                                &ConnectionEndpointListLock);
+
     return Connection;
 }
 
 VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ) {
+    KIRQL OldIrql;
+
     TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
+
+    TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
+    RemoveEntryList(&Connection->ListEntry);
+    TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
+
     exFreePool( Connection );
 }
 
 NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
                     UINT Family, UINT Type, UINT Proto ) {
     NTSTATUS Status;
+    KIRQL OldIrql;
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, "
                            "Proto %d\n",
@@ -352,7 +376,7 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
     TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
                            Connection->SocketContext));
 
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     return Status;
 }
@@ -370,13 +394,9 @@ VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
                            IPPacket->TotalSize,
                            IPPacket->HeaderSize));
 
-    TcpipRecursiveMutexEnter( &TCPLock );
-
     OskitTCPReceiveDatagram( IPPacket->Header,
                              IPPacket->TotalSize,
                              IPPacket->HeaderSize );
-
-    TcpipRecursiveMutexLeave( &TCPLock );
 }
 
 /* event.c */
@@ -447,10 +467,7 @@ TimerThread(PVOID Context)
             PsTerminateSystemThread(Status);
         }
 
-        TcpipRecursiveMutexEnter( &TCPLock );
         TimerOskitTCP( Next == NextFast, Next == NextSlow );
-        TcpipRecursiveMutexLeave( &TCPLock );
-
         if (Next == NextSlow) {
             DrainSignals();
         }
@@ -483,9 +500,6 @@ NTSTATUS TCPStartup(VOID)
 {
     NTSTATUS Status;
 
-    TcpipRecursiveMutexInit( &TCPLock );
-    KeInitializeSpinLock( &SignalledConnectionsLock );
-    InitializeListHead( &SignalledConnectionsList );
     Status = TCPMemStartup();
     if ( ! NT_SUCCESS(Status) ) {
         return Status;
@@ -497,10 +511,8 @@ NTSTATUS TCPStartup(VOID)
         return Status;
     }
 
-    TcpipRecursiveMutexEnter(&TCPLock);
     RegisterOskitTCPEventHandlers( &EventHandlers );
     InitOskitTCP();
-    TcpipRecursiveMutexLeave(&TCPLock);
 
     /* Register this protocol with IP layer */
     IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
@@ -545,9 +557,7 @@ NTSTATUS TCPShutdown(VOID)
 
     TCPInitialized = FALSE;
 
-    TcpipRecursiveMutexEnter(&TCPLock);
     DeinitOskitTCP();
-    TcpipRecursiveMutexLeave(&TCPLock);
 
     PortsShutdown( &TCPPorts );
 
@@ -597,6 +607,7 @@ NTSTATUS TCPConnect
     USHORT RemotePort;
     PTDI_BUCKET Bucket;
     PNEIGHBOR_CACHE_ENTRY NCE;
+    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n"));
 
@@ -625,7 +636,7 @@ NTSTATUS TCPConnect
     AddressToBind = AddressToConnect;
     AddressToBind.sin_addr.s_addr = NCE->Interface->Unicast.Address.IPv4Address;
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
     Status = TCPTranslateError
         ( OskitTCPBind( Connection->SocketContext,
@@ -640,26 +651,29 @@ NTSTATUS TCPConnect
 
         Status = TCPTranslateError
             ( OskitTCPConnect( Connection->SocketContext,
-                               Connection,
                                &AddressToConnect,
                                sizeof(AddressToConnect) ) );
 
+        KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
         if (Status == STATUS_PENDING)
         {
             Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
-            if( !Bucket ) return STATUS_NO_MEMORY;
+            if( !Bucket )
+            {
+               return STATUS_NO_MEMORY;
+            }
             
             Bucket->Request.RequestNotifyObject = (PVOID)Complete;
             Bucket->Request.RequestContext = Context;
-            
-            IoMarkIrpPending((PIRP)Context);
                        
-            ExInterlockedInsertTailList( &Connection->ConnectRequest, &Bucket->Entry, &Connection->Lock );
+            ExInterlockedInsertTailList( &Connection->ConnectRequest, &Bucket->Entry,
+                                         &Connection->Lock );
         }
+    } else {
+        KeReleaseSpinLock(&Connection->Lock, OldIrql);
     }
 
-    TcpipRecursiveMutexLeave(&TCPLock);
-
     return Status;
 }
 
@@ -671,12 +685,11 @@ NTSTATUS TCPDisconnect
   PTCP_COMPLETION_ROUTINE Complete,
   PVOID Context ) {
     NTSTATUS Status = STATUS_INVALID_PARAMETER;
-
-    ASSERT_LOCKED(&TCPLock);
+    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP,("started\n"));
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
     if (Flags & TDI_DISCONNECT_RELEASE)
         Status = TCPTranslateError(OskitTCPDisconnect(Connection->SocketContext));
@@ -684,7 +697,7 @@ NTSTATUS TCPDisconnect
     if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
         Status = TCPTranslateError(OskitTCPShutdown(Connection->SocketContext, FWRITE | FREAD));
 
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("finished %x\n", Status));
 
@@ -694,20 +707,20 @@ NTSTATUS TCPDisconnect
 NTSTATUS TCPClose
 ( PCONNECTION_ENDPOINT Connection ) {
     NTSTATUS Status;
+    KIRQL OldIrql;
+    PVOID Socket;
 
     TI_DbgPrint(DEBUG_TCP,("TCPClose started\n"));
 
-    /* Make our code remove all pending IRPs */
-    Connection->SignalState |= SEL_FIN;
-    HandleSignalledConnection(Connection);
-
-    TcpipRecursiveMutexEnter(&TCPLock);
-
-    Status = TCPTranslateError( OskitTCPClose( Connection->SocketContext ) );
-    if (Status == STATUS_SUCCESS)
-        Connection->SocketContext = NULL;
-
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+    Socket = Connection->SocketContext;
+    Connection->SocketContext = NULL;
+    Status = TCPTranslateError( OskitTCPClose( Socket ) );
+    if (!NT_SUCCESS(Status))
+    {
+        Connection->SocketContext = Socket;
+    }
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("TCPClose finished %x\n", Status));
 
@@ -726,17 +739,18 @@ NTSTATUS TCPReceiveData
     UINT DataLen, Received = 0;
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
+    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
                            ReceiveLength, Connection->SocketContext));
 
-    ASSERT_KM_POINTER(Connection->SocketContext);
-
     NdisQueryBuffer( Buffer, &DataBuffer, &DataLen );
 
     TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
+    ASSERT_KM_POINTER(Connection->SocketContext);
 
     Status = TCPTranslateError
         ( OskitTCPRecv
@@ -746,7 +760,7 @@ NTSTATUS TCPReceiveData
             &Received,
             ReceiveFlags ) );
 
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("OskitTCPReceive: %x, %d\n", Status, Received));
 
@@ -763,9 +777,8 @@ NTSTATUS TCPReceiveData
         Bucket->Request.RequestContext = Context;
         *BytesReceived = 0;
 
-        IoMarkIrpPending((PIRP)Context);
-
-        ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
+        ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry,
+                                     &Connection->Lock );
         TI_DbgPrint(DEBUG_TCP,("Queued read irp\n"));
     } else {
         TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Received));
@@ -788,8 +801,9 @@ NTSTATUS TCPSendData
     UINT Sent = 0;
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
+    KIRQL OldIrql;
 
-    ASSERT_LOCKED(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
                            SendLength, Connection->SocketContext));
@@ -800,14 +814,12 @@ NTSTATUS TCPSendData
     TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n",
                            Connection->SocketContext));
 
-    TcpipRecursiveMutexEnter(&TCPLock);
-
     Status = TCPTranslateError
         ( OskitTCPSend( Connection->SocketContext,
                         (OSK_PCHAR)BufferData, SendLength,
                         &Sent, 0 ) );
 
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP,("OskitTCPSend: %x, %d\n", Status, Sent));
 
@@ -823,10 +835,9 @@ NTSTATUS TCPSendData
         Bucket->Request.RequestNotifyObject = Complete;
         Bucket->Request.RequestContext = Context;
         *BytesSent = 0;
-
-        IoMarkIrpPending((PIRP)Context);
         
-        ExInterlockedInsertTailList( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
+        ExInterlockedInsertTailList( &Connection->SendRequest, &Bucket->Entry,
+                                     &Connection->Lock );
         TI_DbgPrint(DEBUG_TCP,("Queued write irp\n"));
     } else {
         TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent));
@@ -865,14 +876,15 @@ NTSTATUS TCPGetSockAddress
     OSK_UI16 LocalPort, RemotePort;
     PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
     NTSTATUS Status;
+    KIRQL OldIrql;
 
-    TcpipRecursiveMutexEnter(&TCPLock);
+    KeAcquireSpinLock(&Connection->Lock, &OldIrql);
 
     Status = TCPTranslateError(OskitTCPGetAddress(Connection->SocketContext,
                                                   &LocalAddress, &LocalPort,
                                                   &RemoteAddress, &RemotePort));
 
-    TcpipRecursiveMutexLeave(&TCPLock);
+    KeReleaseSpinLock(&Connection->Lock, OldIrql);
 
     if (!NT_SUCCESS(Status))
         return Status;
index 46366e6..125e510 100644 (file)
@@ -172,6 +172,9 @@ NTSTATUS UDPSendDatagram(
     USHORT RemotePort;
     NTSTATUS Status;
     PNEIGHBOR_CACHE_ENTRY NCE;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
 
     TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
                                                   AddrFile, ConnInfo, BufferData, DataSize));
@@ -186,10 +189,12 @@ NTSTATUS UDPSendDatagram(
                break;
 
     default:
+               KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
                return STATUS_UNSUCCESSFUL;
     }
 
     if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
+               KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
                return STATUS_NETWORK_UNREACHABLE;
     }
 
@@ -213,14 +218,20 @@ NTSTATUS UDPSendDatagram(
                                                         DataSize );
 
     if( !NT_SUCCESS(Status) )
+    {
+               KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
                return Status;
+    }
 
     if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, UDPSendPacketComplete, NULL )))
     {
+       KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
         FreeNdisPacket(Packet.NdisPacket);
         return Status;
     }
 
+    KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
     return STATUS_SUCCESS;
 }
 
index b5242fe..b8c008e 100644 (file)
@@ -123,7 +123,7 @@ extern int OskitTCPSend( void *socket,
                         OSK_UINT *OutLen,
                         OSK_UINT Flags );
 
-extern int OskitTCPConnect( void *socket, void *connection,
+extern int OskitTCPConnect( void *socket,
                            void *nam, OSK_UINT namelen );
 extern int OskitTCPClose( void *socket );
 
@@ -131,7 +131,7 @@ extern int OskitTCPBind( void *socket,
                         void *nam, OSK_UINT namelen );
 
 extern int OskitTCPAccept( void *socket, void **new_socket,
-                          void *addr_out,
+                          void *context, void *addr_out,
                           OSK_UINT addr_len,
                           OSK_UINT *out_addr_len,
                           OSK_UINT finish_accept );
@@ -187,4 +187,27 @@ void fbsd_free( void *data, char *file, unsigned line, ... );
 #define        FREAD           0x0001
 #define        FWRITE          0x0002
 
+/* Don't define this unless your are insane or aicom */
+//#define LOCK_SPAM
+
+#ifdef LOCK_SPAM
+#define OSKLock() if (!KeTryToAcquireSpinLockAtDpcLevel(&OSKLock)) \
+                  { \
+                      DbgPrint("OSKLock WAIT (%s)\n", __FUNCTION__); \
+                      KeAcquireSpinLockAtDpcLevel(&OSKLock); \
+                  } \
+                  DbgPrint("OSKLock >>>> (%s)\n", __FUNCTION__)
+
+#define OSKUnlock() KeReleaseSpinLockFromDpcLevel(&OSKLock); \
+                    DbgPrint("OSKLock <<<< (%s)\n", __FUNCTION__)
+#else
+#define OSKLock() KeAcquireSpinLockAtDpcLevel(&OSKLock)
+#define OSKUnlock() KeReleaseSpinLockFromDpcLevel(&OSKLock)
+#endif
+
+#define OSKLockAndRaise(x) KeRaiseIrql(DISPATCH_LEVEL, x); \
+                           OSKLock()
+#define OSKUnlockAndLower(x) OSKUnlock(); \
+                             KeLowerIrql(x)
+
 #endif/*OSKITTCP_H*/
index 5aea3dd..ef6f521 100644 (file)
@@ -23,6 +23,8 @@ OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
 //OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
 OSK_UINT OskitDebugTraceLevel = 0;
 
+KSPIN_LOCK OSKLock;
+
 /* SPL */
 unsigned cpl;
 unsigned net_imask;
@@ -45,6 +47,7 @@ void fbsd_free( void *data, char *file, unsigned line, ... ) {
 
 void InitOskitTCP() {
     OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
+    KeInitializeSpinLock(&OSKLock);
     OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
     mbinit();
     OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
@@ -66,12 +69,19 @@ void DeinitOskitTCP() {
 }
 
 void TimerOskitTCP( int FastTimer, int SlowTimer ) {
+    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);
     if ( SlowTimer ) {
         tcp_slowtimo();
     }
     if ( FastTimer ) {
         tcp_fasttimo();
     }
+    OSKUnlockAndLower(OldIrql);
 }
 
 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
@@ -115,12 +125,16 @@ int OskitTCPSocket( void *context,
                    int proto )
 {
     struct socket *so;
+
+    OSKLock();
     int error = socreate(domain, &so, type, proto);
     if( !error ) {
        so->so_connection = context;
        so->so_state |= SS_NBIO;
        *aso = so;
     }
+    OSKUnlock();
+
     return error;
 }
 
@@ -153,8 +167,11 @@ int OskitTCPRecv( void *connection,
 
     OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
 
+    OSKLock();
     error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
                       &tcp_flags );
+    OSKUnlock();
+
     *OutLen = Len - uio.uio_resid;
 
     return error;
@@ -182,14 +199,15 @@ int OskitTCPBind( void *socket,
     addr.sa_family = addr.sa_len;
     addr.sa_len = sizeof(struct sockaddr);
 
+    OSKLock();
     error = sobind(so, &sabuf);
+    OSKUnlock();
 
     OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
     return (error);
 }
 
-int OskitTCPConnect( void *socket, void *connection,
-                    void *nam, OSK_UINT namelen ) {
+int OskitTCPConnect( void *socket, void *nam, OSK_UINT namelen ) {
     struct socket *so = socket;
     int error = EFAULT;
     struct mbuf sabuf;
@@ -197,8 +215,7 @@ int OskitTCPConnect( void *socket, void *connection,
 
     OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
 
-    so->so_connection = connection;
-
+    OSKLock();
     if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
        error = EALREADY;
        goto done;
@@ -217,7 +234,9 @@ int OskitTCPConnect( void *socket, void *connection,
 
     error = soconnect(so, &sabuf);
 
-    if (error)
+    if (error == EINPROGRESS)
+        goto done;
+    else if (error)
        goto bad;
 
     if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
@@ -232,34 +251,49 @@ bad:
        error = EINTR;
 
 done:
+    OSKUnlock();
     OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
     return (error);
 }
 
 int OskitTCPDisconnect(void *socket)
 {
+    int error;
+
     if (!socket)
         return OSK_ESHUTDOWN;
 
-    return sodisconnect(socket);
+    OSKLock();
+    error = sodisconnect(socket);
+    OSKUnlock();
+
+    return error;
 }
 
 int OskitTCPShutdown( void *socket, int disconn_type ) {
+    int error;
+
     if (!socket)
         return OSK_ESHUTDOWN;
 
-    return soshutdown( socket, disconn_type );
+    OSKLock();
+    error = soshutdown( socket, disconn_type );
+    OSKUnlock();
+
+    return error;
 }
 
 int OskitTCPClose( void *socket ) {
-    struct socket *so = socket;
+    int error;
 
     if (!socket)
         return OSK_ESHUTDOWN;
 
-    so->so_connection = 0;
-    soclose( so );
-    return 0;
+    OSKLock();
+    error = soclose( socket );
+    OSKUnlock();
+
+    return error;
 }
 
 int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
@@ -281,7 +315,10 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
     uio.uio_rw = UIO_WRITE;
     uio.uio_procp = NULL;
 
+    OSKLock();
     error = sosend( socket, NULL, &uio, NULL, NULL, 0 );
+    OSKUnlock();
+
     *OutLen = Len - uio.uio_resid;
 
     return error;
@@ -289,6 +326,7 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
 
 int OskitTCPAccept( void *socket,
                    void **new_socket,
+                   void *context,
                    void *AddrOut,
                    OSK_UINT AddrLen,
                    OSK_UINT *OutAddrLen,
@@ -317,11 +355,12 @@ int OskitTCPAccept( void *socket,
        /* that's a copyin actually */
        namelen = *OutAddrLen;
 
+    OSKLock();
+
     s = splnet();
 
 #if 0
     if ((head->so_options & SO_ACCEPTCONN) == 0) {
-       splx(s);
        OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
                                   head->so_options, SO_ACCEPTCONN));
        error = EINVAL;
@@ -333,39 +372,10 @@ int OskitTCPAccept( void *socket,
                               head->so_q, head->so_state));
 
     if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
-       splx(s);
        error = EWOULDBLOCK;
        goto out;
     }
 
-    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-    while (head->so_q == NULL && head->so_error == 0) {
-       if (head->so_state & SS_CANTRCVMORE) {
-           head->so_error = ECONNABORTED;
-           break;
-       }
-       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-       error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
-                      "accept", 0);
-       if (error) {
-           splx(s);
-           goto out;
-       }
-       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-    }
-    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-
-#if 0
-    if (head->so_error) {
-       OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-       error = head->so_error;
-       head->so_error = 0;
-       splx(s);
-       goto out;
-    }
-    OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-#endif
-
     /*
      * At this point we know that there is at least one connection
      * ready to be accepted. Remove it from the queue.
@@ -384,19 +394,20 @@ int OskitTCPAccept( void *socket,
        head->so_q = so->so_q;
        head->so_qlen--;
 
-       *newso = so;
-
-       /*so->so_state &= ~SS_COMP;*/
-
        mnam.m_data = (char *)&sa;
        mnam.m_len = sizeof(sa);
 
-       (void) soaccept(so, &mnam);
+       error = soaccept(so, &mnam);
+        if (error)
+            goto out;
 
-       so->so_state = SS_NBIO | SS_ISCONNECTED;
+       so->so_state |= SS_NBIO | SS_ISCONNECTED;
         so->so_q = so->so_q0 = NULL;
         so->so_qlen = 0;
         so->so_head = 0;
+        so->so_connection = context;
+
+       *newso = so;
 
        OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
        if (name) {
@@ -406,9 +417,10 @@ int OskitTCPAccept( void *socket,
            *OutAddrLen = namelen;      /* copyout actually */
        }
        OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
-       splx(s);
     }
 out:
+    splx(s);
+    OSKUnlock();
     OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
     return (error);
 }
@@ -421,10 +433,20 @@ out:
 
 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
                              OSK_UINT IpHeaderLen ) {
-    struct mbuf *Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
+    struct mbuf *Ip;
     struct ip *iph;
+    KIRQL OldIrql;
 
-    if( !Ip ) return; /* drop the segment */
+    /* 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);
+    Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
+    if( !Ip )
+    {
+       OSKUnlockAndLower(OldIrql);
+       return; /* drop the segment */
+    }
 
     //memcpy( Ip->m_data, Data, Len );
     Ip->m_pkthdr.len = IpHeaderLen;
@@ -439,6 +461,7 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
                 IpHeaderLen));
 
     tcp_input(Ip, IpHeaderLen);
+    OSKUnlockAndLower(OldIrql);
 
     /* The buffer Ip is freed by tcp_input */
 }
@@ -450,6 +473,7 @@ int OskitTCPSetSockOpt(void *socket,
                        int size)
 {
     struct mbuf *m;
+    int error;
 
     if (!socket)
         return OSK_ESHUTDOWN;
@@ -457,16 +481,23 @@ int OskitTCPSetSockOpt(void *socket,
     if (size >= MLEN)
         return OSK_EINVAL;
 
+    OSKLock();
     m = m_get(M_WAIT, MT_SOOPTS);
     if (!m)
+    {
+        OSKUnlock();
         return OSK_ENOMEM;
+    }
 
     m->m_len = size;
 
     memcpy(m->m_data, buffer, size);
 
     /* m is freed by sosetopt */
-    return sosetopt(socket, level, optname, m);
+    error = sosetopt(socket, level, optname, m);
+    OSKUnlock();
+
+    return error;
 }   
 
 int OskitTCPGetSockOpt(void *socket,
@@ -481,6 +512,7 @@ int OskitTCPGetSockOpt(void *socket,
     if (!socket)
         return OSK_ESHUTDOWN;
 
+    OSKLock();
     error = sogetopt(socket, level, optname, &m);
     if (!error)
     {
@@ -489,6 +521,7 @@ int OskitTCPGetSockOpt(void *socket,
         if (!buffer || oldsize < m->m_len)
         {
             m_freem(m);
+            OSKUnlock();
             return OSK_EINVAL;
         }
 
@@ -496,6 +529,7 @@ int OskitTCPGetSockOpt(void *socket,
 
         m_freem(m);
     }
+    OSKUnlock();
 
     return error;
 }
@@ -507,7 +541,11 @@ int OskitTCPListen( void *socket, int backlog ) {
         return OSK_ESHUTDOWN;
 
     OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
+
+    OSKLock();
     error = solisten( socket, backlog );
+    OSKUnlock();
+
     OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
 
     return error;
@@ -524,11 +562,13 @@ int OskitTCPSetAddress( void *socket,
     if (!socket)
         return OSK_ESHUTDOWN;
 
+    OSKLock();
     inp = (struct inpcb *)so->so_pcb;
     inp->inp_laddr.s_addr = LocalAddress;
     inp->inp_lport = LocalPort;
     inp->inp_faddr.s_addr = RemoteAddress;
     inp->inp_fport = RemotePort;
+    OSKUnlock();
 
     return 0;
 }
@@ -544,11 +584,13 @@ int OskitTCPGetAddress( void *socket,
     if (!socket)
         return OSK_ESHUTDOWN;
 
+    OSKLock();
     inp = (struct inpcb *)so->so_pcb;
     *LocalAddress = inp->inp_laddr.s_addr;
     *LocalPort = inp->inp_lport;
     *RemoteAddress = inp->inp_faddr.s_addr;
     *RemotePort = inp->inp_fport;
+    OSKUnlock();
 
     return 0;
 }