diff --git a/reactos/drivers/network/tcpip/datalink/lan.c b/reactos/drivers/network/tcpip/datalink/lan.c index fef1690dfa2..21601630fdd 100644 --- a/reactos/drivers/network/tcpip/datalink/lan.c +++ b/reactos/drivers/network/tcpip/datalink/lan.c @@ -991,6 +991,11 @@ BOOLEAN BindAdapter( 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)); diff --git a/reactos/drivers/network/tcpip/include/tcp.h b/reactos/drivers/network/tcpip/include/tcp.h index 32c3ec907e7..b18fecdd295 100644 --- a/reactos/drivers/network/tcpip/include/tcp.h +++ b/reactos/drivers/network/tcpip/include/tcp.h @@ -59,6 +59,11 @@ typedef struct _SLEEPING_THREAD { 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 @@ typedef struct _SLEEPING_THREAD { #define SRF_FIN TCP_FIN extern LONG TCP_IPIdentification; +extern CLIENT_DATA ClientInfo; /* accept.c */ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, @@ -106,6 +112,8 @@ VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ); NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection, UINT Family, UINT Type, UINT Proto ); +VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection); + PTCP_SEGMENT TCPCreateSegment( PIP_PACKET IPPacket, PTCPv4_HEADER TCPHeader, @@ -156,8 +164,6 @@ NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection ); NTSTATUS TCPTranslateError( int OskitError ); -VOID TCPTimeout(); - UINT TCPAllocatePort( UINT HintPort ); VOID TCPFreePort( UINT Port ); diff --git a/reactos/drivers/network/tcpip/include/titypes.h b/reactos/drivers/network/tcpip/include/titypes.h index 9ac9561e0bb..88a02bb15e5 100644 --- a/reactos/drivers/network/tcpip/include/titypes.h +++ b/reactos/drivers/network/tcpip/include/titypes.h @@ -263,6 +263,8 @@ typedef struct _TDI_BUCKET { 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 @@ typedef struct _CONNECTION_ENDPOINT { 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 */ diff --git a/reactos/drivers/network/tcpip/tcpip/ainfo.c b/reactos/drivers/network/tcpip/tcpip/ainfo.c index a3ea2e8889c..0c1b11e717f 100644 --- a/reactos/drivers/network/tcpip/tcpip/ainfo.c +++ b/reactos/drivers/network/tcpip/tcpip/ainfo.c @@ -13,6 +13,8 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, PVOID Buffer, UINT BufferSize) { + //KIRQL OldIrql; + switch (ID->toi_id) { #if 0 @@ -20,7 +22,10 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID, 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: diff --git a/reactos/drivers/network/tcpip/tcpip/dispatch.c b/reactos/drivers/network/tcpip/tcpip/dispatch.c index 49de2fd9090..d08ef8aecfa 100644 --- a/reactos/drivers/network/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/network/tcpip/tcpip/dispatch.c @@ -72,7 +72,6 @@ VOID DispDataRequestComplete( { 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 @@ VOID DispDataRequestComplete( Irp = Context; IrpSp = IoGetCurrentIrpStackLocation(Irp); - TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; IoAcquireCancelSpinLock(&OldIrql); @@ -117,6 +115,8 @@ VOID NTAPI DispCancelRequest( PFILE_OBJECT FileObject; UCHAR MinorFunction; + IoReleaseCancelSpinLock(Irp->CancelIrql); + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -168,7 +168,6 @@ VOID NTAPI DispCancelRequest( break; } - IoReleaseCancelSpinLock(Irp->CancelIrql); IRPFinish(Irp, STATUS_CANCELLED); TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); @@ -191,6 +190,8 @@ VOID NTAPI DispCancelListenRequest( PCONNECTION_ENDPOINT Connection; /*NTSTATUS Status = STATUS_SUCCESS;*/ + IoReleaseCancelSpinLock(Irp->CancelIrql); + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -213,8 +214,6 @@ VOID NTAPI DispCancelListenRequest( TCPAbortListenForSocket(Connection->AddressFile->Listener, Connection); - IoReleaseCancelSpinLock(Irp->CancelIrql); - Irp->IoStatus.Information = 0; IRPFinish(Irp, STATUS_CANCELLED); @@ -255,6 +254,7 @@ NTSTATUS DispTdiAssociateAddress( PFILE_OBJECT FileObject; PADDRESS_FILE AddrFile = NULL; NTSTATUS Status; + KIRQL OldIrql; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -274,11 +274,6 @@ NTSTATUS DispTdiAssociateAddress( return STATUS_INVALID_PARAMETER; } - if (Connection->AddressFile) { - TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n")); - return STATUS_INVALID_PARAMETER; - } - Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters; Status = ObReferenceObjectByHandle( @@ -294,8 +289,18 @@ NTSTATUS DispTdiAssociateAddress( 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 @@ NTSTATUS DispTdiAssociateAddress( 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 */ @@ -325,6 +334,9 @@ NTSTATUS DispTdiAssociateAddress( /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */ ObDereferenceObject(FileObject); + KeReleaseSpinLockFromDpcLevel(&AddrFile->Lock); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + return Status; } @@ -405,6 +417,7 @@ NTSTATUS DispTdiDisassociateAddress( PCONNECTION_ENDPOINT Connection; PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; + KIRQL OldIrql; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -424,17 +437,26 @@ NTSTATUS DispTdiDisassociateAddress( 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 @@ NTSTATUS DispTdiListen( PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; + KIRQL OldIrql; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -536,15 +559,23 @@ NTSTATUS DispTdiListen( 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 * when a new connection arrives. */ @@ -581,6 +612,9 @@ NTSTATUS DispTdiListen( Irp ); } + KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + done: if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, 0); @@ -657,12 +691,10 @@ NTSTATUS DispTdiQueryInformation( 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 @@ NTSTATUS DispTdiSendDatagram( DataBuffer, BufferSize, &Irp->IoStatus.Information); - else + else { Status = STATUS_UNSUCCESSFUL; + ASSERT(FALSE); + } } done: @@ -1199,11 +1233,10 @@ VOID DispTdiQueryInformationExComplete( */ { 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, diff --git a/reactos/drivers/network/tcpip/tcpip/main.c b/reactos/drivers/network/tcpip/tcpip/main.c index f8aa2225bde..7e45cccba5a 100644 --- a/reactos/drivers/network/tcpip/tcpip/main.c +++ b/reactos/drivers/network/tcpip/tcpip/main.c @@ -322,7 +322,6 @@ TiDispatchOpenClose( { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; - PTRANSPORT_CONTEXT Context; IRPRemember(Irp, __FILE__, __LINE__); @@ -338,8 +337,7 @@ TiDispatchOpenClose( /* 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: diff --git a/reactos/lib/drivers/ip/network/ip.c b/reactos/lib/drivers/ip/network/ip.c index f13dd614e8c..9709ce4cee6 100644 --- a/reactos/lib/drivers/ip/network/ip.c +++ b/reactos/lib/drivers/ip/network/ip.c @@ -73,9 +73,6 @@ void NTAPI IPTimeout( PVOID Context ) { /* Clean possible outdated cached neighbor addresses */ NBTimeout(); - - /* Call upper layer timeout routines */ - TCPTimeout(); } diff --git a/reactos/lib/drivers/ip/transport/tcp/event.c b/reactos/lib/drivers/ip/transport/tcp/event.c index a4b2275b511..6d062dceb8b 100644 --- a/reactos/lib/drivers/ip/transport/tcp/event.c +++ b/reactos/lib/drivers/ip/transport/tcp/event.c @@ -29,7 +29,8 @@ int TCPSocketState(void *ClientData, 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 @@ int TCPSocketState(void *ClientData, Connection->SignalState |= NewState; - KeReleaseSpinLockFromDpcLevel(&Connection->Lock); + HandleSignalledConnection(Connection); + + if (ClientInfo.Unlocked) + KeReleaseSpinLockFromDpcLevel(&Connection->Lock); return 0; } diff --git a/reactos/lib/drivers/ip/transport/tcp/tcp.c b/reactos/lib/drivers/ip/transport/tcp/tcp.c index 25c8d4d8657..6f9f38c87a0 100644 --- a/reactos/lib/drivers/ip/transport/tcp/tcp.c +++ b/reactos/lib/drivers/ip/transport/tcp/tcp.c @@ -16,30 +16,38 @@ LONG TCP_IPIdentification = 0; static BOOLEAN TCPInitialized = FALSE; static NPAGED_LOOKASIDE_LIST TCPSegmentList; PORT_SET TCPPorts; +CLIENT_DATA ClientInfo; -static VOID DrainSignals() { - PCONNECTION_ENDPOINT Connection; - PLIST_ENTRY CurrentEntry, NextEntry; - KIRQL OldIrql; - NTSTATUS Status = STATUS_SUCCESS; - PTCP_COMPLETION_ROUTINE Complete; +static VOID +ProcessCompletions(PCONNECTION_ENDPOINT Connection) +{ + PLIST_ENTRY CurrentEntry; PTDI_BUCKET Bucket; - PLIST_ENTRY Entry; - PIRP Irp; - PMDL Mdl; - ULONG SocketError; + PTCP_COMPLETION_ROUTINE Complete; - KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); - CurrentEntry = ConnectionEndpointListHead.Flink; - while (CurrentEntry != &ConnectionEndpointListHead) + while ((CurrentEntry = ExInterlockedRemoveHeadList(&Connection->CompletionQueue, + &Connection->Lock))) { - NextEntry = CurrentEntry->Flink; - KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); + Bucket = CONTAINING_RECORD(CurrentEntry, TDI_BUCKET, Entry); + Complete = Bucket->Request.RequestNotifyObject; - Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT, - ListEntry ); + Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information); - KeAcquireSpinLock(&Connection->Lock, &OldIrql); + 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)); @@ -47,8 +55,6 @@ static VOID DrainSignals() { 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) SocketError = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); @@ -57,140 +63,124 @@ static VOID DrainSignals() { 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 ); + Bucket->Status = SocketError; + Bucket->Information = 0; - exFreePool(Bucket); + 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 ); + Bucket->Status = SocketError; + Bucket->Information = 0; - exFreePool(Bucket); + 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 ); + Bucket->Status = SocketError; + Bucket->Information = 0; - exFreePool(Bucket); + 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 ); + Bucket->Status = SocketError; + Bucket->Information = 0; - exFreePool(Bucket); + 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 ); + Bucket->Status = STATUS_SUCCESS; + Bucket->Information = 0; - /* Frees the bucket allocated in TCPConnect */ - exFreePool( Bucket ); + 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 @@ static VOID DrainSignals() { Connection->SocketContext)); TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer)); - KeAcquireSpinLock(&Connection->Lock, &OldIrql); - Status = TCPTranslateError ( OskitTCPRecv( Connection->SocketContext, RecvBuffer, @@ -219,46 +207,35 @@ static VOID DrainSignals() { &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; @@ -277,8 +254,6 @@ static VOID DrainSignals() { ("Connection->SocketContext: %x\n", Connection->SocketContext)); - KeAcquireSpinLock(&Connection->Lock, &OldIrql); - Status = TCPTranslateError ( OskitTCPSend( Connection->SocketContext, SendBuffer, @@ -286,43 +261,55 @@ static VOID DrainSignals() { &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); +static +VOID DrainSignals(VOID) { + PCONNECTION_ENDPOINT Connection; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; - if (!Connection->SocketContext) - { - TCPFreeConnectionEndpoint(Connection); - } + KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); + CurrentEntry = ConnectionEndpointListHead.Flink; + while (CurrentEntry != &ConnectionEndpointListHead) + { + Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT, + ListEntry ); + CurrentEntry = CurrentEntry->Flink; + KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); - CurrentEntry = NextEntry; + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + if (Connection->SocketContext) + { + HandleSignalledConnection(Connection); + KeReleaseSpinLock(&Connection->Lock, OldIrql); - KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); + ProcessCompletions(Connection); + } + else + { + KeReleaseSpinLock(&Connection->Lock, OldIrql); + } + + KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); } - KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); } @@ -342,6 +329,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) { InitializeListHead(&Connection->ListenRequest); InitializeListHead(&Connection->ReceiveRequest); InitializeListHead(&Connection->SendRequest); + InitializeListHead(&Connection->CompletionQueue); /* Save client context pointer */ Connection->ClientContext = ClientContext; @@ -402,13 +390,21 @@ VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) * 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 @@ TimerThread(PVOID Context) while ( 1 ) { if (Next == NextFast) { NextFast += 2; - } + } if (Next == NextSlow) { NextSlow += 5; } @@ -480,9 +476,7 @@ TimerThread(PVOID Context) } TimerOskitTCP( Next == NextFast, Next == NextSlow ); - if (Next == NextSlow) { - DrainSignals(); - } + DrainSignals(); Current = Next; if (10 <= Current) { @@ -502,7 +496,6 @@ StartTimer(VOID) TimerThread, NULL); } - NTSTATUS TCPStartup(VOID) /* * FUNCTION: Initializes the TCP subsystem @@ -523,6 +516,9 @@ NTSTATUS TCPStartup(VOID) return Status; } + KeInitializeSpinLock(&ClientInfo.Lock); + ClientInfo.Unlocked = FALSE; + RegisterOskitTCPEventHandlers( &EventHandlers ); InitOskitTCP(); @@ -862,10 +858,6 @@ NTSTATUS TCPSendData return Status; } -VOID TCPTimeout(VOID) { - /* Now handled by TimerThread */ -} - UINT TCPAllocatePort( UINT HintPort ) { if( HintPort ) { if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort; diff --git a/reactos/lib/drivers/oskittcp/oskittcp/interface.c b/reactos/lib/drivers/oskittcp/oskittcp/interface.c index 685e4bffc64..a925d330434 100644 --- a/reactos/lib/drivers/oskittcp/oskittcp/interface.c +++ b/reactos/lib/drivers/oskittcp/oskittcp/interface.c @@ -285,11 +285,16 @@ int OskitTCPShutdown( void *socket, int disconn_type ) { int OskitTCPClose( void *socket ) { int error; + 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 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len, 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 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len, IpHeaderLen)); tcp_input(Ip, IpHeaderLen); - OSKUnlockAndLower(OldIrql); + OSKUnlock(); /* The buffer Ip is freed by tcp_input */ }