- 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:
Cameron Gutman 2009-11-21 13:00:37 +00:00
parent fda7cf929a
commit c71cdeb49d
10 changed files with 216 additions and 172 deletions

View file

@ -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));

View file

@ -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 );

View file

@ -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 */

View file

@ -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:

View file

@ -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,

View file

@ -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:

View file

@ -73,9 +73,6 @@ void NTAPI IPTimeout( PVOID Context ) {
/* Clean possible outdated cached neighbor addresses */
NBTimeout();
/* Call upper layer timeout routines */
TCPTimeout();
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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 */
}