Fix firefox exit.  Implement a simple work queue for possibly dispatch level
callbacks for cancel and close.
Modified: trunk/reactos/drivers/lib/ip/network/receive.c
Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c
Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h
Modified: trunk/reactos/drivers/net/tcpip/include/tcpip.h
Modified: trunk/reactos/drivers/net/tcpip/include/titypes.h
Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
Modified: trunk/reactos/drivers/net/tcpip/tcpip/fileobjs.c
Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c

Modified: trunk/reactos/drivers/lib/ip/network/receive.c
--- trunk/reactos/drivers/lib/ip/network/receive.c	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/lib/ip/network/receive.c	2005-12-07 08:50:27 UTC (rev 19943)
@@ -521,6 +521,8 @@
  *     IPPacket = Pointer to IP packet
  */
 {
+    IP_ADDRESS Address;
+
     TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
 
     IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2;
@@ -562,7 +564,16 @@
 
     /* FIXME: Should we allow packets to be received on the wrong interface? */
     /* XXX Find out if this packet is destined for us */
-    ProcessFragment(IF, IPPacket);
+
+    if( AddrLocateADEv4( IPPacket->DstAddr.Address.IPv4Address, &Address ) ) {
+	ProcessFragment( IF, IPPacket );
+    } else {
+	PNEIGHBOR_CACHE_ENTRY NCE;
+
+	if((NCE = RouteGetRouteToDestination( &IPPacket->DstAddr ))) {
+	    IPSendDatagram( IPPacket, NCE, NULL, NULL );
+	}
+    }
 #if 0
     } else {
 	/* This packet is not destined for us. If we are a router,

Modified: trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c
--- trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/lib/ip/transport/tcp/tcp.c	2005-12-07 08:50:27 UTC (rev 19943)
@@ -647,4 +647,8 @@
     return STATUS_SUCCESS;
 }
 
+void TCPMarkForDisconnect( PCONNECTION_ENDPOINT Context, BOOLEAN Marked ) {
+    Context->Disconnecting = Marked;
+}
+
 /* EOF */

Modified: trunk/reactos/drivers/net/tcpip/include/tcp.h
--- trunk/reactos/drivers/net/tcpip/include/tcp.h	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/include/tcp.h	2005-12-07 08:50:27 UTC (rev 19943)
@@ -38,6 +38,9 @@
 
 #define TCPOPTLEN_MAX_SEG_SIZE  0x4
 
+#define TCP_CANCEL_DISCONNECT 0
+#define TCP_CANCEL_CLOSE      1
+
 /* Data offset; 32-bit words (leftmost 4 bits); convert to bytes */
 #define TCP_DATA_OFFSET(DataOffset)(((DataOffset) & 0xF0) >> (4-2))
 
@@ -57,6 +60,13 @@
     KEVENT Event;
 } SLEEPING_THREAD, *PSLEEPING_THREAD;
 
+typedef struct _CANCEL_REQUEST {
+    LIST_ENTRY Entry;
+    PVOID Context;
+    PIRP  Irp;
+    UINT  Flags, Type;
+} CANCEL_REQUEST, *PCANCEL_REQUEST;
+
 /* Retransmission timeout constants */
 
 /* Lower bound for retransmission timeout in TCP timer ticks */
@@ -176,4 +186,7 @@
 NTSTATUS TCPShutdown(
   VOID);
 
+void TCPMarkForDisconnect( 
+  PCONNECTION_ENDPOINT Connection, BOOLEAN Marked );
+
 #endif /* __TCP_H */

Modified: trunk/reactos/drivers/net/tcpip/include/tcpip.h
--- trunk/reactos/drivers/net/tcpip/include/tcpip.h	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/include/tcpip.h	2005-12-07 08:50:27 UTC (rev 19943)
@@ -188,6 +188,9 @@
 extern KSPIN_LOCK InterfaceListLock;
 extern LIST_ENTRY AddressFileListHead;
 extern KSPIN_LOCK AddressFileListLock;
+extern LIST_ENTRY      CancelQueue;
+extern KSPIN_LOCK      CancelQueueLock;
+extern WORK_QUEUE_ITEM CancelQueueWork;
 extern NDIS_HANDLE GlobalPacketPool;
 extern NDIS_HANDLE GlobalBufferPool;
 extern KSPIN_LOCK EntityListLock;

