mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
- Disassociate the socket context before closing so we don't get signalled with a freed context (major cause of crashes)
- Signal the connection directly from TCPSocketState - Remove some unused code - Queue completion requests on a separate list so we don't have to keep locking and unlocking while completing - Add better locking to tcpip (not the lib) - Remove some unused variables - Don't hold the cancel spin lock longer than necessary - Check that we successfully got the device description svn path=/trunk/; revision=44250
This commit is contained in:
parent
fda7cf929a
commit
c71cdeb49d
10 changed files with 216 additions and 172 deletions
|
@ -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));
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -73,9 +73,6 @@ void NTAPI IPTimeout( PVOID Context ) {
|
|||
|
||||
/* Clean possible outdated cached neighbor addresses */
|
||||
NBTimeout();
|
||||
|
||||
/* Call upper layer timeout routines */
|
||||
TCPTimeout();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue