mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[TCPIP][IP] Use an ERESOURCE as mutex for address files & connection end points
Spinlocks are not reentrant (and this is done a lot), using them forces us to have an horrible hack in the kernel, which unschedules threads which are at DISPATCH_LEVEL thus allowing another thread to take ownership of the spinlock while the unscheduled thread should already hold it. CORE-6473
This commit is contained in:
parent
10e48faf1d
commit
27fcfe66a2
14 changed files with 326 additions and 343 deletions
|
@ -201,13 +201,13 @@ VOID
|
|||
FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
|
||||
|
||||
VOID
|
||||
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
|
||||
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
|
||||
|
||||
VOID
|
||||
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
|
||||
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
|
||||
|
||||
VOID
|
||||
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked);
|
||||
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
|
||||
|
||||
VOID
|
||||
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status);
|
||||
|
|
|
@ -29,44 +29,26 @@
|
|||
}
|
||||
|
||||
/*
|
||||
* VOID LockObject(PVOID Object, PKIRQL OldIrql)
|
||||
* VOID LockObject(PVOID Object)
|
||||
*/
|
||||
#define LockObject(Object, Irql) \
|
||||
{ \
|
||||
ReferenceObject(Object); \
|
||||
KeAcquireSpinLock(&((Object)->Lock), Irql); \
|
||||
memcpy(&(Object)->OldIrql, Irql, sizeof(KIRQL)); \
|
||||
}
|
||||
#define LockObject(Object) do \
|
||||
{ \
|
||||
ReferenceObject(Object); \
|
||||
KeEnterCriticalRegion(); \
|
||||
ExAcquireResourceExclusiveLite(&(Object)->Resource, TRUE); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* VOID LockObjectAtDpcLevel(PVOID Object)
|
||||
* VOID UnlockObject(PVOID Object)
|
||||
*/
|
||||
#define LockObjectAtDpcLevel(Object) \
|
||||
{ \
|
||||
ReferenceObject(Object); \
|
||||
KeAcquireSpinLockAtDpcLevel(&((Object)->Lock)); \
|
||||
(Object)->OldIrql = DISPATCH_LEVEL; \
|
||||
}
|
||||
|
||||
/*
|
||||
* VOID UnlockObject(PVOID Object, KIRQL OldIrql)
|
||||
*/
|
||||
#define UnlockObject(Object, OldIrql) \
|
||||
#define UnlockObject(Object) do \
|
||||
{ \
|
||||
KeReleaseSpinLock(&((Object)->Lock), OldIrql); \
|
||||
ExReleaseResourceLite(&(Object)->Resource); \
|
||||
KeLeaveCriticalRegion(); \
|
||||
DereferenceObject(Object); \
|
||||
}
|
||||
|
||||
/*
|
||||
* VOID UnlockObjectFromDpcLevel(PVOID Object)
|
||||
*/
|
||||
#define UnlockObjectFromDpcLevel(Object) \
|
||||
{ \
|
||||
KeReleaseSpinLockFromDpcLevel(&((Object)->Lock)); \
|
||||
DereferenceObject(Object); \
|
||||
}
|
||||
|
||||
} while(0)
|
||||
|
||||
#define ASSERT_TCPIP_OBJECT_LOCKED(Object) ASSERT(ExIsResourceAcquiredExclusiveLite(&(Object)->Resource))
|
||||
|
||||
#include <ip.h>
|
||||
|
||||
|
@ -131,8 +113,7 @@ typedef struct _ADDRESS_FILE {
|
|||
LIST_ENTRY ListEntry; /* Entry on list */
|
||||
LONG RefCount; /* Reference count */
|
||||
OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */
|
||||
KSPIN_LOCK Lock; /* Spin lock to manipulate this structure */
|
||||
KIRQL OldIrql; /* Currently not used */
|
||||
ERESOURCE Resource; /* Resource to manipulate this structure */
|
||||
IP_ADDRESS Address; /* Address of this address file */
|
||||
USHORT Family; /* Address family */
|
||||
USHORT Protocol; /* Protocol number */
|
||||
|
@ -142,7 +123,6 @@ typedef struct _ADDRESS_FILE {
|
|||
UINT DF; /* Don't fragment */
|
||||
UINT BCast; /* Receive broadcast packets */
|
||||
UINT HeaderIncl; /* Include header in RawIP packets */
|
||||
WORK_QUEUE_ITEM WorkItem; /* Work queue item handle */
|
||||
DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine for delete request */
|
||||
PVOID Context; /* Delete request context */
|
||||
DATAGRAM_SEND_ROUTINE Send; /* Routine to send a datagram */
|
||||
|
@ -262,8 +242,7 @@ typedef struct _CONNECTION_ENDPOINT {
|
|||
LIST_ENTRY ListEntry; /* Entry on list */
|
||||
LONG RefCount; /* Reference count */
|
||||
OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */
|
||||
KSPIN_LOCK Lock; /* Spin lock to protect this structure */
|
||||
KIRQL OldIrql; /* The old irql is stored here for use in HandleSignalledConnection */
|
||||
ERESOURCE Resource; /* The lock protecting this structure */
|
||||
PVOID ClientContext; /* Pointer to client context information */
|
||||
PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */
|
||||
|
||||
|
@ -279,6 +258,7 @@ typedef struct _CONNECTION_ENDPOINT {
|
|||
/* Disconnect Timer */
|
||||
KTIMER DisconnectTimer;
|
||||
KDPC DisconnectDpc;
|
||||
PIO_WORKITEM DisconnectWorkItem;
|
||||
|
||||
/* Socket state */
|
||||
BOOLEAN SendShutdown;
|
||||
|
|
|
@ -13,17 +13,15 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
|
|||
PVOID Buffer,
|
||||
UINT BufferSize)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
switch (ID->toi_id)
|
||||
{
|
||||
case AO_OPTION_TTL:
|
||||
if (BufferSize < sizeof(UINT))
|
||||
return TDI_INVALID_PARAMETER;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
AddrFile->TTL = *((PUCHAR)Buffer);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return TDI_SUCCESS;
|
||||
|
||||
|
@ -31,9 +29,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
|
|||
if (BufferSize < sizeof(UINT))
|
||||
return TDI_INVALID_PARAMETER;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
AddrFile->DF = *((PUINT)Buffer);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return TDI_SUCCESS;
|
||||
|
||||
|
@ -41,9 +39,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
|
|||
if (BufferSize < sizeof(UINT))
|
||||
return TDI_INVALID_PARAMETER;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
AddrFile->BCast = *((PUINT)Buffer);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return TDI_SUCCESS;
|
||||
|
||||
|
@ -51,9 +49,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
|
|||
if (BufferSize < sizeof(UINT))
|
||||
return TDI_INVALID_PARAMETER;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
AddrFile->HeaderIncl = *((PUINT)Buffer);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return TDI_SUCCESS;
|
||||
|
||||
|
|
|
@ -284,7 +284,6 @@ NTSTATUS DispTdiAssociateAddress(
|
|||
PFILE_OBJECT FileObject;
|
||||
PADDRESS_FILE AddrFile = NULL;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
|
||||
|
||||
|
@ -319,18 +318,18 @@ NTSTATUS DispTdiAssociateAddress(
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (Connection->AddressFile) {
|
||||
ObDereferenceObject(FileObject);
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
TI_DbgPrint(MID_TRACE, ("An address file is already associated.\n"));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
|
||||
ObDereferenceObject(FileObject);
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
|
||||
FileObject->FsContext2));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
@ -341,20 +340,20 @@ NTSTATUS DispTdiAssociateAddress(
|
|||
TranContext = FileObject->FsContext;
|
||||
if (!TranContext) {
|
||||
ObDereferenceObject(FileObject);
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
|
||||
if (!AddrFile) {
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
ObDereferenceObject(FileObject);
|
||||
TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
LockObjectAtDpcLevel(AddrFile);
|
||||
LockObject(AddrFile);
|
||||
|
||||
ReferenceObject(AddrFile);
|
||||
Connection->AddressFile = AddrFile;
|
||||
|
@ -373,8 +372,8 @@ NTSTATUS DispTdiAssociateAddress(
|
|||
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
UnlockObjectFromDpcLevel(AddrFile);
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
UnlockObject(Connection);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -563,7 +562,6 @@ NTSTATUS DispTdiListen(
|
|||
PTRANSPORT_CONTEXT TranContext;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
|
||||
|
||||
|
@ -596,17 +594,17 @@ NTSTATUS DispTdiListen(
|
|||
Irp,
|
||||
(PDRIVER_CANCEL)DispCancelListenRequest);
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (Connection->AddressFile == NULL)
|
||||
{
|
||||
TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
LockObjectAtDpcLevel(Connection->AddressFile);
|
||||
LockObject(Connection->AddressFile);
|
||||
|
||||
/* 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
|
||||
|
@ -647,8 +645,8 @@ NTSTATUS DispTdiListen(
|
|||
Irp );
|
||||
}
|
||||
|
||||
UnlockObjectFromDpcLevel(Connection->AddressFile);
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection->AddressFile);
|
||||
UnlockObject(Connection);
|
||||
|
||||
done:
|
||||
if (Status != STATUS_PENDING) {
|
||||
|
@ -1116,7 +1114,6 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
|
|||
PIO_STACK_LOCATION IrpSp;
|
||||
PADDRESS_FILE AddrFile;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
|
||||
|
||||
|
@ -1139,7 +1136,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
|
|||
Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
/* Set the event handler. if an event handler is associated with
|
||||
a specific event, it's flag (RegisteredXxxHandler) is TRUE.
|
||||
|
@ -1260,7 +1257,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
|
|||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -310,7 +310,7 @@ VOID AddrFileFree(
|
|||
PADDRESS_FILE AddrFile = Object;
|
||||
KIRQL OldIrql;
|
||||
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
|
||||
PDATAGRAM_SEND_REQUEST SendRequest;
|
||||
// PDATAGRAM_SEND_REQUEST SendRequest; See WTF below
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
|
||||
TI_DbgPrint(MID_TRACE, ("Called.\n"));
|
||||
|
@ -330,20 +330,26 @@ VOID AddrFileFree(
|
|||
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
|
||||
|
||||
/* Go through pending receive request list and cancel them all */
|
||||
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
|
||||
while (!IsListEmpty(&AddrFile->ReceiveQueue))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue);
|
||||
ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
|
||||
(*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
|
||||
/* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
|
||||
ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
|
||||
}
|
||||
|
||||
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
|
||||
|
||||
#if 0 /* Biggest WTF. All of this was taken care of above as DATAGRAM_RECEIVE_REQUEST. */
|
||||
/* Go through pending send request list and cancel them all */
|
||||
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
|
||||
while (!IsListEmpty(&AddrFile->ReceiveQueue))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue);
|
||||
SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
|
||||
(*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
|
||||
ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Protocol specific handling */
|
||||
switch (AddrFile->Protocol) {
|
||||
|
@ -361,6 +367,8 @@ VOID AddrFileFree(
|
|||
|
||||
RemoveEntityByContext(AddrFile);
|
||||
|
||||
ExDeleteResourceLite(&AddrFile->Resource);
|
||||
|
||||
ExFreePoolWithTag(Object, ADDR_FILE_TAG);
|
||||
}
|
||||
|
||||
|
@ -553,7 +561,7 @@ NTSTATUS FileOpenAddress(
|
|||
InitializeListHead(&AddrFile->TransmitQueue);
|
||||
|
||||
/* Initialize spin lock that protects the address file object */
|
||||
KeInitializeSpinLock(&AddrFile->Lock);
|
||||
ExInitializeResourceLite(&AddrFile->Resource);
|
||||
|
||||
/* Return address file object */
|
||||
Request->Handle.AddressHandle = AddrFile;
|
||||
|
@ -581,27 +589,27 @@ NTSTATUS FileCloseAddress(
|
|||
PTDI_REQUEST Request)
|
||||
{
|
||||
PADDRESS_FILE AddrFile = Request->Handle.AddressHandle;
|
||||
KIRQL OldIrql;
|
||||
PCONNECTION_ENDPOINT Listener;
|
||||
|
||||
if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
if (InterlockedDecrement(&AddrFile->Sharers) != 0)
|
||||
{
|
||||
/* Still other guys have open handles to this, so keep it around */
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* We have to close this listener because we started it */
|
||||
if( AddrFile->Listener )
|
||||
Listener = AddrFile->Listener;
|
||||
UnlockObject(AddrFile);
|
||||
if( Listener )
|
||||
{
|
||||
TCPClose( AddrFile->Listener );
|
||||
TCPClose( Listener );
|
||||
}
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
|
||||
DereferenceObject(AddrFile);
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
||||
|
|
|
@ -74,11 +74,9 @@ VOID
|
|||
ClearReceiveHandler(
|
||||
_In_ PADDRESS_FILE AddrFile)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
AddrFile->RegisteredReceiveDatagramHandler = FALSE;
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
}
|
||||
|
||||
IO_WORKITEM_ROUTINE EndRequestHandler;
|
||||
|
@ -95,6 +93,8 @@ EndRequestHandler(
|
|||
UINT32 nReplies;
|
||||
KIRQL OldIrql;
|
||||
|
||||
ClearReceiveHandler((PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle);
|
||||
|
||||
KeWaitForSingleObject(&Context->DatagramProcessedEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
TI_DbgPrint(DEBUG_ICMP, ("Finishing request Context: %p\n", Context));
|
||||
|
@ -267,8 +267,6 @@ TimeoutHandler(
|
|||
_In_opt_ PVOID SystemArgument2)
|
||||
{
|
||||
PICMP_PACKET_CONTEXT Context = (PICMP_PACKET_CONTEXT)_Context;
|
||||
PADDRESS_FILE AddrFile = (PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle;
|
||||
ClearReceiveHandler(AddrFile);
|
||||
|
||||
IoQueueWorkItem(Context->FinishWorker, &EndRequestHandler, DelayedWorkQueue, _Context);
|
||||
}
|
||||
|
@ -290,7 +288,6 @@ DispEchoRequest(
|
|||
PUCHAR Buffer;
|
||||
UINT16 RequestSize;
|
||||
PICMP_PACKET_CONTEXT SendContext;
|
||||
KIRQL OldIrql;
|
||||
LARGE_INTEGER RequestTimeout;
|
||||
UINT8 SavedTtl;
|
||||
|
||||
|
@ -390,14 +387,14 @@ DispEchoRequest(
|
|||
|
||||
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, OutputBufferLength);
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
AddrFile->TTL = SavedTtl;
|
||||
AddrFile->ReceiveDatagramHandlerContext = SendContext;
|
||||
AddrFile->ReceiveDatagramHandler = ReceiveDatagram;
|
||||
AddrFile->RegisteredReceiveDatagramHandler = TRUE;
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
Status = AddrFile->Send(AddrFile, &ConnectionInfo, (PCHAR)Buffer, RequestSize, &DataUsed);
|
||||
|
||||
|
|
|
@ -16,13 +16,12 @@ BOOLEAN DGRemoveIRP(
|
|||
{
|
||||
PLIST_ENTRY ListEntry;
|
||||
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Found = FALSE;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
|
||||
Irp, AddrFile));
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
for( ListEntry = AddrFile->ReceiveQueue.Flink;
|
||||
ListEntry != &AddrFile->ReceiveQueue;
|
||||
|
@ -42,7 +41,7 @@ BOOLEAN DGRemoveIRP(
|
|||
}
|
||||
}
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Done.\n"));
|
||||
|
||||
|
@ -73,7 +72,6 @@ DGDeliverData(
|
|||
* handler if it exists, otherwise we drop the packet.
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
LONG AddressLength;
|
||||
PVOID SourceAddress;
|
||||
ULONG BytesTaken;
|
||||
|
@ -82,7 +80,7 @@ DGDeliverData(
|
|||
|
||||
TI_DbgPrint(MIN_TRACE, ("Called.\n"));
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
if (AddrFile->Protocol == IPPROTO_UDP)
|
||||
{
|
||||
|
@ -145,7 +143,7 @@ DGDeliverData(
|
|||
SrcAddress->Address.IPv4Address, SrcPort));
|
||||
|
||||
ReferenceObject(AddrFile);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
/* Complete the receive request */
|
||||
if (Current->BufferSize < DataSize)
|
||||
|
@ -153,12 +151,12 @@ DGDeliverData(
|
|||
else
|
||||
Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
DereferenceObject(AddrFile);
|
||||
}
|
||||
}
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
}
|
||||
else if (AddrFile->RegisteredReceiveDatagramHandler)
|
||||
{
|
||||
|
@ -186,7 +184,7 @@ DGDeliverData(
|
|||
}
|
||||
|
||||
ReferenceObject(AddrFile);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
TI_DbgPrint(MIN_TRACE, ("OptionsSize %d DataSize: %u\n", OptionsSize, DataSize));
|
||||
|
||||
|
@ -209,7 +207,7 @@ DGDeliverData(
|
|||
}
|
||||
else
|
||||
{
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
|
||||
}
|
||||
|
||||
|
@ -254,11 +252,10 @@ NTSTATUS DGReceiveDatagram(
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
ReceiveRequest = ExAllocatePoolWithTag(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST),
|
||||
DATAGRAM_RECV_TAG);
|
||||
|
@ -276,7 +273,7 @@ NTSTATUS DGReceiveDatagram(
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
@ -304,13 +301,13 @@ NTSTATUS DGReceiveDatagram(
|
|||
|
||||
TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,9 +191,8 @@ NTSTATUS RawIPSendDatagram(
|
|||
USHORT RemotePort;
|
||||
NTSTATUS Status;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
|
||||
AddrFile, ConnInfo, BufferData, DataSize));
|
||||
|
@ -208,7 +207,7 @@ NTSTATUS RawIPSendDatagram(
|
|||
break;
|
||||
|
||||
default:
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -222,7 +221,7 @@ NTSTATUS RawIPSendDatagram(
|
|||
* interface we're sending over
|
||||
*/
|
||||
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_NETWORK_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
@ -231,7 +230,7 @@ NTSTATUS RawIPSendDatagram(
|
|||
else
|
||||
{
|
||||
if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) {
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +244,7 @@ NTSTATUS RawIPSendDatagram(
|
|||
BufferData,
|
||||
DataSize );
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
return Status;
|
||||
|
|
|
@ -48,12 +48,11 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog)
|
|||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
struct ip_addr AddressToBind;
|
||||
KIRQL OldIrql;
|
||||
TA_IP_ADDRESS LocalAddress;
|
||||
|
||||
ASSERT(Connection);
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
ASSERT_KM_POINTER(Connection->AddressFile);
|
||||
|
||||
|
@ -93,7 +92,7 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog)
|
|||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPListen] Leaving. Status = %x\n", Status));
|
||||
|
||||
|
@ -106,10 +105,9 @@ BOOLEAN TCPAbortListenForSocket
|
|||
{
|
||||
PLIST_ENTRY ListEntry;
|
||||
PTDI_BUCKET Bucket;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN Found = FALSE;
|
||||
|
||||
LockObject(Listener, &OldIrql);
|
||||
LockObject(Listener);
|
||||
|
||||
ListEntry = Listener->ListenRequest.Flink;
|
||||
while (ListEntry != &Listener->ListenRequest)
|
||||
|
@ -128,7 +126,7 @@ BOOLEAN TCPAbortListenForSocket
|
|||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
UnlockObject(Listener, OldIrql);
|
||||
UnlockObject(Listener);
|
||||
|
||||
return Found;
|
||||
}
|
||||
|
@ -141,9 +139,8 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PTDI_BUCKET Bucket;
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(Listener, &OldIrql);
|
||||
LockObject(Listener);
|
||||
|
||||
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
|
||||
|
||||
|
@ -160,7 +157,7 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
|
|||
else
|
||||
Status = STATUS_NO_MEMORY;
|
||||
|
||||
UnlockObject(Listener, OldIrql);
|
||||
UnlockObject(Listener);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -50,125 +50,66 @@ CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEA
|
|||
}
|
||||
|
||||
VOID
|
||||
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
|
||||
|
||||
if (interlocked)
|
||||
while (!IsListEmpty(&Connection->ReceiveRequest))
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
Entry = RemoveHeadList(&Connection->ReceiveRequest);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,
|
||||
("Completing Receive request: %x %x\n",
|
||||
Bucket->Request, Status));
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->ReceiveRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ReceiveRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
|
||||
|
||||
if (interlocked)
|
||||
while (!IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
Entry = RemoveHeadList(&Connection->SendRequest);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,
|
||||
("Completing Send request: %x %x\n",
|
||||
Bucket->Request, Status));
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->SendRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
|
||||
FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
||||
{
|
||||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
|
||||
|
||||
if (interlocked)
|
||||
while (!IsListEmpty(&Connection->ShutdownRequest))
|
||||
{
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock)))
|
||||
{
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
Entry = RemoveHeadList(&Connection->ShutdownRequest);
|
||||
|
||||
Bucket->Status = Status;
|
||||
Bucket->Information = 0;
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!IsListEmpty(&Connection->ShutdownRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ShutdownRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
|
||||
|
||||
Bucket->Information = 0;
|
||||
Bucket->Status = Status;
|
||||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -177,10 +118,11 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
||||
while (!IsListEmpty(&Connection->ConnectRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ConnectRequest);
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = Status;
|
||||
|
@ -188,8 +130,6 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -198,10 +138,11 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
||||
while (!IsListEmpty(&Connection->ListenRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ListenRequest);
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Bucket->Status = Status;
|
||||
|
@ -210,17 +151,13 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
|
|||
DereferenceObject(Bucket->AssociatedEndpoint);
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
|
||||
{
|
||||
ReferenceObject(Connection);
|
||||
|
||||
// flush receive queue
|
||||
FlushReceiveQueue(Connection, Status, TRUE);
|
||||
FlushReceiveQueue(Connection, Status);
|
||||
|
||||
/* We completed the reads successfully but we need to return failure now */
|
||||
if (Status == STATUS_SUCCESS)
|
||||
|
@ -232,15 +169,13 @@ FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
|
|||
FlushListenQueue(Connection, Status);
|
||||
|
||||
// flush send queue
|
||||
FlushSendQueue(Connection, Status, TRUE);
|
||||
FlushSendQueue(Connection, Status);
|
||||
|
||||
// flush connect queue
|
||||
FlushConnectQueue(Connection, Status);
|
||||
|
||||
// flush shutdown queue
|
||||
FlushShutdownQueue(Connection, Status, TRUE);
|
||||
|
||||
DereferenceObject(Connection);
|
||||
FlushShutdownQueue(Connection, Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -248,18 +183,17 @@ TCPFinEventHandler(void *arg, const err_t err)
|
|||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
|
||||
const NTSTATUS Status = TCPTranslateError(err);
|
||||
KIRQL OldIrql;
|
||||
|
||||
ASSERT(Connection->SocketContext == NULL);
|
||||
ASSERT(Connection->AddressFile);
|
||||
ASSERT(err != ERR_OK);
|
||||
|
||||
LockObject(Connection);
|
||||
|
||||
/* Complete all outstanding requests now */
|
||||
FlushAllQueues(Connection, Status);
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
|
||||
LockObjectAtDpcLevel(Connection->AddressFile);
|
||||
LockObject(Connection->AddressFile);
|
||||
|
||||
/* Unlink this connection from the address file */
|
||||
if (Connection->AddressFile->Connection == Connection)
|
||||
|
@ -284,13 +218,13 @@ TCPFinEventHandler(void *arg, const err_t err)
|
|||
}
|
||||
}
|
||||
|
||||
UnlockObjectFromDpcLevel(Connection->AddressFile);
|
||||
UnlockObject(Connection->AddressFile);
|
||||
|
||||
/* Remove the address file from this connection */
|
||||
DereferenceObject(Connection->AddressFile);
|
||||
Connection->AddressFile = NULL;
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -301,14 +235,15 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
|||
PLIST_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
LockObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
|
||||
while (!IsListEmpty(&Connection->ListenRequest))
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
|
||||
Entry = RemoveHeadList(&Connection->ListenRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Irp = Bucket->Request.RequestContext;
|
||||
|
@ -326,7 +261,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
|||
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
LockObject(Bucket->AssociatedEndpoint, &OldIrql);
|
||||
LockObject(Bucket->AssociatedEndpoint);
|
||||
|
||||
/* sanity assert...this should never be in anything else but a CLOSED state */
|
||||
ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
|
||||
|
@ -337,9 +272,9 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
|||
/* free previously created socket context (we don't use it, we use newpcb) */
|
||||
Bucket->AssociatedEndpoint->SocketContext = newpcb;
|
||||
|
||||
LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
|
||||
UnlockObject(Bucket->AssociatedEndpoint);
|
||||
|
||||
UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
|
||||
LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
|
||||
}
|
||||
|
||||
DereferenceObject(Bucket->AssociatedEndpoint);
|
||||
|
@ -352,7 +287,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
|
|||
}
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -367,12 +302,17 @@ TCPSendEventHandler(void *arg, const u16_t space)
|
|||
ULONG BytesSent;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
LockObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
|
||||
while (!IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
UINT SendLen = 0;
|
||||
PVOID SendBuffer = 0;
|
||||
|
||||
Entry = RemoveHeadList(&Connection->SendRequest);
|
||||
|
||||
UnlockObject(Connection);
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Irp = Bucket->Request.RequestContext;
|
||||
|
@ -400,9 +340,8 @@ TCPSendEventHandler(void *arg, const u16_t space)
|
|||
|
||||
if( Status == STATUS_PENDING )
|
||||
{
|
||||
ExInterlockedInsertHeadList(&Connection->SendRequest,
|
||||
&Bucket->Entry,
|
||||
&Connection->Lock);
|
||||
LockObject(Connection);
|
||||
InsertHeadList(&Connection->SendRequest, &Bucket->Entry);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -416,13 +355,15 @@ TCPSendEventHandler(void *arg, const u16_t space)
|
|||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
LockObject(Connection);
|
||||
}
|
||||
|
||||
// If we completed all outstanding send requests then finish all pending shutdown requests,
|
||||
// cancel the timer and dereference the connection
|
||||
if (IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
FlushShutdownQueue(Connection, STATUS_SUCCESS, FALSE);
|
||||
FlushShutdownQueue(Connection, STATUS_SUCCESS);
|
||||
|
||||
if (KeCancelTimer(&Connection->DisconnectTimer))
|
||||
{
|
||||
|
@ -430,6 +371,8 @@ TCPSendEventHandler(void *arg, const u16_t space)
|
|||
}
|
||||
}
|
||||
|
||||
UnlockObject(Connection);
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
|
@ -446,10 +389,11 @@ TCPRecvEventHandler(void *arg)
|
|||
PUCHAR RecvBuffer;
|
||||
NTSTATUS Status;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
LockObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
|
||||
while(!IsListEmpty(&Connection->ReceiveRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ReceiveRequest);
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
Irp = Bucket->Request.RequestContext;
|
||||
|
@ -460,9 +404,7 @@ TCPRecvEventHandler(void *arg)
|
|||
Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
ExInterlockedInsertHeadList(&Connection->ReceiveRequest,
|
||||
&Bucket->Entry,
|
||||
&Connection->Lock);
|
||||
InsertHeadList(&Connection->ReceiveRequest, &Bucket->Entry);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -471,8 +413,7 @@ TCPRecvEventHandler(void *arg)
|
|||
|
||||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -482,10 +423,11 @@ TCPConnectEventHandler(void *arg, const err_t err)
|
|||
PTDI_BUCKET Bucket;
|
||||
PLIST_ENTRY Entry;
|
||||
|
||||
ReferenceObject(Connection);
|
||||
LockObject(Connection);
|
||||
|
||||
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
|
||||
while (!IsListEmpty(&Connection->ConnectRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->ConnectRequest);
|
||||
|
||||
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
|
||||
|
||||
|
@ -495,5 +437,5 @@ TCPConnectEventHandler(void *arg, const err_t err)
|
|||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
DereferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
|
|
@ -25,21 +25,27 @@ PORT_SET TCPPorts;
|
|||
|
||||
NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
|
||||
|
||||
VOID NTAPI
|
||||
DisconnectTimeoutDpc(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
static
|
||||
IO_WORKITEM_ROUTINE
|
||||
DisconnectWorker;
|
||||
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
NTAPI
|
||||
DisconnectWorker(
|
||||
_Unreferenced_parameter_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PVOID Context
|
||||
)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Context;
|
||||
PLIST_ENTRY Entry;
|
||||
PTDI_BUCKET Bucket;
|
||||
|
||||
LockObjectAtDpcLevel(Connection);
|
||||
|
||||
/* We timed out waiting for pending sends so force it to shutdown */
|
||||
TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
|
||||
|
||||
LockObject(Connection);
|
||||
|
||||
while (!IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
Entry = RemoveHeadList(&Connection->SendRequest);
|
||||
|
@ -64,11 +70,23 @@ DisconnectTimeoutDpc(PKDPC Dpc,
|
|||
CompleteBucket(Connection, Bucket, FALSE);
|
||||
}
|
||||
|
||||
UnlockObjectFromDpcLevel(Connection);
|
||||
UnlockObject(Connection);
|
||||
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DisconnectTimeoutDpc(PKDPC Dpc,
|
||||
PVOID DeferredContext,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
|
||||
|
||||
IoQueueWorkItem(Connection->DisconnectWorkItem, DisconnectWorker, DelayedWorkQueue, Connection);
|
||||
}
|
||||
|
||||
VOID ConnectionFree(PVOID Object)
|
||||
{
|
||||
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Object;
|
||||
|
@ -80,6 +98,9 @@ VOID ConnectionFree(PVOID Object)
|
|||
RemoveEntryList(&Connection->ListEntry);
|
||||
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
|
||||
|
||||
ExDeleteResourceLite(&Connection->Resource);
|
||||
IoFreeWorkItem(Connection->DisconnectWorkItem);
|
||||
|
||||
ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
|
||||
}
|
||||
|
||||
|
@ -96,7 +117,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext )
|
|||
RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
|
||||
|
||||
/* Initialize spin lock that protects the connection endpoint file object */
|
||||
KeInitializeSpinLock(&Connection->Lock);
|
||||
ExInitializeResourceLite(&Connection->Resource);
|
||||
InitializeListHead(&Connection->ConnectRequest);
|
||||
InitializeListHead(&Connection->ListenRequest);
|
||||
InitializeListHead(&Connection->ReceiveRequest);
|
||||
|
@ -107,6 +128,13 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext )
|
|||
/* Initialize disconnect timer */
|
||||
KeInitializeTimer(&Connection->DisconnectTimer);
|
||||
KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, Connection);
|
||||
Connection->DisconnectWorkItem = IoAllocateWorkItem(TCPDeviceObject);
|
||||
if (!Connection->DisconnectWorkItem)
|
||||
{
|
||||
ExDeleteResourceLite(&Connection->Resource);
|
||||
ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Save client context pointer */
|
||||
Connection->ClientContext = ClientContext;
|
||||
|
@ -126,9 +154,8 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
|
|||
UINT Family, UINT Type, UINT Proto )
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Called: Connection %x, Family %d, Type %d, "
|
||||
"Proto %d, sizeof(CONNECTION_ENDPOINT) = %d\n",
|
||||
|
@ -140,7 +167,7 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
|
|||
else
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Leaving. Status = 0x%x\n", Status));
|
||||
|
||||
|
@ -149,15 +176,13 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
|
|||
|
||||
NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection )
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
FlushAllQueues(Connection, STATUS_CANCELLED);
|
||||
|
||||
LibTCPClose(Connection, FALSE, TRUE);
|
||||
UnlockObject(Connection);
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
LibTCPClose(Connection, FALSE, TRUE);
|
||||
|
||||
DereferenceObject(Connection);
|
||||
|
||||
|
@ -287,7 +312,6 @@ NTSTATUS TCPConnect
|
|||
TA_IP_ADDRESS LocalAddress;
|
||||
PTDI_BUCKET Bucket;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
KIRQL OldIrql;
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));
|
||||
|
||||
|
@ -308,11 +332,11 @@ NTSTATUS TCPConnect
|
|||
RemoteAddress.Address.IPv4Address,
|
||||
RemotePort));
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (!Connection->AddressFile)
|
||||
{
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -320,7 +344,7 @@ NTSTATUS TCPConnect
|
|||
{
|
||||
if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
|
||||
{
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
return STATUS_NETWORK_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
@ -335,48 +359,51 @@ NTSTATUS TCPConnect
|
|||
&bindaddr,
|
||||
Connection->AddressFile->Port));
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Copy bind address into connection */
|
||||
Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
|
||||
/* Check if we had an unspecified port */
|
||||
if (!Connection->AddressFile->Port)
|
||||
{
|
||||
/* We did, so we need to copy back the port */
|
||||
Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Allocate the port in the port bitmap */
|
||||
Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
|
||||
|
||||
/* This should never fail */
|
||||
ASSERT(Connection->AddressFile->Port != 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
connaddr.addr = RemoteAddress.Address.IPv4Address;
|
||||
|
||||
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
|
||||
if (!Bucket)
|
||||
{
|
||||
UnlockObject(Connection, OldIrql);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
|
||||
Bucket->Request.RequestContext = Context;
|
||||
|
||||
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
|
||||
|
||||
Status = TCPTranslateError(LibTCPConnect(Connection,
|
||||
&connaddr,
|
||||
RemotePort));
|
||||
}
|
||||
UnlockObject(Connection);
|
||||
return Status;
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
/* Copy bind address into connection */
|
||||
Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
|
||||
/* Check if we had an unspecified port */
|
||||
if (!Connection->AddressFile->Port)
|
||||
{
|
||||
/* We did, so we need to copy back the port */
|
||||
Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
UnlockObject(Connection);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Allocate the port in the port bitmap */
|
||||
Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
|
||||
|
||||
/* This should never fail */
|
||||
ASSERT(Connection->AddressFile->Port != 0xFFFF);
|
||||
}
|
||||
|
||||
connaddr.addr = RemoteAddress.Address.IPv4Address;
|
||||
|
||||
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
|
||||
if (!Bucket)
|
||||
{
|
||||
UnlockObject(Connection);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
|
||||
Bucket->Request.RequestContext = Context;
|
||||
|
||||
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
|
||||
|
||||
UnlockObject(Connection);
|
||||
|
||||
Status = TCPTranslateError(LibTCPConnect(Connection,
|
||||
&connaddr,
|
||||
RemotePort));
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status));
|
||||
|
||||
|
@ -394,12 +421,11 @@ NTSTATUS TCPDisconnect
|
|||
{
|
||||
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
||||
PTDI_BUCKET Bucket;
|
||||
KIRQL OldIrql;
|
||||
LARGE_INTEGER ActualTimeout;
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (Connection->SocketContext)
|
||||
{
|
||||
|
@ -407,12 +433,20 @@ NTSTATUS TCPDisconnect
|
|||
{
|
||||
if (IsListEmpty(&Connection->SendRequest))
|
||||
{
|
||||
ReferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
|
||||
LockObject(Connection);
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
else if (Timeout && Timeout->QuadPart == 0)
|
||||
{
|
||||
FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
|
||||
TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
|
||||
FlushSendQueue(Connection, STATUS_FILE_CLOSED);
|
||||
ReferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
LibTCPShutdown(Connection, 0, 1);
|
||||
LockObject(Connection);
|
||||
DereferenceObject(Connection);
|
||||
Status = STATUS_TIMEOUT;
|
||||
}
|
||||
else
|
||||
|
@ -431,7 +465,7 @@ NTSTATUS TCPDisconnect
|
|||
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
|
||||
if (!Bucket)
|
||||
{
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -441,11 +475,11 @@ NTSTATUS TCPDisconnect
|
|||
InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
|
||||
|
||||
ReferenceObject(Connection);
|
||||
if (KeCancelTimer(&Connection->DisconnectTimer))
|
||||
if (KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc))
|
||||
{
|
||||
/* Timer was already in the queue. */
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);
|
||||
|
||||
Status = STATUS_PENDING;
|
||||
}
|
||||
|
@ -453,20 +487,26 @@ NTSTATUS TCPDisconnect
|
|||
|
||||
if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
|
||||
{
|
||||
FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE);
|
||||
FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
|
||||
FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE);
|
||||
FlushReceiveQueue(Connection, STATUS_FILE_CLOSED);
|
||||
FlushSendQueue(Connection, STATUS_FILE_CLOSED);
|
||||
FlushShutdownQueue(Connection, STATUS_FILE_CLOSED);
|
||||
ReferenceObject(Connection);
|
||||
UnlockObject(Connection);
|
||||
Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1));
|
||||
DereferenceObject(Connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnlockObject(Connection);
|
||||
/* We already got closed by the other side so just return success */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", Status));
|
||||
|
||||
return Status;
|
||||
|
@ -506,7 +546,9 @@ NTSTATUS TCPReceiveData
|
|||
Bucket->Request.RequestNotifyObject = Complete;
|
||||
Bucket->Request.RequestContext = Context;
|
||||
|
||||
ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
|
||||
LockObject(Connection);
|
||||
InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry );
|
||||
UnlockObject(Connection);
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n"));
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = STATUS_PENDING\n"));
|
||||
|
@ -532,9 +574,8 @@ NTSTATUS TCPSendData
|
|||
{
|
||||
NTSTATUS Status;
|
||||
PTDI_BUCKET Bucket;
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
ReferenceObject(Connection);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket %x)\n",
|
||||
SendLength, Connection->SocketContext));
|
||||
|
@ -558,7 +599,7 @@ NTSTATUS TCPSendData
|
|||
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
|
||||
if (!Bucket)
|
||||
{
|
||||
UnlockObject(Connection, OldIrql);
|
||||
DereferenceObject(Connection);
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate bucket\n"));
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
@ -566,13 +607,15 @@ NTSTATUS TCPSendData
|
|||
Bucket->Request.RequestNotifyObject = Complete;
|
||||
Bucket->Request.RequestContext = Context;
|
||||
|
||||
LockObject(Connection);
|
||||
InsertTailList( &Connection->SendRequest, &Bucket->Entry );
|
||||
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
|
||||
TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", Status));
|
||||
DereferenceObject(Connection);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -606,13 +649,12 @@ NTSTATUS TCPGetSockAddress
|
|||
PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
|
||||
struct ip_addr ipaddr;
|
||||
NTSTATUS Status;
|
||||
KIRQL OldIrql;
|
||||
|
||||
AddressIP->TAAddressCount = 1;
|
||||
AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
||||
AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (GetRemote)
|
||||
{
|
||||
|
@ -627,7 +669,7 @@ NTSTATUS TCPGetSockAddress
|
|||
&AddressIP->Address[0].Address[0].sin_port));
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
|
||||
AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
|
||||
|
||||
|
@ -641,7 +683,6 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
|
|||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PLIST_ENTRY ListHead[5];
|
||||
KIRQL OldIrql;
|
||||
PTDI_BUCKET Bucket;
|
||||
UINT i = 0;
|
||||
BOOLEAN Found = FALSE;
|
||||
|
@ -652,7 +693,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
|
|||
ListHead[3] = &Endpoint->ListenRequest;
|
||||
ListHead[4] = &Endpoint->ShutdownRequest;
|
||||
|
||||
LockObject(Endpoint, &OldIrql);
|
||||
LockObject(Endpoint);
|
||||
|
||||
for( i = 0; i < 5; i++ )
|
||||
{
|
||||
|
@ -671,7 +712,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
|
|||
}
|
||||
}
|
||||
|
||||
UnlockObject(Endpoint, OldIrql);
|
||||
UnlockObject(Endpoint);
|
||||
|
||||
return Found;
|
||||
}
|
||||
|
|
|
@ -171,9 +171,8 @@ NTSTATUS UDPSendDatagram(
|
|||
USHORT RemotePort;
|
||||
NTSTATUS Status;
|
||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||
KIRQL OldIrql;
|
||||
|
||||
LockObject(AddrFile, &OldIrql);
|
||||
LockObject(AddrFile);
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
|
||||
AddrFile, ConnInfo, BufferData, DataSize));
|
||||
|
@ -188,7 +187,7 @@ NTSTATUS UDPSendDatagram(
|
|||
break;
|
||||
|
||||
default:
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -200,7 +199,7 @@ NTSTATUS UDPSendDatagram(
|
|||
* interface we're sending over
|
||||
*/
|
||||
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_NETWORK_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
@ -209,7 +208,7 @@ NTSTATUS UDPSendDatagram(
|
|||
else
|
||||
{
|
||||
if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) {
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +222,7 @@ NTSTATUS UDPSendDatagram(
|
|||
BufferData,
|
||||
DataSize );
|
||||
|
||||
UnlockObject(AddrFile, OldIrql);
|
||||
UnlockObject(AddrFile);
|
||||
|
||||
if( !NT_SUCCESS(Status) )
|
||||
return Status;
|
||||
|
|
|
@ -31,6 +31,9 @@ struct lwip_callback_msg
|
|||
struct {
|
||||
PVOID Arg;
|
||||
} Socket;
|
||||
struct {
|
||||
struct tcp_pcb* pcb;
|
||||
} FreeSocket;
|
||||
struct {
|
||||
PCONNECTION_ENDPOINT Connection;
|
||||
struct ip_addr *IpAddress;
|
||||
|
@ -99,6 +102,7 @@ extern void TCPRecvEventHandler(void *arg);
|
|||
|
||||
/* TCP functions */
|
||||
PTCP_PCB LibTCPSocket(void *arg);
|
||||
VOID LibTCPFreeSocket(PTCP_PCB pcb);
|
||||
err_t LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const ipaddr, const u16_t port);
|
||||
PTCP_PCB LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog);
|
||||
err_t LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe);
|
||||
|
|
|
@ -81,7 +81,9 @@ void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, struct pbuf *p)
|
|||
qp->p = p;
|
||||
qp->Offset = 0;
|
||||
|
||||
ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry, &Connection->Lock);
|
||||
LockObject(Connection);
|
||||
InsertTailList(&Connection->PacketQueue, &qp->ListEntry);
|
||||
UnlockObject(Connection);
|
||||
}
|
||||
|
||||
PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection)
|
||||
|
@ -104,11 +106,10 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
|
|||
struct pbuf* p;
|
||||
NTSTATUS Status;
|
||||
UINT ReadLength, PayloadLength, Offset, Copied;
|
||||
KIRQL OldIrql;
|
||||
|
||||
(*Received) = 0;
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
LockObject(Connection);
|
||||
|
||||
if (!IsListEmpty(&Connection->PacketQueue))
|
||||
{
|
||||
|
@ -132,13 +133,9 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
|
|||
qp = NULL;
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
|
||||
Copied = pbuf_copy_partial(p, RecvBuffer, ReadLength, Offset);
|
||||
ASSERT(Copied == ReadLength);
|
||||
|
||||
LockObject(Connection, &OldIrql);
|
||||
|
||||
/* Update trackers */
|
||||
RecvLen -= ReadLength;
|
||||
RecvBuffer += ReadLength;
|
||||
|
@ -172,7 +169,7 @@ NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
|
|||
Status = STATUS_PENDING;
|
||||
}
|
||||
|
||||
UnlockObject(Connection, OldIrql);
|
||||
UnlockObject(Connection);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -364,6 +361,33 @@ LibTCPSocket(void *arg)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
LibTCPFreeSocketCallback(void *arg)
|
||||
{
|
||||
struct lwip_callback_msg *msg = arg;
|
||||
|
||||
ASSERT(msg);
|
||||
|
||||
/* Calling tcp_close will free it */
|
||||
tcp_close(msg->Input.FreeSocket.pcb);
|
||||
|
||||
KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
void LibTCPFreeSocket(PTCP_PCB pcb)
|
||||
{
|
||||
struct lwip_callback_msg msg;
|
||||
|
||||
KeInitializeEvent(&msg.Event, NotificationEvent, FALSE);
|
||||
msg.Input.FreeSocket.pcb = pcb;
|
||||
|
||||
tcpip_callback_with_block(LibTCPFreeSocketCallback, &msg, 1);
|
||||
|
||||
WaitForEventSafely(&msg.Event);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
LibTCPBindCallback(void *arg)
|
||||
|
|
Loading…
Reference in a new issue