From f7fc8ee97d5f0146c77147df3331fe8a94f53b52 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Wed, 7 Dec 2005 08:50:27 +0000 Subject: [PATCH] Fix firefox exit. Implement a simple work queue for possibly dispatch level callbacks for cancel and close. svn path=/trunk/; revision=19943 --- reactos/drivers/lib/ip/network/receive.c | 13 +++- reactos/drivers/lib/ip/transport/tcp/tcp.c | 4 + reactos/drivers/net/tcpip/include/tcp.h | 13 ++++ reactos/drivers/net/tcpip/include/tcpip.h | 3 + reactos/drivers/net/tcpip/include/titypes.h | 2 + reactos/drivers/net/tcpip/tcpip/dispatch.c | 82 +++++++++++++++++---- reactos/drivers/net/tcpip/tcpip/fileobjs.c | 26 +++++-- reactos/drivers/net/tcpip/tcpip/main.c | 13 +++- 8 files changed, 131 insertions(+), 25 deletions(-) diff --git a/reactos/drivers/lib/ip/network/receive.c b/reactos/drivers/lib/ip/network/receive.c index d6c05872e81..f53a2e0e45b 100644 --- a/reactos/drivers/lib/ip/network/receive.c +++ b/reactos/drivers/lib/ip/network/receive.c @@ -521,6 +521,8 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket) * 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 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket) /* 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, diff --git a/reactos/drivers/lib/ip/transport/tcp/tcp.c b/reactos/drivers/lib/ip/transport/tcp/tcp.c index fcaa415b42d..205e8253d27 100644 --- a/reactos/drivers/lib/ip/transport/tcp/tcp.c +++ b/reactos/drivers/lib/ip/transport/tcp/tcp.c @@ -647,4 +647,8 @@ NTSTATUS TCPGetPeerAddress return STATUS_SUCCESS; } +void TCPMarkForDisconnect( PCONNECTION_ENDPOINT Context, BOOLEAN Marked ) { + Context->Disconnecting = Marked; +} + /* EOF */ diff --git a/reactos/drivers/net/tcpip/include/tcp.h b/reactos/drivers/net/tcpip/include/tcp.h index f56937bb2da..56c721601c2 100644 --- a/reactos/drivers/net/tcpip/include/tcp.h +++ b/reactos/drivers/net/tcpip/include/tcp.h @@ -38,6 +38,9 @@ typedef struct TCPv4_HEADER { #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 @@ typedef struct _SLEEPING_THREAD { 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 TCPStartup( NTSTATUS TCPShutdown( VOID); +void TCPMarkForDisconnect( + PCONNECTION_ENDPOINT Connection, BOOLEAN Marked ); + #endif /* __TCP_H */ diff --git a/reactos/drivers/net/tcpip/include/tcpip.h b/reactos/drivers/net/tcpip/include/tcpip.h index 8e4740bd7db..8a5638563f5 100644 --- a/reactos/drivers/net/tcpip/include/tcpip.h +++ b/reactos/drivers/net/tcpip/include/tcpip.h @@ -188,6 +188,9 @@ extern LIST_ENTRY InterfaceListHead; 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; diff --git a/reactos/drivers/net/tcpip/include/titypes.h b/reactos/drivers/net/tcpip/include/titypes.h index 52f0a5fa0d1..c75586de4a6 100644 --- a/reactos/drivers/net/tcpip/include/titypes.h +++ b/reactos/drivers/net/tcpip/include/titypes.h @@ -308,6 +308,8 @@ typedef struct _CONNECTION_ENDPOINT { * 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; diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index 20204f35f81..c3fe3c6a13f 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -12,6 +12,8 @@ #include "precomp.h" #include +extern VOID DeleteConnectionEndpoint( PCONNECTION_ENDPOINT Endpoint ); + NTSTATUS DispPrepareIrpForCancel( PTRANSPORT_CONTEXT Context, PIRP Irp, @@ -135,6 +137,55 @@ VOID DispDataRequestComplete( 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, @@ -150,6 +201,7 @@ VOID DDKAPI DispCancelRequest( 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 @@ VOID DDKAPI DispCancelRequest( /* 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: diff --git a/reactos/drivers/net/tcpip/tcpip/fileobjs.c b/reactos/drivers/net/tcpip/tcpip/fileobjs.c index 546df6f782d..1f6bcc023d4 100644 --- a/reactos/drivers/net/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/net/tcpip/tcpip/fileobjs.c @@ -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 @@ NTSTATUS FileCloseAddress( KIRQL OldIrql; PADDRESS_FILE AddrFile; NTSTATUS Status = STATUS_SUCCESS; + PCANCEL_REQUEST CancelReq; TI_DbgPrint(MID_TRACE, ("Called.\n")); @@ -369,8 +369,16 @@ NTSTATUS FileCloseAddress( 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 @@ NTSTATUS FileCloseConnection( { 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")); diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index b6e7c32d50e..4ce086e7c97 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -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 @@ KDPC IPTimeoutDpc; 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 @@ DriverEntry( InitializeListHead(&InterfaceListHead); KeInitializeSpinLock(&InterfaceListLock); + /* Initialize cancellation queue */ + InitializeListHead(&CancelQueue); + KeInitializeSpinLock(&CancelQueueLock); + ExInitializeWorkItem( &CancelQueueWork, CancelQueuePassiveHandler, NULL ); + /* Initialize network level protocol subsystem */ IPStartup(RegistryPath);