- 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
GetName( RegistryPath, &IF->Name );
Status = FindDeviceDescForAdapter( &IF->Name, &IF->Description );
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));
TI_DbgPrint(DEBUG_DATALINK,("Adapter Description: %wZ\n",
&IF->Description));
KEVENT Event;
} SLEEPING_THREAD, *PSLEEPING_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 */
/* Retransmission timeout constants */
/* Lower bound for retransmission timeout in TCP timer ticks */
#define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification;
#define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification;
+extern CLIENT_DATA ClientInfo;
/* accept.c */
NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
/* accept.c */
NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
UINT Family, UINT Type, UINT Proto );
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,
PTCP_SEGMENT TCPCreateSegment(
PIP_PACKET IPPacket,
PTCPv4_HEADER TCPHeader,
NTSTATUS TCPTranslateError( int OskitError );
NTSTATUS TCPTranslateError( int OskitError );
UINT TCPAllocatePort( UINT HintPort );
VOID TCPFreePort( UINT Port );
UINT TCPAllocatePort( UINT HintPort );
VOID TCPFreePort( UINT Port );
LIST_ENTRY Entry;
struct _CONNECTION_ENDPOINT *AssociatedEndpoint;
TDI_REQUEST Request;
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
} TDI_BUCKET, *PTDI_BUCKET;
/* Transport connection context structure A.K.A. Transmission Control Block
LIST_ENTRY ListenRequest; /* Queued listen requests */
LIST_ENTRY ReceiveRequest; /* Queued receive requests */
LIST_ENTRY SendRequest; /* Queued send requests */
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 */
/* Signals */
UINT SignalState; /* Active signals from oskit */
PVOID Buffer,
UINT BufferSize)
{
PVOID Buffer,
UINT BufferSize)
{
switch (ID->toi_id)
{
#if 0
switch (ID->toi_id)
{
#if 0
if (BufferSize < sizeof(UCHAR))
return TDI_INVALID_PARAMETER;
if (BufferSize < sizeof(UCHAR))
return TDI_INVALID_PARAMETER;
+ KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
AddrFile->TTL = *((PUCHAR)Buffer);
AddrFile->TTL = *((PUCHAR)Buffer);
+ KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
+
return TDI_SUCCESS;
#endif
default:
return TDI_SUCCESS;
#endif
default:
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
- PTRANSPORT_CONTEXT TranContext;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
Irp = Context;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp = Context;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
- TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
IoAcquireCancelSpinLock(&OldIrql);
IoAcquireCancelSpinLock(&OldIrql);
PFILE_OBJECT FileObject;
UCHAR MinorFunction;
PFILE_OBJECT FileObject;
UCHAR MinorFunction;
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
- IoReleaseCancelSpinLock(Irp->CancelIrql);
IRPFinish(Irp, STATUS_CANCELLED);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
IRPFinish(Irp, STATUS_CANCELLED);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
PCONNECTION_ENDPOINT Connection;
/*NTSTATUS Status = STATUS_SUCCESS;*/
PCONNECTION_ENDPOINT Connection;
/*NTSTATUS Status = STATUS_SUCCESS;*/
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection);
TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection);
- IoReleaseCancelSpinLock(Irp->CancelIrql);
-
Irp->IoStatus.Information = 0;
IRPFinish(Irp, STATUS_CANCELLED);
Irp->IoStatus.Information = 0;
IRPFinish(Irp, STATUS_CANCELLED);
PFILE_OBJECT FileObject;
PADDRESS_FILE AddrFile = NULL;
NTSTATUS Status;
PFILE_OBJECT FileObject;
PADDRESS_FILE AddrFile = NULL;
NTSTATUS Status;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_INVALID_PARAMETER;
}
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(
Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
Status = ObReferenceObjectByHandle(
return STATUS_INVALID_PARAMETER;
}
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);
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;
TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
FileObject->FsContext2));
return STATUS_INVALID_PARAMETER;
TranContext = FileObject->FsContext;
if (!TranContext) {
ObDereferenceObject(FileObject);
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) {
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;
}
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 */
Connection->AddressFile = AddrFile;
/* Add connection endpoint to the address file */
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
ObDereferenceObject(FileObject);
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
ObDereferenceObject(FileObject);
+ KeReleaseSpinLockFromDpcLevel(&AddrFile->Lock);
+ KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
PCONNECTION_ENDPOINT Connection;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
PCONNECTION_ENDPOINT Connection;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_INVALID_PARAMETER;
}
return STATUS_INVALID_PARAMETER;
}
+ KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+
if (!Connection->AddressFile) {
if (!Connection->AddressFile) {
+ KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
return STATUS_INVALID_PARAMETER;
}
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;
/* 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;
/* Remove the address file from this connection */
Connection->AddressFile = NULL;
+ KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
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);
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. */
/* 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. */
+ KeReleaseSpinLockFromDpcLevel(&Connection->AddressFile->Lock);
+ KeReleaseSpinLock(&Connection->Lock, OldIrql);
+
done:
if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0);
done:
if (Status != STATUS_PENDING) {
DispDataRequestComplete(Irp, Status, 0);
case TDI_CONNECTION_FILE:
Endpoint =
(PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
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));
RtlZeroMemory(
&Address->Address[0].Address[0].sin_zero,
sizeof(Address->Address[0].Address[0].sin_zero));
+ return TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
default:
TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
default:
TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
DataBuffer,
BufferSize,
&Irp->IoStatus.Information);
DataBuffer,
BufferSize,
&Irp->IoStatus.Information);
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_UNSUCCESSFUL;
*/
{
PTI_QUERY_CONTEXT QueryContext;
*/
{
PTI_QUERY_CONTEXT QueryContext;
QueryContext = (PTI_QUERY_CONTEXT)Context;
if (NT_SUCCESS(Status)) {
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,
QueryContext->InputMdl,
FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
(PCHAR)&QueryContext->QueryInfo.Context,
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
- PTRANSPORT_CONTEXT Context;
IRPRemember(Irp, __FILE__, __LINE__);
IRPRemember(Irp, __FILE__, __LINE__);
/* Close an address file, connection endpoint, or control connection */
case IRP_MJ_CLOSE:
/* 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);
/* Clean possible outdated cached neighbor addresses */
NBTimeout();
/* Clean possible outdated cached neighbor addresses */
NBTimeout();
-
- /* Call upper layer timeout routines */
- TCPTimeout();
- KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
+ if (ClientInfo.Unlocked)
+ KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
NewState, Connection,
TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
NewState, Connection,
Connection->SignalState |= NewState;
Connection->SignalState |= NewState;
- KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
+ HandleSignalledConnection(Connection);
+
+ if (ClientInfo.Unlocked)
+ KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
static BOOLEAN TCPInitialized = FALSE;
static NPAGED_LOOKASIDE_LIST TCPSegmentList;
PORT_SET TCPPorts;
static BOOLEAN TCPInitialized = FALSE;
static NPAGED_LOOKASIDE_LIST TCPSegmentList;
PORT_SET TCPPorts;
-static VOID DrainSignals() {
- PCONNECTION_ENDPOINT Connection;
- PLIST_ENTRY CurrentEntry, NextEntry;
- KIRQL OldIrql;
- NTSTATUS Status = STATUS_SUCCESS;
- PTCP_COMPLETION_ROUTINE Complete;
+static VOID
+ProcessCompletions(PCONNECTION_ENDPOINT Connection)
+{
+ PLIST_ENTRY CurrentEntry;
- 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));
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
Connection, Connection->SocketContext));
if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) {
TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
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));
/* If OskitTCP initiated the disconnect, try to read the socket error that occurred */
if (Connection->SocketContext)
SocketError = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext));
if (!Connection->SocketContext || !SocketError)
SocketError = STATUS_CANCELLED;
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 );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
- Complete( Bucket->Request.RequestContext, SocketError, 0 );
+ Bucket->Status = SocketError;
+ Bucket->Information = 0;
+ InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
- &Connection->Lock )) != NULL)
+ while (!IsListEmpty(&Connection->SendRequest))
+ Entry = RemoveHeadList( &Connection->SendRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
- Complete( Bucket->Request.RequestContext, SocketError, 0 );
+ Bucket->Status = SocketError;
+ Bucket->Information = 0;
+ InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
- &Connection->Lock )) != NULL)
+ while (!IsListEmpty(&Connection->ListenRequest))
+ Entry = RemoveHeadList( &Connection->ListenRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
- Complete( Bucket->Request.RequestContext, SocketError, 0 );
+ Bucket->Status = SocketError;
+ Bucket->Information = 0;
+ InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
- while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
- &Connection->Lock )) != NULL)
+ while (!IsListEmpty(&Connection->ConnectRequest))
+ Entry = RemoveHeadList( &Connection->ConnectRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
- Complete( Bucket->Request.RequestContext, SocketError, 0 );
+ Bucket->Status = SocketError;
+ Bucket->Information = 0;
+ InsertTailList(&Connection->CompletionQueue, &Bucket->Entry);
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
+ Connection->SignalState = 0;
}
/* Things that can happen when we try the initial connection */
if( Connection->SignalState & SEL_CONNECT ) {
}
/* 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 );
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
*/
}
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"));
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;
PIO_STACK_LOCATION IrpSp;
+ Entry = RemoveHeadList( &Connection->ListenRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
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"));
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 );
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 ) {
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) {
- ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry,
- &Connection->Lock );
+ InsertHeadList( &Connection->ListenRequest, &Bucket->Entry );
- 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 */
}
/* 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"));
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;
OSK_UINT RecvLen = 0, Received = 0;
PVOID RecvBuffer = 0;
+ Entry = RemoveHeadList( &Connection->ReceiveRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
-
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
- KeReleaseSpinLock(&Connection->Lock, OldIrql);
-
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
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));
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"));
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;
OSK_UINT SendLen = 0, Sent = 0;
PVOID SendBuffer = 0;
+ Entry = RemoveHeadList( &Connection->SendRequest );
+
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
("Connection->SocketContext: %x\n",
Connection->SocketContext));
("Connection->SocketContext: %x\n",
Connection->SocketContext));
- KeAcquireSpinLock(&Connection->Lock, &OldIrql);
-
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
- 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",
- 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));
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);
}
KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
}
InitializeListHead(&Connection->ListenRequest);
InitializeListHead(&Connection->ReceiveRequest);
InitializeListHead(&Connection->SendRequest);
InitializeListHead(&Connection->ListenRequest);
InitializeListHead(&Connection->ReceiveRequest);
InitializeListHead(&Connection->SendRequest);
+ InitializeListHead(&Connection->CompletionQueue);
/* Save client context pointer */
Connection->ClientContext = ClientContext;
/* Save client context pointer */
Connection->ClientContext = ClientContext;
* This is the low level interface for receiving TCP data
*/
{
* This is the low level interface for receiving TCP data
*/
{
TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to oskit\n",
IPPacket->TotalSize,
IPPacket->HeaderSize));
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 );
OskitTCPReceiveDatagram( IPPacket->Header,
IPPacket->TotalSize,
IPPacket->HeaderSize );
+
+ ClientInfo.Unlocked = FALSE;
+ KeReleaseSpinLock(&ClientInfo.Lock, OldIrql);
while ( 1 ) {
if (Next == NextFast) {
NextFast += 2;
while ( 1 ) {
if (Next == NextFast) {
NextFast += 2;
if (Next == NextSlow) {
NextSlow += 5;
}
if (Next == NextSlow) {
NextSlow += 5;
}
}
TimerOskitTCP( Next == NextFast, Next == NextSlow );
}
TimerOskitTCP( Next == NextFast, Next == NextSlow );
- if (Next == NextSlow) {
- DrainSignals();
- }
Current = Next;
if (10 <= Current) {
Current = Next;
if (10 <= Current) {
NTSTATUS TCPStartup(VOID)
/*
* FUNCTION: Initializes the TCP subsystem
NTSTATUS TCPStartup(VOID)
/*
* FUNCTION: Initializes the TCP subsystem
+ KeInitializeSpinLock(&ClientInfo.Lock);
+ ClientInfo.Unlocked = FALSE;
+
RegisterOskitTCPEventHandlers( &EventHandlers );
InitOskitTCP();
RegisterOskitTCPEventHandlers( &EventHandlers );
InitOskitTCP();
-VOID TCPTimeout(VOID) {
- /* Now handled by TimerThread */
-}
-
UINT TCPAllocatePort( UINT HintPort ) {
if( HintPort ) {
if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort;
UINT TCPAllocatePort( UINT HintPort ) {
if( HintPort ) {
if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort;
int OskitTCPClose( void *socket ) {
int error;
int OskitTCPClose( void *socket ) {
int error;
+ struct socket *so = socket;
if (!socket)
return OSK_ESHUTDOWN;
OSKLock();
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();
error = soclose( socket );
OSKUnlock();
OSK_UINT IpHeaderLen ) {
struct mbuf *Ip;
struct ip *iph;
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);
Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
if( !Ip )
{
Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
if( !Ip )
{
- OSKUnlockAndLower(OldIrql);
return; /* drop the segment */
}
return; /* drop the segment */
}
IpHeaderLen));
tcp_input(Ip, IpHeaderLen);
IpHeaderLen));
tcp_input(Ip, IpHeaderLen);
- OSKUnlockAndLower(OldIrql);
/* The buffer Ip is freed by tcp_input */
}
/* The buffer Ip is freed by tcp_input */
}