Modified: trunk/reactos/drivers/net/tcpip/include/titypes.h
--- trunk/reactos/drivers/net/tcpip/include/titypes.h	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/include/titypes.h	2005-12-07 08:50:27 UTC (rev 19943)
@@ -308,6 +308,8 @@
 				* notification service to the client */
     UINT    SignalState;       /* Active signals from oskit */
     BOOLEAN Signalled;         /* Are we a member of the signal list */
+    BOOLEAN Disconnecting;     /* Cancelling an irp .. we need to leave it 
+				* alone for now */
 } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
 
 

Modified: trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c
--- trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-12-07 08:50:27 UTC (rev 19943)
@@ -12,6 +12,8 @@
 #include "precomp.h"
 #include <pseh/pseh.h>
 
+extern VOID DeleteConnectionEndpoint( PCONNECTION_ENDPOINT Endpoint );
+
 NTSTATUS DispPrepareIrpForCancel(
     PTRANSPORT_CONTEXT Context,
     PIRP Irp,
@@ -135,7 +137,56 @@
     TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
 }
 
+VOID DDKAPI CancelQueuePassiveHandler( PVOID CancelRequestVoid ) 
+{
+    KIRQL OldIrql;
+    PCANCEL_REQUEST CancelReq;
+    PLIST_ENTRY CqEntry;
 
+    KeAcquireSpinLock( &CancelQueueLock, &OldIrql );
+
+    TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Starting\n"));
+
+    for( CqEntry = CancelQueue.Flink;
+	 CqEntry != &CancelQueue;
+	) {
+	CancelReq = CONTAINING_RECORD(CqEntry, CANCEL_REQUEST, Entry);
+	ExInterlockedRemoveHeadList( &CancelQueue, &CancelQueueLock );
+	CqEntry = CancelQueue.Flink;
+
+	KeReleaseSpinLock( &CancelQueueLock, OldIrql );
+
+	TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Executing %x\n", CancelReq));
+
+	switch( CancelReq->Type ) {
+	case TCP_CANCEL_DISCONNECT:
+	    TCPDisconnect
+		( CancelReq->Context,
+		  CancelReq->Flags,
+		  NULL,
+		  NULL,
+		  DispDataRequestComplete,
+		  CancelReq->Irp );
+	    break;
+
+	case TCP_CANCEL_CLOSE:
+	    TCPClose( CancelReq->Context );
+	    DeleteConnectionEndpoint( CancelReq->Context );
+	    break;
+	}
+
+	TCPMarkForDisconnect( CancelReq->Context, FALSE );
+
+	ExFreePool( CancelReq );
+
+	KeAcquireSpinLock( &CancelQueueLock, &OldIrql );
+    }
+
+    TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE: Ending\n"));
+
+    KeReleaseSpinLock( &CancelQueueLock, OldIrql );
+}
+
 VOID DDKAPI DispCancelRequest(
     PDEVICE_OBJECT Device,
     PIRP Irp)
