Author: zhu
Date: Fri Jul 1 19:37:51 2016
New Revision: 71713
URL:
http://svn.reactos.org/svn/reactos?rev=71713&view=rev
Log:
State variables implemented. A QueryNdisBuffer macro is expanded out in my code because
I'm trying to chase down a page fault that happens during that particular call.
Modified:
branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c
branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c
branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h
Modified: branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/base/appli…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c [iso-8859-1]
(original)
+++ branches/GSoC_2016/lwIP-tcpip/base/applications/network/tcpserver/main.c [iso-8859-1]
Fri Jul 1 19:37:51 2016
@@ -63,7 +63,7 @@
exit(1);
} else {
printf("Socket connection accepted\n");
- ret = recv(accepted, &buff[0], 256, MSG_OOB);
+ ret = recv(accepted, &buff[0], 256, 0);
printf("Received %d bytes\n", ret);
printf("Message: %s", &buff[0]);
}
Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c [iso-8859-1] Fri Jul 1
19:37:51 2016
@@ -30,11 +30,12 @@
static LIST_ENTRY AddressListHead;
/* implementation in testing */
-PTCP_REQUEST
+NTSTATUS
PrepareIrpForCancel(
PIRP Irp,
PDRIVER_CANCEL CancelRoutine,
- UCHAR CancelMode
+ UCHAR CancelMode,
+ UCHAR PendingMode
)
{
PIO_STACK_LOCATION IrpSp;
@@ -51,21 +52,31 @@
Request = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Request), TAG_TCP_REQUEST);
if (!Request)
{
- return NULL;
- }
- Request->PendingIrp = Irp;
- Request->CancelMode = CancelMode;
+ DPRINT1("Allocation failed, out of memory\n");
+ IoReleaseCancelSpinLock(OldIrql);
+
+ return STATUS_NO_MEMORY;
+ }
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext;
+
+ Request->PendingIrp = Irp;
+ Request->Context = Context;
+ Request->CancelMode = CancelMode;
+ Request->PendingMode = PendingMode;
+
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
InsertTailList(&Context->RequestListHead, &Request->ListEntry);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+
IoSetCancelRoutine(Irp, CancelRoutine);
IoReleaseCancelSpinLock(OldIrql);
DPRINT1("Prepared for cancel\n");
-
- return Request;
+
+ return STATUS_SUCCESS;
}
DPRINT1("Already cancelled\n");
@@ -75,7 +86,7 @@
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
- return NULL;
+ return STATUS_CANCELLED;
}
/* implementation in testing */
@@ -89,13 +100,13 @@
{
PIO_STACK_LOCATION IrpSp;
PTCP_CONTEXT Context;
+ PADDRESS_FILE AddressFile;
PLIST_ENTRY Head;
PLIST_ENTRY Entry;
PTCP_REQUEST Request;
- UCHAR MinorFunction;
KIRQL OldIrql;
- DPRINT1("IRP Cancel\n");
+ DPRINT1("IRP Cancel on IRP at %08x\n", Irp);
IoReleaseCancelSpinLock(Irp->CancelIrql);
@@ -113,32 +124,13 @@
}
TCP_CANCEL:
- MinorFunction = IrpSp->MinorFunction;
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
- switch(MinorFunction)
- {
- case TDI_LISTEN:
- DPRINT1("TDI_LISTEN Cancel\n");
- Context->AddressFile->ConnectionContext->lwip_tcp_pcb = NULL;
- break;
- case TDI_SEND:
- DPRINT1("TDI_SEND Cancel\n");
- break;
- case TDI_CONNECT:
- DPRINT1("TDI_CONNECT Cancel\n");
- break;
- case TDI_RECEIVE:
- DPRINT1("TDI_RECEIVE Cancel\n");
- break;
- case TDI_DISCONNECT:
- DPRINT1("TDI_DISCONNECT Cancel\n");
- break;
- default:
- DPRINT1("Invalid MinorFunction for TCP_CANCEL\n");
- goto FINISH;
- }
-
+
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
+
+ AddressFile = Context->AddressFile;
+ DPRINT1("AddressFile at %08x\n", AddressFile);
Head = &Context->RequestListHead;
Entry = Head->Flink;
while (Entry != Head)
@@ -146,29 +138,65 @@
Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
if (Request->PendingIrp == Irp)
{
- DPRINT1("Found matching request\n");
switch (Request->CancelMode)
{
- case TCP_REQUEST_CANCEL_MODE_ABORT:
+ case TCP_REQUEST_CANCEL_MODE_ABORT :
+ if (Context->lwip_tcp_pcb == AddressFile->lwip_tcp_pcb)
+ {
+ AddressFile->lwip_tcp_pcb = NULL;
+ }
tcp_abort(Context->lwip_tcp_pcb);
+ Context->lwip_tcp_pcb = NULL;
+
+ RemoveEntryList(Entry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ if (!IsListEmpty(&Context->RequestListHead))
+ {
+ DPRINT1("Aborting PCB with outstanding requests\n");
+ }
+
break;
- case TCP_REQUEST_CANCEL_MODE_CLOSE:
+
+ case TCP_REQUEST_CANCEL_MODE_CLOSE :
+ if (Context->lwip_tcp_pcb == AddressFile->lwip_tcp_pcb)
+ {
+ AddressFile->lwip_tcp_pcb = NULL;
+ }
tcp_close(Context->lwip_tcp_pcb);
+ Context->lwip_tcp_pcb = NULL;
+
+ RemoveEntryList(Entry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ if (!IsListEmpty(&Context->RequestListHead))
+ {
+ DPRINT1("Closing PCB with outstanding requests\n");
+ }
+
+ break;
+
+ case TCP_REQUEST_CANCEL_MODE_PRESERVE :
+ RemoveEntryList(Entry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ break;
+ default :
+ DPRINT1("Invalid request cancel mode\n");
break;
}
- Context->lwip_tcp_pcb = NULL;
- Request->PendingIrp = NULL;
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
goto FINISH;
}
Entry = Entry->Flink;
}
- DPRINT1("No matching TCP_REQUEST found\n");
+ DPRINT1("Matching TCP_REQUEST not found\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
goto FINISH;
DGRAM_CANCEL:
DPRINT1("DGRAM_CANCEL\n");
FINISH:
+ DPRINT1("\n Minor Function: %08x\n", IrpSp->MinorFunction);
+
IoAcquireCancelSpinLock(&OldIrql);
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(OldIrql);
@@ -193,6 +221,153 @@
_In_ PTDI_ADDRESS_IP Address)
{
return ((Address->in_addr == 0) || (Address->in_addr == 0xFFFFFFFF));
+}
+
+/* Implementation in testing */
+void
+lwip_tcp_err_callback(
+ void *arg,
+ err_t err)
+{
+ PADDRESS_FILE AddressFile;
+ PTCP_CONTEXT Context;
+ PTCP_REQUEST Request;
+ PLIST_ENTRY Head;
+ PLIST_ENTRY HeadNest;
+ PLIST_ENTRY EntryNest;
+ PLIST_ENTRY Entry;
+ PLIST_ENTRY Temp;
+ PIRP Irp;
+ KIRQL OldIrql;
+ KIRQL CancelIrql;
+
+ NTSTATUS Status;
+
+ switch (err)
+ {
+ case ERR_ABRT :
+ DPRINT1("lwIP socket aborted\n");
+ break;
+ case ERR_RST :
+ DPRINT1("lwIP socket reset\n");
+ break;
+ case ERR_CLSD :
+ DPRINT1("lwIP socket closed\n");
+ break;
+ case ERR_CONN :
+ DPRINT1("lwIP connection failed\n");
+ break;
+ case ERR_ARG :
+ DPRINT1("lwIP invalid arguments\n");
+ break;
+ case ERR_IF :
+ DPRINT1("Low=level error\n");
+ break;
+ default :
+ DPRINT1("Unsupported lwIP error code: %d\n", err);
+ break;
+ }
+
+ Status = STATUS_ADDRESS_CLOSED;
+
+ switch (*((UCHAR*)arg))
+ {
+ case TDI_TRANSPORT_ADDRESS_FILE :
+ AddressFile = (PADDRESS_FILE)arg;
+ DPRINT1("AddressFile at %08x\n", AddressFile);
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+
+ Head = &AddressFile->ContextListHead;
+ Entry = Head->Flink;
+ while (Entry != Head)
+ {
+ Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
+ HeadNest = &Context->RequestListHead;
+ EntryNest = HeadNest->Flink;
+ while (EntryNest != HeadNest)
+ {
+ Request = CONTAINING_RECORD(EntryNest, TCP_REQUEST, ListEntry);
+ Irp = Request->PendingIrp;
+ if (Irp)
+ {
+ if (Irp->Cancel)
+ {
+ IoAcquireCancelSpinLock(&CancelIrql);
+ Irp->Cancel = FALSE;
+ IoSetCancelRoutine(Irp, NULL);
+ IoReleaseCancelSpinLock(CancelIrql);
+ }
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+ }
+ Temp = EntryNest->Flink;
+ RemoveEntryList(EntryNest);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ EntryNest = Temp;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+
+ if (Context->lwip_tcp_pcb != AddressFile->lwip_tcp_pcb)
+ {
+ tcp_close(Context->lwip_tcp_pcb);
+ }
+ Context->lwip_tcp_pcb = NULL;
+
+ Entry = Entry->Flink;
+ }
+
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+
+ AddressFile->lwip_tcp_pcb = NULL;
+
+ return;
+ case TDI_CONNECTION_FILE :
+ Context = (PTCP_CONTEXT)arg;
+ DPRINT1("AddressFile at %08x\n", Context->AddressFile);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
+ HeadNest = &Context->RequestListHead;
+ EntryNest = HeadNest->Flink;
+ while (EntryNest != HeadNest)
+ {
+ Request = CONTAINING_RECORD(EntryNest, TCP_REQUEST, ListEntry);
+ Irp = Request->PendingIrp;
+ if (Irp)
+ {
+ if (Irp->Cancel)
+ {
+ IoAcquireCancelSpinLock(&CancelIrql);
+ Irp->Cancel = FALSE;
+ IoSetCancelRoutine(Irp, NULL);
+ IoReleaseCancelSpinLock(CancelIrql);
+ }
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+ }
+ Temp = EntryNest->Flink;
+ RemoveEntryList(EntryNest);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ EntryNest = Temp;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+
+ if (Context->lwip_tcp_pcb != Context->AddressFile->lwip_tcp_pcb)
+ {
+ tcp_close(Context->lwip_tcp_pcb);
+ }
+ Context->lwip_tcp_pcb = NULL;
+
+ return;
+ default :
+ DPRINT1("Invalid argument\n");
+ return;
+ }
}
static
@@ -302,71 +477,67 @@
struct tcp_pcb *newpcb,
err_t err)
{
- PIRP Irp;
KIRQL OldIrql;
- PTCP_REQUEST Request;
PADDRESS_FILE AddressFile;
PTCP_CONTEXT Context;
+ PTCP_REQUEST Request;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
PLIST_ENTRY Head;
PLIST_ENTRY Entry;
DPRINT1("lwIP TCP Accept Callback\n");
+ IoAcquireCancelSpinLock(&OldIrql);
AddressFile = (PADDRESS_FILE)arg;
- if (AddressFile->TcpState != TCP_STATE_LISTENING)
- {
- DPRINT1("Accept callback on an address file that's not listening\n");
- return ERR_ABRT;
- }
- Head = &AddressFile->ConnectionContext->ListEntry;
- Entry = Head->Blink;
- Irp = NULL;
+ KeAcquireSpinLockAtDpcLevel(&AddressFile->ContextListLock);
+
+ Head = &AddressFile->ContextListHead;
+ Entry = Head->Flink;
while (Entry != Head)
{
Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry);
- if (Context->lwip_tcp_pcb == AddressFile->ConnectionContext->lwip_tcp_pcb)
- {
- if (IsListEmpty(&Context->RequestListHead))
+ if (Context->TcpState == TCP_STATE_LISTENING)
+ {
+ KeReleaseSpinLockFromDpcLevel(&AddressFile->ContextListLock);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
+ Context->lwip_tcp_pcb = newpcb;
+ Context->TcpState = TCP_STATE_ACCEPTED;
+ tcp_accepted(AddressFile->lwip_tcp_pcb);
+ Head = &Context->RequestListHead;
+ Entry = Head->Flink;
+
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ Irp = Request->PendingIrp;
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ if (!Irp || IrpSp->MinorFunction != TDI_LISTEN)
{
- DPRINT1("Context has empty request list\n");
- return ERR_ABRT;
- }
- Request = CONTAINING_RECORD(Context->RequestListHead.Flink,
- TCP_REQUEST, ListEntry);
- Irp = Request->PendingIrp;
- if (!Irp)
- {
- DPRINT1("Request has been cancelled\n");
- RemoveEntryList(&Request->ListEntry);
+ DPRINT1("Received callback for canceld TDI_LISTEN\n");
+ RemoveEntryList(Entry);
+ Entry = Entry->Flink;
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
return ERR_ABRT;
}
- break;
- }
- Entry = Entry->Blink;
- }
- if (!Irp)
- {
- DPRINT1("Could not find a listening tcp_pcb\n");
- return ERR_ABRT;
- }
-
- IoAcquireCancelSpinLock(&OldIrql);
- IoSetCancelRoutine(Irp, NULL);
- Irp->Cancel = FALSE;
+
+ IoSetCancelRoutine(Irp, NULL);
+ Irp->Cancel = FALSE;
+
+ IoReleaseCancelSpinLock(OldIrql);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ return ERR_OK;
+ }
+ Entry = Entry->Flink;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&AddressFile->ContextListLock);
IoReleaseCancelSpinLock(OldIrql);
- Context->lwip_tcp_pcb = newpcb;
- tcp_accepted(AddressFile->ConnectionContext->lwip_tcp_pcb);
- RemoveEntryList(&Request->ListEntry);
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-
- ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
-
- return ERR_OK;
+ return ERR_ABRT;
}
/* implementation in testing */
@@ -379,34 +550,96 @@
)
{
PTCP_REQUEST Request;
+ PTCP_CONTEXT Context;
+ PLIST_ENTRY Head;
+ PLIST_ENTRY Entry;
+ PLIST_ENTRY Temp;
PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
KIRQL OldIrql;
+ PVOID Buffer;
+ PTDI_REQUEST_KERNEL_SEND RequestInfo;
+ UINT Len;
+
+ err_t lwip_err;
+
DPRINT1("lwIP TCP Sent Callback\n");
- Request = (PTCP_REQUEST)arg;
- Irp = Request->PendingIrp;
+ Context = (PTCP_CONTEXT)arg;
+ IoAcquireCancelSpinLock(&OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
+ Head = &Context->RequestListHead;
+ Entry = Head->Flink;
+ while (Entry != Head)
+ {
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ if (Request->PendingMode == TCP_REQUEST_PENDING_SEND)
+ {
+ Irp = Request->PendingIrp;
+ Entry = Entry->Flink;
+ goto FOUND;
+ }
+ Entry = Entry->Flink;
+ }
+ DPRINT1("Matching TDI_SEND request not found\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+ return ERR_ABRT;
+FOUND:
if (!Irp)
{
DPRINT1("Callback on cancelled IRP\n");
RemoveEntryList(&Request->ListEntry);
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
return ERR_ABRT;
}
- IoAcquireCancelSpinLock(&OldIrql);
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext;
+
IoSetCancelRoutine(Irp, NULL);
Irp->Cancel = FALSE;
- IoReleaseCancelSpinLock(OldIrql);
-
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = len;
+
+ RemoveEntryList(&Request->ListEntry);
+
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+
+ lwip_err = ERR_OK;
+ while (Entry != Head)
+ {
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ if (Request->PendingMode == TCP_REQUEST_PENDING_SEND)
+ {
+ Irp = Request->PendingIrp;
+ if (!Irp)
+ {
+ Temp = Entry->Flink;
+ RemoveEntryList(Entry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ Entry = Temp;
+ continue;
+ }
+ NdisQueryBuffer(Irp->MdlAddress, &Buffer, &Len);
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ RequestInfo = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters;
+ lwip_err = tcp_write(Context->lwip_tcp_pcb, Buffer, RequestInfo->SendLength,
0);
+ break;
+ }
+ Entry = Entry->Flink;
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
- RemoveEntryList(&Request->ListEntry);
- ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
-
- return ERR_OK;
+ return lwip_err;
}
/* This implementation does not take into account any flags */
@@ -432,6 +665,8 @@
INT RemainingSrceBytes;
UCHAR *CurrentDestLocation;
UCHAR *CurrentSrceLocation;
+ PLIST_ENTRY Head;
+ PLIST_ENTRY Entry;
DPRINT1("lwIP TCP Receive Callback\n");
@@ -441,43 +676,98 @@
return ERR_ABRT;
}
- Request = (PTCP_REQUEST)arg;
- Irp = Request->PendingIrp;
+ IoAcquireCancelSpinLock(&OldIrql);
+
+ Context = (PTCP_CONTEXT)arg;
+ DPRINT1("Context at %08x\n", Context);
+ DPRINT1("AddressFile at %08x\n", Context->AddressFile);
+ if (!(Context->TcpState & TCP_STATE_RECEIVING))
+ {
+ DPRINT1("Receive callback on connection that is not currently receiving\n");
+ IoReleaseCancelSpinLock(OldIrql);
+ return ERR_ARG;
+ }
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+ Head = &Context->RequestListHead;
+ Entry = Head->Flink;
+ Irp = NULL;
+ while (Entry != Head)
+ {
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ if (!Request->PendingIrp)
+ {
+ RemoveEntryList(Entry);
+ Entry = Entry->Flink;
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+ continue;
+ }
+ if (Request->PendingMode == TCP_REQUEST_PENDING_RECEIVE)
+ {
+ Irp = Request->PendingIrp;
+ Entry = Entry->Flink;
+ break;
+ }
+ Entry = Entry->Flink;
+ }
if (!Irp)
{
- DPRINT1("Callback on cancelled IRP\n");
+ DPRINT1("Receive callback on cancelled IRP\n");
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+ return ERR_ABRT;
+ }
+ DPRINT1("IRP at %08x\n", Irp);
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ IoSetCancelRoutine(Irp, NULL);
+ Irp->Cancel = FALSE;
+
+ if (Context->lwip_tcp_pcb != tpcb)
+ {
+ DPRINT1("Receive tcp_pcb mismatch\n");
+ tcp_abort(tpcb);
+
RemoveEntryList(&Request->ListEntry);
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
- return ERR_ABRT;
- }
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
- Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext;
- if (Context->lwip_tcp_pcb != tpcb)
- {
- DPRINT1("Receive tcp_pcb mismatch\n");
- tcp_abort(tpcb);
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
- RemoveEntryList(&Request->ListEntry);
- ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+
return ERR_ABRT;
}
- if (!(Context->AddressFile->TcpState &
(TCP_STATE_LISTENING|TCP_STATE_CONNECTED)))
- {
- DPRINT1("Invalid TCP state\n");
+ if (!(Context->TcpState &
(TCP_STATE_RECEIVING|TCP_STATE_ACCEPTED|TCP_STATE_CONNECTED)))
+ {
+ DPRINT1("Invalid TCP state: %08x\n", Context->TcpState);
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+
return ERR_ABRT;
}
-
- IoAcquireCancelSpinLock(&OldIrql);
- IoSetCancelRoutine(Irp, NULL);
- Irp->Cancel = FALSE;
- IoReleaseCancelSpinLock(OldIrql);
Buffer = (PNDIS_BUFFER)Irp->MdlAddress;
ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
- NdisQueryBuffer(Buffer, &CurrentDestLocation, &RemainingDestBytes);
+ DPRINT1("NDIS Buffer: %08x\n", Buffer);
+
+ if (Buffer->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA|MDL_SOURCE_IS_NONPAGED_POOL))
+ {
+ DPRINT1("Option 0\n");
+ CurrentDestLocation = Buffer->MappedSystemVa;
+ }
+ else
+ {
+ DPRINT1("Option 1\n");
+ CurrentDestLocation = MmMapLockedPages(Buffer, KernelMode);
+ }
+// CurrentDestLocation = MmGetSystemAddressForMdl(Buffer);
+ RemainingDestBytes = Buffer->ByteCount;
+// NdisQueryBuffer(Buffer, &CurrentDestLocation, &RemainingDestBytes);
DPRINT1("\n PTDI_REQUEST_KERNEL_RECEIVE->ReceiveLength = %d\n NDIS_BUFFER
length = %d\n pbuf->tot_len = %d\n",
ReceiveInfo->ReceiveLength,
@@ -535,13 +825,26 @@
DPRINT1("Receive CopiedLength = %d\n", CopiedLength);
tcp_recved(tpcb, CopiedLength);
+
+ RemoveEntryList(&Request->ListEntry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+
+ while (Entry != Head)
+ {
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ if (Request->PendingMode == TCP_REQUEST_PENDING_RECEIVE)
+ {
+ tcp_recv(tpcb, lwip_tcp_receive_callback);
+ break;
+ }
+ }
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = CopiedLength;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-
- RemoveEntryList(&Request->ListEntry);
- ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
return ERR_OK;
}
@@ -601,43 +904,65 @@
{
PTCP_REQUEST Request;
PTCP_CONTEXT Context;
- PADDRESS_FILE AddressFile;
- PIO_STACK_LOCATION IrpSp;
PIRP Irp;
KIRQL OldIrql;
+ PLIST_ENTRY Head;
+ PLIST_ENTRY Entry;
DPRINT1("lwIP TCP Connected Callback\n");
- Request = (PTCP_REQUEST)arg;
+ IoAcquireCancelSpinLock(&OldIrql);
+
+ Context = (PTCP_CONTEXT)arg;
+ Head = &Context->RequestListHead;
+ Entry = Head->Flink;
+ if (Head == Entry)
+ {
+ DPRINT1("Request list is empty\n");
+ return ERR_ARG;
+ }
+ Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
Irp = Request->PendingIrp;
if (!Irp)
{
DPRINT1("Callback on cancelled IRP\n");
+
+ KeAcquireSpinLockAtDpcLevel(&Request->Context->RequestListLock);
+
RemoveEntryList(&Request->ListEntry);
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+
+ KeReleaseSpinLockFromDpcLevel(&Request->Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+
return ERR_ABRT;
}
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
- Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext;
- AddressFile = Context->AddressFile;
- if (AddressFile->TcpState != TCP_STATE_CONNECTING)
- {
- DPRINT1("Invalid TCP state\n");
- }
-
- IoAcquireCancelSpinLock(&OldIrql);
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+
+ if (Context->TcpState != TCP_STATE_CONNECTING)
+ {
+ DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+ IoReleaseCancelSpinLock(OldIrql);
+
+ return ERR_ABRT;
+ }
+
+ Context->TcpState = TCP_STATE_CONNECTED;
+
IoSetCancelRoutine(Irp, NULL);
Irp->Cancel = FALSE;
+
+ RemoveEntryList(&Request->ListEntry);
+ ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
+
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
IoReleaseCancelSpinLock(OldIrql);
-
- AddressFile->TcpState = TCP_STATE_CONNECTED;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-
- RemoveEntryList(&Request->ListEntry);
- ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
return ERR_OK;
}
@@ -652,25 +977,10 @@
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PADDRESS_FILE AddressFile;
- PTCP_CONTEXT TcpContext;
LIST_ENTRY* ListEntry;
KIRQL OldIrql;
-// ULONG *temp;
-
USHORT Port = 1;
-
-/* temp = (ULONG*)Address;
- DPRINT1("\n TcpIpCreateAddress Input Dump\n %08x %08x %08x %08x\n",
- temp[3], temp[2],
- temp[1], temp[0]);
-
- temp = IrpSp->FileObject->FsContext;
- if (temp) {
- DPRINT1("\n IrpSp Dump\n %08x %08x %08x %08x\n %08x %08x %08x %08x\n",
- temp[7], temp[6], temp[5], temp[4],
- temp[3], temp[2], temp[1], temp[0]);
- }*/
/* See if this port is already taken, and find a free one if needed. */
KeAcquireSpinLock(&AddressListLock, &OldIrql);
@@ -744,10 +1054,12 @@
AddressFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(*AddressFile),
TAG_ADDRESS_FILE);
if (!AddressFile)
{
+ KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_NO_MEMORY;
}
RtlZeroMemory(AddressFile, sizeof(*AddressFile));
+ AddressFile->Type = TDI_TRANSPORT_ADDRESS_FILE;
AddressFile->RefCount = 1;
RtlCopyMemory(&AddressFile->Address, Address, sizeof(*Address));
AddressFile->Protocol = Protocol;
@@ -766,16 +1078,10 @@
ip_addr_t IpAddr;
ip4_addr_set_u32(&IpAddr, AddressFile->Address.in_addr);
InsertEntityInstance(CO_TL_ENTITY, &AddressFile->Instance);
- AddressFile->TcpState = TCP_STATE_CREATED;
- TcpContext
- = ExAllocatePoolWithTag(NonPagedPool, sizeof(TCP_CONTEXT), TAG_TCP_CONTEXT);
- InitializeListHead(&TcpContext->ListEntry);
- TcpContext->AddressFile = AddressFile;
- TcpContext->Protocol = IPPROTO_TCP;
- InitializeListHead(&TcpContext->RequestListHead);
- TcpContext->lwip_tcp_pcb = tcp_new();
- AddressFile->ConnectionContext = TcpContext;
AddressFile->ContextCount = 0;
+ AddressFile->lwip_tcp_pcb = tcp_new();
+ tcp_arg(AddressFile->lwip_tcp_pcb, AddressFile);
+ tcp_err(AddressFile->lwip_tcp_pcb, lwip_tcp_err_callback);
break;
}
case IPPROTO_UDP:
@@ -848,10 +1154,13 @@
DPRINT1("Creating connection context for non-TCP protocoln");
return STATUS_INVALID_PARAMETER;
}
+ Context->Type = TDI_CONNECTION_FILE;
Context->Protocol = Protocol;
RtlCopyMemory(&Context->RequestAddress, Address, sizeof(*Address));
+ KeInitializeSpinLock(&Context->RequestListLock);
InitializeListHead(&Context->RequestListHead);
Context->lwip_tcp_pcb = NULL;
+ Context->TcpState = TCP_STATE_CREATED;
IrpSp->FileObject->FsContext = (PVOID)Context;
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
@@ -890,25 +1199,26 @@
if (AddressFile->ContextCount != 0)
{
DPRINT1("Calling close on TCP address with open contexts\n");
+ KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
}
- if (AddressFile->ConnectionContext->lwip_tcp_pcb)
+ if (AddressFile->lwip_tcp_pcb)
{
- lwip_err = tcp_close(AddressFile->ConnectionContext->lwip_tcp_pcb);
+ lwip_err = tcp_close(AddressFile->lwip_tcp_pcb);
if (lwip_err != ERR_OK)
{
DPRINT1("lwIP tcp_close error: %d", lwip_err);
+ KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
- AddressFile->ConnectionContext->lwip_tcp_pcb = NULL;
}
- ExFreePoolWithTag(AddressFile->ConnectionContext, TAG_TCP_CONTEXT);
break;
case IPPROTO_RAW :
raw_remove(AddressFile->lwip_raw_pcb);
break;
default :
DPRINT1("Unknown protocol\n");
+ KeReleaseSpinLock(&AddressListLock, OldIrql);
return STATUS_INVALID_ADDRESS;
}
@@ -935,6 +1245,8 @@
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
+ KIRQL OldIrql;
+
if (Context->Protocol != IPPROTO_TCP)
{
DPRINT1("Invalid protocol\n");
@@ -946,12 +1258,15 @@
return STATUS_UNSUCCESSFUL;
}
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
+
if (Context->lwip_tcp_pcb)
{
lwip_err = tcp_close(Context->lwip_tcp_pcb);
if (lwip_err != ERR_OK)
{
DPRINT1("lwIP tcp_close error: %d", lwip_err);
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
}
@@ -968,17 +1283,21 @@
if (IrpSp->FileObject->FsContext != Context)
{
DPRINT1("IRP context mismatch\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
- DPRINT1("Closing outstanding request on context\n");
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+ DPRINT1("Unexpected outstanding request on context\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+ return STATUS_UNSUCCESSFUL;
}
Entry = Entry->Flink;
ExFreePoolWithTag(Request, TAG_TCP_REQUEST);
}
+
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
+
+ ExFreePoolWithTag(Context, TAG_TCP_CONTEXT);
return STATUS_SUCCESS;
}
@@ -1061,7 +1380,6 @@
{
PIO_STACK_LOCATION IrpSp;
PTCP_CONTEXT Context;
- PTCP_REQUEST Request;
PTDI_REQUEST_KERNEL_CONNECT Parameters;
PTRANSPORT_ADDRESS RemoteTransportAddress;
@@ -1080,12 +1398,13 @@
}
Context = IrpSp->FileObject->FsContext;
+ DPRINT1("AddressFile at %08x\n", Context->AddressFile);
if (Context->AddressFile->Protocol != IPPROTO_TCP)
{
DPRINT1("Received TDI_CONNECT for a non-TCP protocol\n");
return STATUS_INVALID_ADDRESS;
}
- if (Context->AddressFile->TcpState != TCP_STATE_BOUND)
+ if (Context->TcpState != TCP_STATE_BOUND)
{
DPRINT1("Connecting on address that's not bound\n");
return STATUS_INVALID_ADDRESS;
@@ -1109,7 +1428,6 @@
(ip_addr_t *)&SocketAddressInRemote->sin_addr.s_addr,
SocketAddressInRemote->sin_port,
lwip_tcp_connected_callback);
-// DPRINT1("lwip error %d\n", lwip_err);
switch (lwip_err)
{
case (ERR_VAL) :
@@ -1148,13 +1466,14 @@
}
case (ERR_OK) :
{
- Request = PrepareIrpForCancel(
+ PrepareIrpForCancel(
Irp,
CancelRequestRoutine,
- TCP_REQUEST_CANCEL_MODE_ABORT);
- tcp_arg(Context->lwip_tcp_pcb, Request);
- Context->AddressFile->TcpState = TCP_STATE_CONNECTING;
- break;
+ TCP_REQUEST_CANCEL_MODE_ABORT,
+ TCP_REQUEST_PENDING_GENERAL);
+ tcp_arg(Context->lwip_tcp_pcb, Context);
+ Context->TcpState = TCP_STATE_CONNECTING;
+ return STATUS_PENDING;
}
default :
{
@@ -1163,8 +1482,6 @@
return STATUS_NOT_IMPLEMENTED;
}
}
-
- return STATUS_PENDING;
}
/* Implementation in testing */
@@ -1180,6 +1497,7 @@
err_t lwip_err;
NTSTATUS Status;
+ KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
@@ -1230,80 +1548,78 @@
if (AddressFile->Address.in_addr == 0)
{
- // should really look through address file list for an interface
+ // TODO: should really look through address file list for an interface
AddressFile->Address.in_addr = 0x0100007f;
}
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+
Context->AddressFile = AddressFile;
- Context->lwip_tcp_pcb = AddressFile->ConnectionContext->lwip_tcp_pcb;
- InsertTailList(&AddressFile->ConnectionContext->ListEntry,
+ InsertTailList(&AddressFile->ContextListHead,
&Context->ListEntry);
AddressFile->ContextCount++;
-
- switch (AddressFile->TcpState)
- {
- case TCP_STATE_CREATED :
- /* Finally calling into lwip to perform socket bind */
- lwip_err = tcp_bind(
- Context->lwip_tcp_pcb,
- (ip_addr_t *)&AddressFile->Address.in_addr,
- AddressFile->Address.sin_port);
- ip_set_option(Context->lwip_tcp_pcb, SOF_BROADCAST);
- DPRINT1("lwip error %d\n TCP PCB:\n Local Address: %08x\n Local Port: %04x\n
Remote Address: %08x\n Remote Port: %04x\n",
- lwip_err,
- Context->lwip_tcp_pcb->local_ip,
- Context->lwip_tcp_pcb->local_port,
- Context->lwip_tcp_pcb->remote_ip,
- Context->lwip_tcp_pcb->remote_port);
- if (lwip_err != ERR_OK)
+ Context->lwip_tcp_pcb = AddressFile->lwip_tcp_pcb;
+
+ if (AddressFile->ContextListHead.Flink == &Context->ListEntry)
+ {
+ DPRINT1("lwIP tcp_bind\n");
+ lwip_err = tcp_bind(
+ Context->lwip_tcp_pcb,
+ (ip_addr_t *)&AddressFile->Address.in_addr,
+ AddressFile->Address.sin_port);
+ ip_set_option(Context->lwip_tcp_pcb, SOF_BROADCAST);
+ DPRINT1("lwip error %d\n TCP PCB:\n Local Address: %08x\n Local Port: %04x\n
Remote Address: %08x\n Remote Port: %04x\n",
+ lwip_err,
+ Context->lwip_tcp_pcb->local_ip,
+ Context->lwip_tcp_pcb->local_port,
+ Context->lwip_tcp_pcb->remote_ip,
+ Context->lwip_tcp_pcb->remote_port);
+ if (lwip_err != ERR_OK)
+ {
+ switch (lwip_err)
{
- switch (lwip_err)
+ case (ERR_BUF) :
{
- case (ERR_BUF) :
- {
- DPRINT1("lwIP ERR_BUFF\n");
- Status = STATUS_NO_MEMORY;
- goto LEAVE;
- }
- case (ERR_VAL) :
- {
- DPRINT1("lwIP ERR_VAL\n");
- Status = STATUS_INVALID_PARAMETER;
- goto LEAVE;
- }
- case (ERR_USE) :
- {
- DPRINT1("lwIP ERR_USE\n");
- Status = STATUS_ADDRESS_ALREADY_EXISTS;
- goto LEAVE;
- }
- case (ERR_OK) :
- {
- DPRINT1("lwIP ERR_OK\n");
- break;
- }
- default :
- {
- DPRINT1("lwIP unexpected error\n");
- Status = STATUS_NOT_IMPLEMENTED;
- goto LEAVE;
- }
+ DPRINT1("lwIP ERR_BUFF\n");
+ Status = STATUS_NO_MEMORY;
+ goto LEAVE;
+ }
+ case (ERR_VAL) :
+ {
+ DPRINT1("lwIP ERR_VAL\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto LEAVE;
+ }
+ case (ERR_USE) :
+ {
+ DPRINT1("lwIP ERR_USE\n");
+ Status = STATUS_ADDRESS_ALREADY_EXISTS;
+ goto LEAVE;
+ }
+ case (ERR_OK) :
+ {
+ DPRINT1("lwIP ERR_OK\n");
+ break;
+ }
+ default :
+ {
+ DPRINT1("lwIP unexpected error\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ goto LEAVE;
}
}
- AddressFile->TcpState = TCP_STATE_BOUND;
- case TCP_STATE_BOUND :
- case TCP_STATE_LISTENING :
- Status = STATUS_SUCCESS;
- break;
- default :
- DPRINT1("Invalid TCP state: %d\n", AddressFile->TcpState);
- Status = STATUS_UNSUCCESSFUL;
- }
+ }
+ }
+
+ DPRINT1("TcpIpAssociateAddress Exiting\n");
+
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+
+ Context->TcpState = TCP_STATE_BOUND;
LEAVE:
return Status;
}
-
/* Implementation in testing */
NTSTATUS
@@ -1314,6 +1630,8 @@
PTCP_CONTEXT Context;
PADDRESS_FILE AddressFile;
+ KIRQL OldIrql;
+
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if ((ULONG)IrpSp->FileObject->FsContext2 != TDI_CONNECTION_FILE)
{
@@ -1323,6 +1641,9 @@
Context = IrpSp->FileObject->FsContext;
AddressFile = Context->AddressFile;
+ DPRINT1("AddressFile at %08x\n", AddressFile);
+ DPRINT1("Context at %08x\n", Context);
+
if (AddressFile->Protocol != IPPROTO_TCP)
{
DPRINT1("Received TDI_DISASSOCIATE_ADDRESS for non-TCP protocol\n");
@@ -1334,27 +1655,32 @@
return STATUS_INVALID_ADDRESS;
}
- switch (AddressFile->TcpState)
- {
- case TCP_STATE_BOUND :
- tcp_close(Context->lwip_tcp_pcb);
- case TCP_STATE_CONNECTED :
- AddressFile->ConnectionContext->lwip_tcp_pcb = NULL;
- Context->lwip_tcp_pcb = NULL;
- case TCP_STATE_LISTENING :
- RemoveEntryList(&Context->ListEntry);
- Context->AddressFile = NULL;
- AddressFile->ContextCount--;
- if (AddressFile->ContextCount == 0)
- {
- return TcpIpCloseAddress(AddressFile);
- }
- return STATUS_SUCCESS;
- default :
- DPRINT1("Invalid TCP state: %d\n", AddressFile->TcpState);
- // TODO: more case statements for better error reporting
- return STATUS_UNSUCCESSFUL;
- }
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+
+ if (AddressFile->lwip_tcp_pcb == Context->lwip_tcp_pcb)
+ {
+ Context->lwip_tcp_pcb = NULL;
+ }
+
+ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock);
+ if (!(IsListEmpty(&Context->RequestListHead)))
+ {
+ DPRINT1("Disassociating context with outstanding requests\n");
+ }
+ KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock);
+
+ RemoveEntryList(&Context->ListEntry);
+ AddressFile->ContextCount--;
+ Context->AddressFile = NULL;
+
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+
+ if (AddressFile->ContextCount == 0)
+ {
+ return TcpIpCloseAddress(AddressFile);
+ }
+
+ return STATUS_SUCCESS;
}
/* Implementation in testing */
@@ -1364,9 +1690,10 @@
{
PIO_STACK_LOCATION IrpSp;
PADDRESS_FILE AddressFile;
- PTCP_CONTEXT ConnectionContext;
+ PTCP_CONTEXT Context;
struct tcp_pcb *lpcb;
+ KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
@@ -1376,46 +1703,44 @@
DPRINT1("Not a connection context\n");
return STATUS_FILE_INVALID;
}
-
/* Get context file */
- ConnectionContext = IrpSp->FileObject->FsContext;
- AddressFile = ConnectionContext->AddressFile;
- if (ConnectionContext->Protocol != IPPROTO_TCP)
- {
- DPRINT1("Received TDI_LISTEN for a non-TCP protocol\n");
- return STATUS_INVALID_ADDRESS;
- }
-
- switch (AddressFile->TcpState)
- {
- case TCP_STATE_BOUND :
- /* Call down into lwip to initiate a listen */
- lpcb = tcp_listen(AddressFile->ConnectionContext->lwip_tcp_pcb);
- DPRINT1("lwip tcp_listen returned\n");
- if (lpcb == NULL)
- {
- /* tcp_listen returning NULL can mean
- either INVALID_ADDRESS or NO_MEMORY
- if SO_REUSE is enabled in lwip options */
- DPRINT1("lwip tcp_listen error\n");
- return STATUS_INVALID_ADDRESS;
- }
- AddressFile->ConnectionContext->lwip_tcp_pcb = lpcb;
- tcp_arg(lpcb, AddressFile);
- tcp_accept(lpcb, lwip_tcp_accept_callback);
- AddressFile->TcpState = TCP_STATE_LISTENING;
- case TCP_STATE_LISTENING :
- ConnectionContext->lwip_tcp_pcb
- = AddressFile->ConnectionContext->lwip_tcp_pcb;
- PrepareIrpForCancel(
- Irp,
- CancelRequestRoutine,
- TCP_REQUEST_CANCEL_MODE_CLOSE);
- return STATUS_PENDING;
- default :
- DPRINT1("Invalid TCP sate\n");
- return STATUS_UNSUCCESSFUL;
- }
+ Context = IrpSp->FileObject->FsContext;
+ if (!(Context->TcpState & TCP_STATE_BOUND))
+ {
+ DPRINT1("Received TDI_LISTEN for a context that has not been associated\n");
+ // TODO: better return code
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ AddressFile = Context->AddressFile;
+ DPRINT1("AddresFile at %08x\n", AddressFile);
+
+ KeAcquireSpinLock(&AddressFile->ContextListLock, &OldIrql);
+ if (AddressFile->ContextListHead.Flink == &Context->ListEntry)
+ {
+ lpcb = tcp_listen(Context->lwip_tcp_pcb);
+ AddressFile->lwip_tcp_pcb = lpcb;
+ Context->lwip_tcp_pcb = lpcb;
+ if (lpcb == NULL)
+ {
+ /* tcp_listen returning NULL can mean
+ either INVALID_ADDRESS or NO_MEMORY
+ if SO_REUSE is enabled in lwip options */
+ DPRINT1("lwip tcp_listen error\n");
+ return STATUS_INVALID_ADDRESS;
+ }
+ tcp_arg(lpcb, AddressFile);
+ tcp_accept(lpcb, lwip_tcp_accept_callback);
+ }
+ KeReleaseSpinLock(&AddressFile->ContextListLock, OldIrql);
+
+ PrepareIrpForCancel(
+ Irp,
+ CancelRequestRoutine,
+ TCP_REQUEST_CANCEL_MODE_ABORT,
+ TCP_REQUEST_PENDING_GENERAL);
+ Context->TcpState = TCP_STATE_LISTENING;
+ return STATUS_PENDING;
}
NTSTATUS
@@ -1430,6 +1755,10 @@
UINT Len;
err_t lwip_err;
+ PLIST_ENTRY Head;
+ PLIST_ENTRY Entry;
+ PLIST_ENTRY Temp;
+ KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Request = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters;
@@ -1441,26 +1770,15 @@
}
Context = IrpSp->FileObject->FsContext;
- switch (Context->AddressFile->TcpState)
- {
- case TCP_STATE_LISTENING :
- if (Context->lwip_tcp_pcb ==
Context->AddressFile->ConnectionContext->lwip_tcp_pcb)
- {
- DPRINT1("Has the PCB been assigned by an lwIP callback?\n");
- // TODO: change to better error
- return STATUS_UNSUCCESSFUL;
- }
- case TCP_STATE_CONNECTED :
- break;
- default :
- DPRINT1("Invalid TCP state: %d\n", Context->AddressFile->TcpState);
- // TODO: more cases for better error reporting
- return STATUS_UNSUCCESSFUL;
- }
-
+ if (!(Context->TcpState & (TCP_STATE_ACCEPTED|TCP_STATE_CONNECTED)))
+ {
+ DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
+ // TODO: better return code
+ return STATUS_UNSUCCESSFUL;
+ }
if (!Irp->MdlAddress)
{
- DPRINT1("TcpIpSendEmpty\n");
+ DPRINT1("TcpIpSend Empty\n");
return STATUS_INVALID_PARAMETER;
}
NdisQueryBuffer(Irp->MdlAddress, &Buffer, &Len);
@@ -1475,33 +1793,61 @@
return STATUS_INVALID_PARAMETER;
}
+ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql);
+
+ Head = &Context->RequestListHead;
+ Entry = Head->Flink;
+ while (Entry != Head)
+ {
+ TcpRequest = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry);
+ if (!TcpRequest->PendingIrp)
+ {
+ Temp = Entry->Flink;
+ RemoveEntryList(Entry);
+ Entry = Temp;
+ ExFreePoolWithTag(TcpRequest, TAG_TCP_REQUEST);
+ continue;
+ }
+ if (TcpRequest->PendingMode == TCP_REQUEST_PENDING_SEND)
+ {
+ goto LEAVE;
+ }
+ Entry = Entry->Flink;
+ }
+
+ tcp_arg(Context->lwip_tcp_pcb, Context);
+ tcp_sent(Context->lwip_tcp_pcb, lwip_tcp_sent_callback);
+
lwip_err = tcp_write(Context->lwip_tcp_pcb, Buffer, Request->SendLength, 0);
switch (lwip_err)
{
case ERR_OK:
- DPRINT1("lwIP ERR_OK\n");
break;
case ERR_MEM:
DPRINT1("lwIP ERR_MEM\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_NO_MEMORY;
case ERR_ARG:
DPRINT1("lwIP ERR_ARG\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_INVALID_PARAMETER;
case ERR_CONN:
DPRINT1("lwIP ERR_CONN\n");
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_CONNECTION_ACTIVE;
default:
DPRINT1("Unknwon lwIP Error: %d\n", lwip_err);
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_NOT_IMPLEMENTED;
}
- TcpRequest = PrepareIrpForCancel(
+LEAVE:
+ PrepareIrpForCancel(
Irp,
CancelRequestRoutine,
- TCP_REQUEST_CANCEL_MODE_ABORT);
- tcp_arg(Context->lwip_tcp_pcb, TcpRequest);
- tcp_sent(Context->lwip_tcp_pcb, lwip_tcp_sent_callback);
-
+ TCP_REQUEST_CANCEL_MODE_PRESERVE,
+ TCP_REQUEST_PENDING_SEND);
+ KeReleaseSpinLock(&Context->RequestListLock, OldIrql);
return STATUS_PENDING;
}
@@ -1511,10 +1857,10 @@
{
PIO_STACK_LOCATION IrpSp;
PTCP_CONTEXT Context;
- PADDRESS_FILE AddressFile;
- PTCP_REQUEST Request;
PTDI_REQUEST_KERNEL_RECEIVE RequestInfo;
+
+ DPRINT1("Receive IRP Address: %08x\n", Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
@@ -1524,31 +1870,31 @@
return STATUS_INVALID_PARAMETER;
}
Context = IrpSp->FileObject->FsContext;
- AddressFile = Context->AddressFile;
- switch (AddressFile->TcpState)
- {
- case TCP_STATE_LISTENING :
- if (Context->lwip_tcp_pcb == AddressFile->ConnectionContext->lwip_tcp_pcb)
- {
- DPRINT1("Has the PCB been assigned by an lwIP callback?\n");
- return STATUS_INVALID_ADDRESS;
- }
- case TCP_STATE_CONNECTED :
- RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
- DPRINT1("\n Request Length = %d\n", RequestInfo->ReceiveLength);
-
- Request = PrepareIrpForCancel(
- Irp,
- CancelRequestRoutine,
- TCP_REQUEST_CANCEL_MODE_CLOSE);
- tcp_arg(Context->lwip_tcp_pcb, Request);
+ DPRINT1("Receive Context Address: %08x\n", Context);
+ DPRINT1("Receive Address File Address: %08x\n", Context->AddressFile);
+ if (Context->TcpState & (TCP_STATE_CONNECTED|TCP_STATE_ACCEPTED))
+ {
+ RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
+ DPRINT1("\n Request Length = %d\n", RequestInfo->ReceiveLength);
+
+ PrepareIrpForCancel(
+ Irp,
+ CancelRequestRoutine,
+ TCP_REQUEST_CANCEL_MODE_PRESERVE,
+ TCP_REQUEST_PENDING_RECEIVE);
+
+ if (!(Context->TcpState & TCP_STATE_RECEIVING))
+ {
+ tcp_arg(Context->lwip_tcp_pcb, Context);
tcp_recv(Context->lwip_tcp_pcb, lwip_tcp_receive_callback);
-
- return STATUS_PENDING;
- default :
- DPRINT1("Invalid TCP state: %d\n", AddressFile->TcpState);
- return STATUS_INVALID_PARAMETER;
- }
+ Context->TcpState |= TCP_STATE_RECEIVING;
+ }
+
+ return STATUS_PENDING;
+ }
+ DPRINT1("Invalid TCP state: %d\n", Context->TcpState);
+ // TODO: better return error
+ return STATUS_UNSUCCESSFUL;
}
NTSTATUS
Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/ne…
==============================================================================
--- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] (original)
+++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h [iso-8859-1] Fri Jul 1
19:37:51 2016
@@ -1,47 +1,68 @@
#pragma once
-#define TCP_REQUEST_CANCEL_MODE_ABORT 1
-#define TCP_REQUEST_CANCEL_MODE_CLOSE 2
+#define TCP_REQUEST_CANCEL_MODE_ABORT 1
+#define TCP_REQUEST_CANCEL_MODE_CLOSE 2
+#define TCP_REQUEST_CANCEL_MODE_PRESERVE 3
-#define TCP_STATE_CREATED 1 // created, unbound
-#define TCP_STATE_BOUND 2 // bound, not listening or trying to connect
-#define TCP_STATE_LISTENING 4 // listening, may or may not have connected clients
-#define TCP_STATE_CONNECTING 8 // trying to connect as a client
-#define TCP_STATE_CONNECTED 16 // connected as client
+#define TCP_REQUEST_PENDING_GENERAL 0
+#define TCP_REQUEST_PENDING_SEND 1
+#define TCP_REQUEST_PENDING_RECEIVE 2
+
+#define TCP_STATE_CREATED 0x1 << 0
+#define TCP_STATE_BOUND 0x1 << 1
+#define TCP_STATE_LISTENING 0x1 << 2
+#define TCP_STATE_ACCEPTED 0x1 << 3
+#define TCP_STATE_RECEIVING 0x1 << 4
+#define TCP_STATE_ABORTED 0x1 << 5
+#define TCP_STATE_CONNECTING 0x1 << 6
+#define TCP_STATE_CONNECTED 0x1 << 7
+#define TCP_STATE_SENDING 0x1 << 8
typedef struct _ADDRESS_FILE {
+ UCHAR Type;
LIST_ENTRY ListEntry;
LONG RefCount;
LONG ContextCount;
IPPROTO Protocol;
TDI_ADDRESS_IP Address;
TCPIP_INSTANCE Instance;
- KSPIN_LOCK RequestLock;
- LIST_ENTRY RequestListHead;
- UCHAR TcpState;
+ union
+ {
+ KSPIN_LOCK RequestLock;
+ KSPIN_LOCK ContextListLock;
+ };
+ union
+ {
+ LIST_ENTRY RequestListHead;
+ LIST_ENTRY ContextListHead;
+ };
union
{
struct raw_pcb* lwip_raw_pcb;
struct udp_pcb* lwip_udp_pcb;
- struct _TCP_CONTEXT *ConnectionContext;
+ struct tcp_pcb* lwip_tcp_pcb;
};
} ADDRESS_FILE, *PADDRESS_FILE;
typedef struct _TCP_CONTEXT {
+ UCHAR Type;
LIST_ENTRY ListEntry;
PADDRESS_FILE AddressFile;
IPPROTO Protocol;
TDI_ADDRESS_IP RequestAddress;
- KSPIN_LOCK RequestListLock; // TODO: implement
+ KSPIN_LOCK RequestListLock;
LIST_ENTRY RequestListHead;
struct tcp_pcb* lwip_tcp_pcb;
+ ULONG TcpState;
} TCP_CONTEXT, *PTCP_CONTEXT;
typedef struct _TCP_REQUEST {
LIST_ENTRY ListEntry;
PIRP PendingIrp;
+ PTCP_CONTEXT Context;
UCHAR CancelMode;
+ UCHAR PendingMode;
} TCP_REQUEST, *PTCP_REQUEST;
void