From: Cameron Gutman Date: Sat, 14 Nov 2009 18:38:02 +0000 (+0000) Subject: - Use a spin lock to protect OSKit instead of a recursive mutex X-Git-Tag: ReactOS-0.3.11~54 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=f3d4211e560f5d8059339a6b3af9ccf75d1f3766 - Use a spin lock to protect OSKit instead of a recursive mutex - 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 --- diff --git a/reactos/drivers/network/tcpip/include/fileobjs.h b/reactos/drivers/network/tcpip/include/fileobjs.h index bff07a64b40..12327701db8 100644 --- a/reactos/drivers/network/tcpip/include/fileobjs.h +++ b/reactos/drivers/network/tcpip/include/fileobjs.h @@ -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); diff --git a/reactos/drivers/network/tcpip/include/tcp.h b/reactos/drivers/network/tcpip/include/tcp.h index e80d17f2500..32c3ec907e7 100644 --- a/reactos/drivers/network/tcpip/include/tcp.h +++ b/reactos/drivers/network/tcpip/include/tcp.h @@ -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 ); diff --git a/reactos/drivers/network/tcpip/include/titypes.h b/reactos/drivers/network/tcpip/include/titypes.h index eaac15a1496..9ac9561e0bb 100644 --- a/reactos/drivers/network/tcpip/include/titypes.h +++ b/reactos/drivers/network/tcpip/include/titypes.h @@ -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 index 3450ab8567f..00000000000 --- a/reactos/drivers/network/tcpip/recmutex/recmutex.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#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 index 3479268e3bd..00000000000 --- a/reactos/drivers/network/tcpip/recmutex/recmutex.h +++ /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*/ diff --git a/reactos/drivers/network/tcpip/tcpip.rbuild b/reactos/drivers/network/tcpip/tcpip.rbuild index 2a9f91cc52e..4dd14d3cbdf 100644 --- a/reactos/drivers/network/tcpip/tcpip.rbuild +++ b/reactos/drivers/network/tcpip/tcpip.rbuild @@ -21,9 +21,6 @@ lan.c - - recmutex.c - ainfo.c buffer.c diff --git a/reactos/drivers/network/tcpip/tcpip/dispatch.c b/reactos/drivers/network/tcpip/tcpip/dispatch.c index 182330928af..49de2fd9090 100644 --- a/reactos/drivers/network/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/network/tcpip/tcpip/dispatch.c @@ -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; } diff --git a/reactos/drivers/network/tcpip/tcpip/fileobjs.c b/reactos/drivers/network/tcpip/tcpip/fileobjs.c index 85808f9c0bf..dec7a0c9576 100644 --- a/reactos/drivers/network/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/network/tcpip/tcpip/fileobjs.c @@ -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; diff --git a/reactos/drivers/network/tcpip/tcpip/lock.c b/reactos/drivers/network/tcpip/tcpip/lock.c index 3f9d823c857..9a6cdc95fa3 100644 --- a/reactos/drivers/network/tcpip/tcpip/lock.c +++ b/reactos/drivers/network/tcpip/tcpip/lock.c @@ -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 ); -} diff --git a/reactos/drivers/network/tcpip/tcpip/mocklock.c b/reactos/drivers/network/tcpip/tcpip/mocklock.c index 0042ef8b803..0aa957c4035 100644 --- a/reactos/drivers/network/tcpip/tcpip/mocklock.c +++ b/reactos/drivers/network/tcpip/tcpip/mocklock.c @@ -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 ) { -} diff --git a/reactos/lib/drivers/ip/transport/datagram/datagram.c b/reactos/lib/drivers/ip/transport/datagram/datagram.c index 70660605950..fafea75f84a 100644 --- a/reactos/lib/drivers/ip/transport/datagram/datagram.c +++ b/reactos/lib/drivers/ip/transport/datagram/datagram.c @@ -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; diff --git a/reactos/lib/drivers/ip/transport/rawip/rawip.c b/reactos/lib/drivers/ip/transport/rawip/rawip.c index f7b9b6dbec9..328337cdb38 100644 --- a/reactos/lib/drivers/ip/transport/rawip/rawip.c +++ b/reactos/lib/drivers/ip/transport/rawip/rawip.c @@ -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; } diff --git a/reactos/lib/drivers/ip/transport/tcp/accept.c b/reactos/lib/drivers/ip/transport/tcp/accept.c index f44c0c918ec..b99c03b203c 100644 --- a/reactos/lib/drivers/ip/transport/tcp/accept.c +++ b/reactos/lib/drivers/ip/transport/tcp/accept.c @@ -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; } diff --git a/reactos/lib/drivers/ip/transport/tcp/event.c b/reactos/lib/drivers/ip/transport/tcp/event.c index ba9e867457b..a4b2275b511 100644 --- a/reactos/lib/drivers/ip/transport/tcp/event.c +++ b/reactos/lib/drivers/ip/transport/tcp/event.c @@ -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); diff --git a/reactos/lib/drivers/ip/transport/tcp/tcp.c b/reactos/lib/drivers/ip/transport/tcp/tcp.c index a9907abf810..c978bebf298 100644 --- a/reactos/lib/drivers/ip/transport/tcp/tcp.c +++ b/reactos/lib/drivers/ip/transport/tcp/tcp.c @@ -15,12 +15,12 @@ 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; diff --git a/reactos/lib/drivers/ip/transport/udp/udp.c b/reactos/lib/drivers/ip/transport/udp/udp.c index 46366e6833d..125e5101fc0 100644 --- a/reactos/lib/drivers/ip/transport/udp/udp.c +++ b/reactos/lib/drivers/ip/transport/udp/udp.c @@ -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; } diff --git a/reactos/lib/drivers/oskittcp/include/oskittcp.h b/reactos/lib/drivers/oskittcp/include/oskittcp.h index b5242fe03a9..b8c008e2172 100644 --- a/reactos/lib/drivers/oskittcp/include/oskittcp.h +++ b/reactos/lib/drivers/oskittcp/include/oskittcp.h @@ -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*/ diff --git a/reactos/lib/drivers/oskittcp/oskittcp/interface.c b/reactos/lib/drivers/oskittcp/oskittcp/interface.c index 5aea3ddd517..ef6f521cd58 100644 --- a/reactos/lib/drivers/oskittcp/oskittcp/interface.c +++ b/reactos/lib/drivers/oskittcp/oskittcp/interface.c @@ -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; }