Author: cgutman Date: Sat Nov 21 14:00:37 2009 New Revision: 44250
URL: http://svn.reactos.org/svn/reactos?rev=44250&view=rev Log: - Disassociate the socket context before closing so we don't get signalled with a freed context (major cause of crashes) - Signal the connection directly from TCPSocketState - Remove some unused code - Queue completion requests on a separate list so we don't have to keep locking and unlocking while completing - Add better locking to tcpip (not the lib) - Remove some unused variables - Don't hold the cancel spin lock longer than necessary - Check that we successfully got the device description
Modified: trunk/reactos/drivers/network/tcpip/datalink/lan.c trunk/reactos/drivers/network/tcpip/include/tcp.h trunk/reactos/drivers/network/tcpip/include/titypes.h trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c trunk/reactos/drivers/network/tcpip/tcpip/main.c trunk/reactos/lib/drivers/ip/network/ip.c trunk/reactos/lib/drivers/ip/transport/tcp/event.c trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c
Modified: trunk/reactos/drivers/network/tcpip/datalink/lan.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/datal... ============================================================================== --- trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -991,6 +991,11 @@ GetName( RegistryPath, &IF->Name );
Status = FindDeviceDescForAdapter( &IF->Name, &IF->Description ); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Failed to get device description.\n")); + IPDestroyInterface(IF); + return FALSE; + }
TI_DbgPrint(DEBUG_DATALINK,("Adapter Description: %wZ\n", &IF->Description));
Modified: trunk/reactos/drivers/network/tcpip/include/tcp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/inclu... ============================================================================== --- trunk/reactos/drivers/network/tcpip/include/tcp.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/include/tcp.h [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -59,6 +59,11 @@ KEVENT Event; } SLEEPING_THREAD, *PSLEEPING_THREAD;
+typedef struct _CLIENT_DATA { + BOOLEAN Unlocked; + KSPIN_LOCK Lock; +} CLIENT_DATA, *PCLIENT_DATA; + /* Retransmission timeout constants */
/* Lower bound for retransmission timeout in TCP timer ticks */ @@ -84,6 +89,7 @@ #define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification; +extern CLIENT_DATA ClientInfo;
/* accept.c */ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, @@ -105,6 +111,8 @@
NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection, UINT Family, UINT Type, UINT Proto ); + +VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection);
PTCP_SEGMENT TCPCreateSegment( PIP_PACKET IPPacket, @@ -156,8 +164,6 @@
NTSTATUS TCPTranslateError( int OskitError );
-VOID TCPTimeout(); - UINT TCPAllocatePort( UINT HintPort );
VOID TCPFreePort( UINT Port );
Modified: trunk/reactos/drivers/network/tcpip/include/titypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/inclu... ============================================================================== --- trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -263,6 +263,8 @@ LIST_ENTRY Entry; struct _CONNECTION_ENDPOINT *AssociatedEndpoint; TDI_REQUEST Request; + NTSTATUS Status; + ULONG Information; } TDI_BUCKET, *PTDI_BUCKET;
/* Transport connection context structure A.K.A. Transmission Control Block @@ -280,6 +282,7 @@ LIST_ENTRY ListenRequest; /* Queued listen requests */ LIST_ENTRY ReceiveRequest; /* Queued receive requests */ LIST_ENTRY SendRequest; /* Queued send requests */ + LIST_ENTRY CompletionQueue;/* Completed requests to finish */
/* Signals */ UINT SignalState; /* Active signals from oskit */
Modified: trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip... ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/ainfo.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -13,6 +13,8 @@ PVOID Buffer, UINT BufferSize) { + //KIRQL OldIrql; + switch (ID->toi_id) { #if 0 @@ -20,7 +22,10 @@ if (BufferSize < sizeof(UCHAR)) return TDI_INVALID_PARAMETER;
+ KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); AddrFile->TTL = *((PUCHAR)Buffer); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + return TDI_SUCCESS; #endif default:
Modified: trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip... ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -72,7 +72,6 @@ { PIRP Irp; PIO_STACK_LOCATION IrpSp; - PTRANSPORT_CONTEXT TranContext; KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n", @@ -80,7 +79,6 @@
Irp = Context; IrpSp = IoGetCurrentIrpStackLocation(Irp); - TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
IoAcquireCancelSpinLock(&OldIrql);
@@ -116,6 +114,8 @@ PTRANSPORT_CONTEXT TranContext; PFILE_OBJECT FileObject; UCHAR MinorFunction; + + IoReleaseCancelSpinLock(Irp->CancelIrql);
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -168,7 +168,6 @@ break; }
- IoReleaseCancelSpinLock(Irp->CancelIrql); IRPFinish(Irp, STATUS_CANCELLED);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); @@ -191,6 +190,8 @@ PCONNECTION_ENDPOINT Connection; /*NTSTATUS Status = STATUS_SUCCESS;*/
+ IoReleaseCancelSpinLock(Irp->CancelIrql); + TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -212,8 +213,6 @@
TCPAbortListenForSocket(Connection->AddressFile->Listener, Connection); - - IoReleaseCancelSpinLock(Irp->CancelIrql);
Irp->IoStatus.Information = 0; IRPFinish(Irp, STATUS_CANCELLED); @@ -255,6 +254,7 @@ PFILE_OBJECT FileObject; PADDRESS_FILE AddrFile = NULL; NTSTATUS Status; + KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -271,11 +271,6 @@ Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; if (!Connection) { TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); - return STATUS_INVALID_PARAMETER; - } - - if (Connection->AddressFile) { - TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n")); return STATUS_INVALID_PARAMETER; }
@@ -294,8 +289,18 @@ return STATUS_INVALID_PARAMETER; }
+ KeAcquireSpinLock(&Connection->Lock, &OldIrql); + + if (Connection->AddressFile) { + ObDereferenceObject(FileObject); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n")); + return STATUS_INVALID_PARAMETER; + } + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { ObDereferenceObject(FileObject); + KeReleaseSpinLock(&Connection->Lock, OldIrql); TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n", FileObject->FsContext2)); return STATUS_INVALID_PARAMETER; @@ -306,17 +311,21 @@ TranContext = FileObject->FsContext; if (!TranContext) { ObDereferenceObject(FileObject); + KeReleaseSpinLock(&Connection->Lock, OldIrql); TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); return STATUS_INVALID_PARAMETER; }
AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; if (!AddrFile) { + KeReleaseSpinLock(&Connection->Lock, OldIrql); ObDereferenceObject(FileObject); TI_DbgPrint(MID_TRACE, ("No address file object.\n")); return STATUS_INVALID_PARAMETER; }
+ KeAcquireSpinLockAtDpcLevel(&AddrFile->Lock); + Connection->AddressFile = AddrFile;
/* Add connection endpoint to the address file */ @@ -324,6 +333,9 @@
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */ ObDereferenceObject(FileObject); + + KeReleaseSpinLockFromDpcLevel(&AddrFile->Lock); + KeReleaseSpinLock(&Connection->Lock, OldIrql);
return Status; } @@ -405,6 +417,7 @@ PCONNECTION_ENDPOINT Connection; PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; + KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -424,16 +437,25 @@ return STATUS_INVALID_PARAMETER; }
+ KeAcquireSpinLock(&Connection->Lock, &OldIrql); + if (!Connection->AddressFile) { + KeReleaseSpinLock(&Connection->Lock, OldIrql); TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n")); return STATUS_INVALID_PARAMETER; }
+ KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock); + /* Remove this connection from the address file */ Connection->AddressFile->Connection = NULL;
+ KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock); + /* Remove the address file from this connection */ Connection->AddressFile = NULL; + + KeReleaseSpinLock(&Connection->Lock, OldIrql);
return STATUS_SUCCESS; } @@ -511,6 +533,7 @@ PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; + KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -536,14 +559,22 @@
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
- TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n", - Connection->AddressFile )); - ASSERT(Connection->AddressFile); - Status = DispPrepareIrpForCancel (TranContext->Handle.ConnectionContext, Irp, (PDRIVER_CANCEL)DispCancelListenRequest); + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + + if (Connection->AddressFile == NULL) + { + TI_DbgPrint(MID_TRACE, ("No associated address file\n")); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + Status = STATUS_INVALID_PARAMETER; + goto done; + } + + KeAcquireSpinLockAtDpcLevel(&Connection->AddressFile->Lock);
/* Listening will require us to create a listening socket and store it in * the address file. It will be signalled, and attempt to complete an irp @@ -580,6 +611,9 @@ DispDataRequestComplete, Irp ); } + + KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock); + KeReleaseSpinLock(&Connection->Lock, OldIrql);
done: if (Status != STATUS_PENDING) { @@ -657,12 +691,10 @@ case TDI_CONNECTION_FILE: Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; - TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE ); - DbgPrint("Returning socket address %x\n", Address->Address[0].Address[0].in_addr); RtlZeroMemory( &Address->Address[0].Address[0].sin_zero, sizeof(Address->Address[0].Address[0].sin_zero)); - return STATUS_SUCCESS; + return TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
default: TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); @@ -990,8 +1022,10 @@ DataBuffer, BufferSize, &Irp->IoStatus.Information); - else + else { Status = STATUS_UNSUCCESSFUL; + ASSERT(FALSE); + } }
done: @@ -1199,11 +1233,10 @@ */ { PTI_QUERY_CONTEXT QueryContext; - UINT Count = 0;
QueryContext = (PTI_QUERY_CONTEXT)Context; if (NT_SUCCESS(Status)) { - Count = CopyBufferToBufferChain( + CopyBufferToBufferChain( QueryContext->InputMdl, FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context), (PCHAR)&QueryContext->QueryInfo.Context,
Modified: trunk/reactos/drivers/network/tcpip/tcpip/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip... ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/main.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/main.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -322,7 +322,6 @@ { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; - PTRANSPORT_CONTEXT Context;
IRPRemember(Irp, __FILE__, __LINE__);
@@ -338,8 +337,7 @@
/* Close an address file, connection endpoint, or control connection */ case IRP_MJ_CLOSE: - Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; - Status = TiCloseFileObject(DeviceObject, Irp); + Status = TiCloseFileObject(DeviceObject, Irp); break;
default:
Modified: trunk/reactos/lib/drivers/ip/network/ip.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/ip.c... ============================================================================== --- trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -73,9 +73,6 @@
/* Clean possible outdated cached neighbor addresses */ NBTimeout(); - - /* Call upper layer timeout routines */ - TCPTimeout(); }
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/event.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/event.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -29,7 +29,8 @@ return 0; }
- KeAcquireSpinLockAtDpcLevel(&Connection->Lock); + if (ClientInfo.Unlocked) + KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n", NewState, Connection, @@ -38,7 +39,10 @@
Connection->SignalState |= NewState;
- KeReleaseSpinLockFromDpcLevel(&Connection->Lock); + HandleSignalledConnection(Connection); + + if (ClientInfo.Unlocked) + KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
return 0; }
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -16,38 +16,44 @@ static BOOLEAN TCPInitialized = FALSE; static NPAGED_LOOKASIDE_LIST TCPSegmentList; PORT_SET TCPPorts; - -static VOID DrainSignals() { - PCONNECTION_ENDPOINT Connection; - PLIST_ENTRY CurrentEntry, NextEntry; - KIRQL OldIrql; - NTSTATUS Status = STATUS_SUCCESS; +CLIENT_DATA ClientInfo; + +static VOID +ProcessCompletions(PCONNECTION_ENDPOINT Connection) +{ + PLIST_ENTRY CurrentEntry; + PTDI_BUCKET Bucket; PTCP_COMPLETION_ROUTINE Complete; - PTDI_BUCKET Bucket; - PLIST_ENTRY Entry; - PIRP Irp; - PMDL Mdl; - ULONG SocketError; - - KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); - CurrentEntry = ConnectionEndpointListHead.Flink; - while (CurrentEntry != &ConnectionEndpointListHead) + + while ((CurrentEntry = ExInterlockedRemoveHeadList(&Connection->CompletionQueue, + &Connection->Lock))) { - NextEntry = CurrentEntry->Flink; - KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); - - Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT, - ListEntry ); - - KeAcquireSpinLock(&Connection->Lock, &OldIrql); + Bucket = CONTAINING_RECORD(CurrentEntry, TDI_BUCKET, Entry); + Complete = Bucket->Request.RequestNotifyObject; + + Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); + + exFreePool(Bucket); + } + + if (!Connection->SocketContext) + TCPFreeConnectionEndpoint(Connection); +} + +VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection) +{ + PTDI_BUCKET Bucket; + PLIST_ENTRY Entry; + NTSTATUS Status; + PIRP Irp; + PMDL Mdl; + ULONG SocketError;
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n", Connection, Connection->SocketContext));
if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) { TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n")); - - Connection->SignalState = 0;
/* If OskitTCP initiated the disconnect, try to read the socket error that occurred */ if (Connection->SocketContext) @@ -57,140 +63,124 @@ if (!Connection->SocketContext || !SocketError) SocketError = STATUS_CANCELLED;
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - - while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest, - &Connection->Lock )) != NULL) + while (!IsListEmpty(&Connection->ReceiveRequest)) { + Entry = RemoveHeadList( &Connection->ReceiveRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - - Complete( Bucket->Request.RequestContext, SocketError, 0 ); - - exFreePool(Bucket); + + Bucket->Status = SocketError; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); }
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest, - &Connection->Lock )) != NULL) + while (!IsListEmpty(&Connection->SendRequest)) { + Entry = RemoveHeadList( &Connection->SendRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - - Complete( Bucket->Request.RequestContext, SocketError, 0 ); - - exFreePool(Bucket); + + Bucket->Status = SocketError; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); }
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest, - &Connection->Lock )) != NULL) + while (!IsListEmpty(&Connection->ListenRequest)) { + Entry = RemoveHeadList( &Connection->ListenRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - - Complete( Bucket->Request.RequestContext, SocketError, 0 ); - - exFreePool(Bucket); + + Bucket->Status = SocketError; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); }
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest, - &Connection->Lock )) != NULL) + while (!IsListEmpty(&Connection->ConnectRequest)) { + Entry = RemoveHeadList( &Connection->ConnectRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - - Complete( Bucket->Request.RequestContext, SocketError, 0 ); - - exFreePool(Bucket); + + Bucket->Status = SocketError; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); }
- KeAcquireSpinLock(&Connection->Lock, &OldIrql); + Connection->SignalState = 0; }
/* Things that can happen when we try the initial connection */ if( Connection->SignalState & SEL_CONNECT ) { - KeReleaseSpinLock(&Connection->Lock, OldIrql); - while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest, - &Connection->Lock )) != NULL ) { - - TI_DbgPrint(DEBUG_TCP, ("Connect Event\n")); + while (!IsListEmpty(&Connection->ConnectRequest)) { + Entry = RemoveHeadList( &Connection->ConnectRequest );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - TI_DbgPrint(DEBUG_TCP, - ("Completing Request %x\n", Bucket->Request.RequestContext)); - - Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 ); - - /* Frees the bucket allocated in TCPConnect */ - exFreePool( Bucket ); + + Bucket->Status = STATUS_SUCCESS; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); } - KeAcquireSpinLock(&Connection->Lock, &OldIrql); }
if( Connection->SignalState & SEL_ACCEPT ) { /* Handle readable on a listening socket -- * TODO: Implement filtering */ - - KeReleaseSpinLock(&Connection->Lock, OldIrql); - TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n", Connection, IsListEmpty(&Connection->ListenRequest) ? "empty" : "nonempty"));
- while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest, - &Connection->Lock )) != NULL ) { + while (!IsListEmpty(&Connection->ListenRequest)) { PIO_STACK_LOCATION IrpSp;
+ Entry = RemoveHeadList( &Connection->ListenRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext; IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n")); - - KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPServiceListeningSocket ( Connection->AddressFile->Listener, Bucket->AssociatedEndpoint, (PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) { - ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry, - &Connection->Lock ); + InsertHeadList( &Connection->ListenRequest, &Bucket->Entry ); break; } else { - Complete( Bucket->Request.RequestContext, Status, 0 ); - exFreePool( Bucket ); + Bucket->Status = Status; + Bucket->Information = 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); } } - - KeAcquireSpinLock(&Connection->Lock, &OldIrql); }
/* Things that happen after we're connected */ - if( Connection->SignalState & SEL_READ && - Connection->SignalState & SEL_CONNECT ) { + if( Connection->SignalState & SEL_READ ) { TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n", IsListEmpty(&Connection->ReceiveRequest) ? "empty" : "nonempty"));
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - - while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest, - &Connection->Lock )) != NULL ) { + while (!IsListEmpty(&Connection->ReceiveRequest)) { OSK_UINT RecvLen = 0, Received = 0; PVOID RecvBuffer = 0;
+ Entry = RemoveHeadList( &Connection->ReceiveRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext; Mdl = Irp->MdlAddress; @@ -210,8 +200,6 @@ Connection->SocketContext)); TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
- KeAcquireSpinLock(&Connection->Lock, &OldIrql); - Status = TCPTranslateError ( OskitTCPRecv( Connection->SocketContext, RecvBuffer, @@ -219,46 +207,35 @@ &Received, 0 ) );
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
- if( Status == STATUS_SUCCESS ) { - TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n", - Received, Status)); - Complete( Bucket->Request.RequestContext, - STATUS_SUCCESS, Received ); - exFreePool( Bucket ); - } else if( Status == STATUS_PENDING ) { - ExInterlockedInsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry, - &Connection->Lock ); + if( Status == STATUS_PENDING ) { + InsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry ); break; } else { TI_DbgPrint(DEBUG_TCP, ("Completing Receive request: %x %x\n", Bucket->Request, Status)); - Complete( Bucket->Request.RequestContext, Status, 0 ); - exFreePool( Bucket ); + + Bucket->Status = Status; + Bucket->Information = (Status == STATUS_SUCCESS) ? Received : 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); } } - - KeAcquireSpinLock(&Connection->Lock, &OldIrql); } - if( Connection->SignalState & SEL_WRITE && - Connection->SignalState & SEL_CONNECT ) { + if( Connection->SignalState & SEL_WRITE ) { TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n", IsListEmpty(&Connection->SendRequest) ? "empty" : "nonempty"));
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - - while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest, - &Connection->Lock )) != NULL ) { + while (!IsListEmpty(&Connection->SendRequest)) { OSK_UINT SendLen = 0, Sent = 0; PVOID SendBuffer = 0;
+ Entry = RemoveHeadList( &Connection->SendRequest ); + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext; Mdl = Irp->MdlAddress; @@ -276,8 +253,6 @@ (DEBUG_TCP, ("Connection->SocketContext: %x\n", Connection->SocketContext)); - - KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError ( OskitTCPSend( Connection->SocketContext, @@ -286,43 +261,55 @@ &Sent, 0 ) );
- KeReleaseSpinLock(&Connection->Lock, OldIrql); - TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
- if( Status == STATUS_SUCCESS ) { - TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n", - Sent, Status)); - Complete( Bucket->Request.RequestContext, - STATUS_SUCCESS, Sent ); - exFreePool( Bucket ); - } else if( Status == STATUS_PENDING ) { - ExInterlockedInsertHeadList( &Connection->SendRequest, &Bucket->Entry, - &Connection->Lock ); + if( Status == STATUS_PENDING ) { + InsertHeadList( &Connection->SendRequest, &Bucket->Entry ); break; } else { TI_DbgPrint(DEBUG_TCP, ("Completing Send request: %x %x\n", Bucket->Request, Status)); - Complete( Bucket->Request.RequestContext, Status, 0 ); - exFreePool( Bucket ); + + Bucket->Status = Status; + Bucket->Information = (Status == STATUS_SUCCESS) ? Sent : 0; + + InsertTailList(&Connection->CompletionQueue, &Bucket->Entry); } } - KeAcquireSpinLock(&Connection->Lock, &OldIrql); } - - KeReleaseSpinLock(&Connection->Lock, OldIrql); - - if (!Connection->SocketContext) - { - TCPFreeConnectionEndpoint(Connection); - } - - CurrentEntry = NextEntry; - - KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); - } - +} + +static +VOID DrainSignals(VOID) { + PCONNECTION_ENDPOINT Connection; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); + CurrentEntry = ConnectionEndpointListHead.Flink; + while (CurrentEntry != &ConnectionEndpointListHead) + { + Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT, + ListEntry ); + CurrentEntry = CurrentEntry->Flink; + KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + if (Connection->SocketContext) + { + HandleSignalledConnection(Connection); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + + ProcessCompletions(Connection); + } + else + { + KeReleaseSpinLock(&Connection->Lock, OldIrql); + } + + KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); + } KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); }
@@ -342,6 +329,7 @@ InitializeListHead(&Connection->ListenRequest); InitializeListHead(&Connection->ReceiveRequest); InitializeListHead(&Connection->SendRequest); + InitializeListHead(&Connection->CompletionQueue);
/* Save client context pointer */ Connection->ClientContext = ClientContext; @@ -402,13 +390,21 @@ * This is the low level interface for receiving TCP data */ { + KIRQL OldIrql; + TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to oskit\n", IPPacket->TotalSize, IPPacket->HeaderSize));
+ KeAcquireSpinLock(&ClientInfo.Lock, &OldIrql); + ClientInfo.Unlocked = TRUE; + OskitTCPReceiveDatagram( IPPacket->Header, IPPacket->TotalSize, IPPacket->HeaderSize ); + + ClientInfo.Unlocked = FALSE; + KeReleaseSpinLock(&ClientInfo.Lock, OldIrql); }
/* event.c */ @@ -467,7 +463,7 @@ while ( 1 ) { if (Next == NextFast) { NextFast += 2; - } + } if (Next == NextSlow) { NextSlow += 5; } @@ -480,9 +476,7 @@ }
TimerOskitTCP( Next == NextFast, Next == NextSlow ); - if (Next == NextSlow) { - DrainSignals(); - } + DrainSignals();
Current = Next; if (10 <= Current) { @@ -501,7 +495,6 @@ PsCreateSystemThread(&TimerThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, TimerThread, NULL); } -
NTSTATUS TCPStartup(VOID) /* @@ -522,6 +515,9 @@ TCPMemShutdown(); return Status; } + + KeInitializeSpinLock(&ClientInfo.Lock); + ClientInfo.Unlocked = FALSE;
RegisterOskitTCPEventHandlers( &EventHandlers ); InitOskitTCP(); @@ -862,10 +858,6 @@ return Status; }
-VOID TCPTimeout(VOID) { - /* Now handled by TimerThread */ -} - UINT TCPAllocatePort( UINT HintPort ) { if( HintPort ) { if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort;
Modified: trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/oskittcp/oskitt... ============================================================================== --- trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/oskittcp/oskittcp/interface.c [iso-8859-1] Sat Nov 21 14:00:37 2009 @@ -285,11 +285,16 @@
int OskitTCPClose( void *socket ) { int error; - - if (!socket) - return OSK_ESHUTDOWN; - - OSKLock(); + struct socket *so = socket; + + if (!socket) + return OSK_ESHUTDOWN; + + OSKLock(); + /* We have to remove the socket context here otherwise we end up + * back in HandleSignalledConnection with a freed connection context + */ + so->so_connection = NULL; error = soclose( socket ); OSKUnlock();
@@ -435,16 +440,12 @@ OSK_UINT IpHeaderLen ) { struct mbuf *Ip; struct ip *iph; - KIRQL OldIrql; - - /* This function is a special case in which we cannot use OSKLock/OSKUnlock - * because we don't enter with the connection lock held */ - - OSKLockAndRaise(&OldIrql); + + OSKLock(); Ip = m_devget( (char *)Data, Len, 0, NULL, NULL ); if( !Ip ) { - OSKUnlockAndLower(OldIrql); + OSKUnlock(); return; /* drop the segment */ }
@@ -461,7 +462,7 @@ IpHeaderLen));
tcp_input(Ip, IpHeaderLen); - OSKUnlockAndLower(OldIrql); + OSKUnlock();
/* The buffer Ip is freed by tcp_input */ }