@@ -150,6 +201,7 @@
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     UCHAR MinorFunction;
+    PCANCEL_REQUEST CancelRequest;
     /*NTSTATUS Status = STATUS_SUCCESS;*/
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -169,23 +221,21 @@
     /* Try canceling the request */
     switch(MinorFunction) {
     case TDI_SEND:
-        TCPDisconnect
-            ( TranContext->Handle.ConnectionContext,
-              TDI_DISCONNECT_RELEASE,
-              NULL,
-              NULL,
-              DispDataRequestComplete,
-              Irp );
-        break;
-
     case TDI_RECEIVE:
-        TCPDisconnect
-            ( TranContext->Handle.ConnectionContext,
-              TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE,
-              NULL,
-              NULL,
-              DispDataRequestComplete,
-              Irp );
+	CancelRequest = ExAllocatePoolWithTag
+	    ( sizeof(CANCEL_REQUEST), NonPagedPool, FOURCC('T','c','k','O') );
+	TCPMarkForDisconnect( TranContext->Handle.ConnectionContext, TRUE );
+	if( CancelRequest ) {
+	    TI_DbgPrint(DEBUG_IRP,("CANCEL QUEUE:-> %x\n", CancelRequest));
+	    CancelRequest->Flags = TDI_DISCONNECT_RELEASE |
+		(MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0;
+	    CancelRequest->Context = TranContext->Handle.ConnectionContext;
+	    CancelRequest->Irp = Irp;
+	    CancelRequest->Type = TCP_CANCEL_DISCONNECT;
+	    ExInterlockedInsertTailList
+		( &CancelQueue, &CancelRequest->Entry, &CancelQueueLock );
+	    ExQueueWorkItem( &CancelQueueWork, CriticalWorkQueue );
+	}
         break;
 
     case TDI_SEND_DATAGRAM:

Modified: trunk/reactos/drivers/net/tcpip/tcpip/fileobjs.c
--- trunk/reactos/drivers/net/tcpip/tcpip/fileobjs.c	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/tcpip/fileobjs.c	2005-12-07 08:50:27 UTC (rev 19943)
@@ -10,7 +10,6 @@
 
 #include "precomp.h"
 
-
 /* List of all address file objects managed by this driver */
 LIST_ENTRY AddressFileListHead;
 KSPIN_LOCK AddressFileListLock;
@@ -352,6 +351,7 @@
   KIRQL OldIrql;
   PADDRESS_FILE AddrFile;
   NTSTATUS Status = STATUS_SUCCESS;
+  PCANCEL_REQUEST CancelReq;
 
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
 
@@ -369,8 +369,16 @@
   switch (AddrFile->Protocol) {
   case IPPROTO_TCP:
     TCPFreePort( AddrFile->Port );
-    if( AddrFile->Listener )
-	TCPClose( AddrFile->Listener );
+    if( AddrFile->Listener ) {
+	CancelReq = ExAllocatePoolWithTag
+	    ( sizeof(CANCEL_REQUEST), NonPagedPool, FOURCC('T','c','l','s') );
+	if( CancelReq ) {
+	    CancelReq->Type = TCP_CANCEL_CLOSE;
+	    CancelReq->Context = AddrFile->Listener;
+	    AddrFile->Listener = NULL;
+	    ExQueueWorkItem( &CancelQueueWork, CriticalWorkQueue );
+	}
+    }
     break;
 
   case IPPROTO_UDP:
@@ -466,15 +474,19 @@
 {
   PCONNECTION_ENDPOINT Connection;
   NTSTATUS Status = STATUS_SUCCESS;
+  PCANCEL_REQUEST CancelReq;
 
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
 
   Connection = Request->Handle.ConnectionContext;
 
-  TcpipRecursiveMutexEnter( &TCPLock, TRUE );
-  TCPClose(Connection);
-  DeleteConnectionEndpoint(Connection);
-  TcpipRecursiveMutexLeave( &TCPLock );
+  CancelReq = ExAllocatePoolWithTag
+      ( sizeof(CANCEL_REQUEST), NonPagedPool, FOURCC('T','c','l','s') );
+  if( CancelReq ) {
+      CancelReq->Type = TCP_CANCEL_CLOSE;
+      CancelReq->Context = Connection;
+      ExQueueWorkItem( &CancelQueueWork, CriticalWorkQueue );
+  }
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 

Modified: trunk/reactos/drivers/net/tcpip/tcpip/main.c
--- trunk/reactos/drivers/net/tcpip/tcpip/main.c	2005-12-07 00:06:27 UTC (rev 19942)
+++ trunk/reactos/drivers/net/tcpip/tcpip/main.c	2005-12-07 08:50:27 UTC (rev 19943)
@@ -14,7 +14,7 @@
 #ifndef NDEBUG
 DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
 #else
-DWORD DebugTraceLevel = 0;
+DWORD DebugTraceLevel = DEBUG_IRP;
 #endif /* NDEBUG */
 
 PDEVICE_OBJECT TCPDeviceObject   = NULL;
@@ -35,6 +35,12 @@
 KSPIN_LOCK IpWorkLock;
 WORK_QUEUE_ITEM IpWorkItem;
 
+/* Cancel Queue */
+LIST_ENTRY CancelQueue;
+KSPIN_LOCK CancelQueueLock;
+WORK_QUEUE_ITEM CancelQueueWork;
+extern VOID DDKAPI CancelQueuePassiveHandler( PVOID Context );
+
 VOID TiWriteErrorLog(
     PDRIVER_OBJECT DriverContext,
     NTSTATUS ErrorCode,
@@ -809,6 +815,11 @@
   InitializeListHead(&InterfaceListHead);
   KeInitializeSpinLock(&InterfaceListLock);
 
+  /* Initialize cancellation queue */
+  InitializeListHead(&CancelQueue);
+  KeInitializeSpinLock(&CancelQueueLock);
+  ExInitializeWorkItem( &CancelQueueWork, CancelQueuePassiveHandler, NULL );
+
   /* Initialize network level protocol subsystem */
   IPStartup(RegistryPath);