Author: zhu Date: Tue Jul 12 19:22:33 2016 New Revision: 71905 URL: http://svn.reactos.org/svn/reactos?rev=71905&view=rev Log: Multitude of bug fixes for state TCP Context state transitions, memory allocation/deallocation, and LIST_ENTRY usage. Corrected handling of dying sockets. Previously, connected sockets assigned by lwIP through the accepted callback were not assigned an error callback.
Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.c?rev=71905&r1=71904&r2=71905&view=diff ============================================================================== --- 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] Tue Jul 12 19:22:33 2016 @@ -46,7 +46,6 @@ PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; PTCP_REQUEST Request; - NTSTATUS Status; DPRINT1("Prepare for cancel\n"); @@ -56,8 +55,7 @@ if (!Request) { DPRINT1("Allocation failed, out of memory\n"); - Status = STATUS_NO_MEMORY; - goto RETURN; + return STATUS_NO_MEMORY; } IrpSp = IoGetCurrentIrpStackLocation(Irp); @@ -71,10 +69,8 @@ IoSetCancelRoutine(Irp, CancelRoutine); InsertTailList(&Context->RequestListHead, &Request->ListEntry); - Status = STATUS_SUCCESS; DPRINT1("Prepared for cancel\n"); - - goto RETURN; + return STATUS_SUCCESS; } DPRINT1("Already cancelled\n"); @@ -82,8 +78,7 @@ Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; -RETURN: - return Status; + return STATUS_CANCELLED; } /* implementation in testing */ @@ -114,6 +109,12 @@ case TDI_CONNECTION_FILE : Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext; goto TCP_CANCEL; + case TCP_REQUEST_STRUCT : + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoSetCancelRoutine(Irp, NULL); + ExFreePoolWithTag(IrpSp->FileObject->FsContext, TAG_TCP_REQUEST); + goto FINISH; default : DPRINT1("Cancellation error\n"); goto FINISH; @@ -142,6 +143,7 @@ { AddressFile->lwip_tcp_pcb = NULL; } + DPRINT1("Aborting PCB at %p\n", Context->lwip_tcp_pcb); tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); InterlockedDecrement(&PcbCount); @@ -162,6 +164,7 @@ { AddressFile->lwip_tcp_pcb = NULL; } + DPRINT1("Closing PCB at %p\n", Context->lwip_tcp_pcb); tcp_close(Context->lwip_tcp_pcb); InterlockedDecrement(&PcbCount); DPRINT1("\n PCB Count: %d\n", PcbCount); @@ -200,8 +203,6 @@ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); DPRINT1("CancelRequestRoutine Exiting\n"); - - return; } void @@ -234,10 +235,11 @@ PLIST_ENTRY RequestHead; PLIST_ENTRY RequestEntry; PLIST_ENTRY Entry; - PLIST_ENTRY Temp; PIRP Irp; KIRQL OldIrql; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; switch (err) @@ -258,7 +260,7 @@ DPRINT1("lwIP invalid arguments\n"); break; case ERR_IF : - DPRINT1("Low=level error\n"); + DPRINT1("Low-level error\n"); break; default : DPRINT1("Unsupported lwIP error code: %d\n", err); @@ -301,25 +303,23 @@ Irp = Request->PendingIrp; if (Irp) { - if (Irp->Cancel) - { - Irp->Cancel = FALSE; - IoSetCancelRoutine(Irp, NULL); - } - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + IrpSp = IoGetCurrentIrpStackLocation(Irp); + RequestEntry = RequestEntry->Flink; + RemoveEntryList(&Request->ListEntry); + IrpSp->FileObject->FsContext = Request; + IrpSp->FileObject->FsContext2 = (PVOID)TCP_REQUEST_STRUCT; + continue; } - Temp = RequestEntry->Flink; - RemoveEntryList(RequestEntry); + RequestEntry = RequestEntry->Flink; + RemoveEntryList(&Request->ListEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - RequestEntry = Temp; } KeReleaseSpinLockFromDpcLevel(&Context->RequestListLock); if (Context->lwip_tcp_pcb != AddressFile->lwip_tcp_pcb) { + DPRINT1("Aborting PCB at %p\n", Context->lwip_tcp_pcb); tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); InterlockedDecrement(&PcbCount); @@ -339,7 +339,7 @@ Context = (PTCP_CONTEXT)arg; DPRINT1("AddressFile at %p\n", Context->AddressFile); KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); - + RequestHead = &Context->RequestListHead; RequestEntry = RequestHead->Flink; while (RequestEntry != RequestHead) @@ -348,19 +348,16 @@ Irp = Request->PendingIrp; if (Irp) { - if (Irp->Cancel) - { - Irp->Cancel = FALSE; - IoSetCancelRoutine(Irp, NULL); - } - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + IrpSp = IoGetCurrentIrpStackLocation(Irp); + RequestEntry = RequestEntry->Flink; + RemoveEntryList(&Request->ListEntry); + IrpSp->FileObject->FsContext = Request; + IrpSp->FileObject->FsContext2 = (PVOID)TCP_REQUEST_STRUCT; + continue; } - Temp = RequestEntry->Flink; - RemoveEntryList(RequestEntry); + RequestEntry = RequestEntry->Flink; + RemoveEntryList(&Request->ListEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); - RequestEntry = Temp; } KeReleaseSpinLock(&Context->RequestListLock, OldIrql); @@ -507,6 +504,7 @@ KeAcquireSpinLockAtDpcLevel(&Context->RequestListLock); Context->lwip_tcp_pcb = newpcb; + tcp_err(Context->lwip_tcp_pcb, lwip_tcp_err_callback); InterlockedIncrement(&PcbCount); DPRINT1("\n PCB Count: %d\n", PcbCount); Context->TcpState = TCP_STATE_ACCEPTED; @@ -690,7 +688,6 @@ UCHAR *CurrentSrceLocation; PLIST_ENTRY Head; PLIST_ENTRY Entry; - PLIST_ENTRY NextEntry; NTSTATUS Status; err_t lwip_err; @@ -714,23 +711,19 @@ Head = &Context->RequestListHead; Entry = Head->Flink; Irp = NULL; - DPRINT1("Entering Loop\n"); while (Entry != Head) { - DPRINT1("Fetching Request\n"); Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); - DPRINT1("Request Fetched. Points to %08x\n", Request); if (!Request->PendingIrp) { - DPRINT1("IRP pointer dereferenced\n"); - NextEntry = Entry->Flink; - RemoveEntryList(Entry); - DPRINT1("Entry removed\n"); - Entry = NextEntry; + Entry = Entry->Flink; + RemoveEntryList(&Request->ListEntry); ExFreePoolWithTag(Request, TAG_TCP_REQUEST); continue; } if (Request->PendingMode == TCP_REQUEST_PENDING_RECEIVE) { Irp = Request->PendingIrp; Entry = Entry->Flink; + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_TCP_REQUEST); break; } Entry = Entry->Flink; @@ -747,7 +740,7 @@ Irp->Cancel = FALSE; if (Context->lwip_tcp_pcb != tpcb) { - DPRINT1("Receive tcp_pcb mismatch\n"); + DPRINT1("Receive tcp_pcb mismatch\nAborting PCB at %p\n", tpcb); tcp_arg(tpcb, NULL); tcp_abort(tpcb); InterlockedDecrement(&PcbCount); @@ -759,7 +752,8 @@ lwip_err = ERR_ABRT; goto BAD; } - if (!(Context->TcpState & (TCP_STATE_RECEIVING|TCP_STATE_ACCEPTED|TCP_STATE_CONNECTED))) { + if (!(Context->TcpState & TCP_STATE_RECEIVING) || + !(Context->TcpState & (TCP_STATE_CONNECTED|TCP_STATE_ACCEPTED))) { DPRINT1("Invalid TCP state: %08x\n", Context->TcpState); // TODO: better return code Status = STATUS_UNSUCCESSFUL; @@ -817,13 +811,19 @@ } RETURN: - DPRINT1("Receive CopiedLength = %d\n", CopiedLength); + DPRINT1("Receive CopiedLength = %d\nReceived on PCB at %p\n", CopiedLength, tpcb); tcp_recved(tpcb, CopiedLength); while (Entry != Head) { Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); + if (!Request->PendingIrp) { + Entry = Entry->Flink; + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_TCP_REQUEST); + continue; + } if (Request->PendingMode == TCP_REQUEST_PENDING_RECEIVE) { - tcp_recv(tpcb, lwip_tcp_receive_callback); + tcp_recv(Context->lwip_tcp_pcb, lwip_tcp_receive_callback); break; } Entry = Entry->Flink; @@ -831,11 +831,7 @@ lwip_err = ERR_OK; BAD: - RemoveEntryList(&Request->ListEntry); - KeReleaseSpinLock(&Context->RequestListLock, OldIrql); - - ExFreePoolWithTag(Request, TAG_TCP_REQUEST); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = CopiedLength; @@ -1137,24 +1133,25 @@ IrpSp = IoGetCurrentIrpStackLocation(Irp); + if (Protocol != IPPROTO_TCP) + { + DPRINT1("Creating connection context for non-TCP protocoln"); + return STATUS_INVALID_PARAMETER; + } + Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Context), TAG_TCP_CONTEXT); if (!Context) { return STATUS_NO_MEMORY; } - - if (Protocol != IPPROTO_TCP) - { - DPRINT1("Creating connection context for non-TCP protocoln"); - return STATUS_INVALID_PARAMETER; - } Context->Type = TDI_CONNECTION_FILE; + Context->TcpState = TCP_STATE_CREATED; Context->Protocol = Protocol; RtlCopyMemory(&Context->RequestAddress, Address, sizeof(*Address)); + Context->AddressFile = NULL; 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; @@ -1203,10 +1200,12 @@ { if (AddressFile->lwip_tcp_pcb->state == LISTEN) { + DPRINT1("Closing PCB at %p\n", AddressFile->lwip_tcp_pcb); lwip_err = tcp_close(AddressFile->lwip_tcp_pcb); } else { + DPRINT1("Aborting PCB at %p\n", AddressFile->lwip_tcp_pcb); tcp_arg(AddressFile->lwip_tcp_pcb, NULL); tcp_abort(AddressFile->lwip_tcp_pcb); lwip_err = ERR_OK; @@ -1275,18 +1274,31 @@ KeAcquireSpinLock(&Context->RequestListLock, &OldIrql); + AddressFile = Context->AddressFile; + if (Context->lwip_tcp_pcb == AddressFile->lwip_tcp_pcb) + { + Context->lwip_tcp_pcb = NULL; + } + if (Context->lwip_tcp_pcb) { + if (Context->lwip_tcp_pcb == AddressFile->lwip_tcp_pcb) + { + Context->lwip_tcp_pcb = NULL; + } if (Context->TcpState == TCP_STATE_LISTENING) { + DPRINT1("Closing PCB at %p\n", Context->lwip_tcp_pcb); lwip_err = tcp_close(Context->lwip_tcp_pcb); } else { + DPRINT1("Aborting PCB at %p\n", Context->lwip_tcp_pcb); tcp_arg(Context->lwip_tcp_pcb, NULL); tcp_abort(Context->lwip_tcp_pcb); lwip_err = ERR_OK; } + Context->lwip_tcp_pcb = NULL; InterlockedDecrement(&PcbCount); DPRINT1("\n PCB Count: %d\n", PcbCount); if (lwip_err != ERR_OK) @@ -1322,8 +1334,6 @@ } KeReleaseSpinLock(&Context->RequestListLock, OldIrql); - - AddressFile = Context->AddressFile; ExFreePoolWithTag(Context, TAG_TCP_CONTEXT); Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/address.h?rev=71905&r1=71904&r2=71905&view=diff ============================================================================== --- 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] Tue Jul 12 19:22:33 2016 @@ -4,6 +4,8 @@ #define TCP_REQUEST_CANCEL_MODE_ABORT 1 #define TCP_REQUEST_CANCEL_MODE_CLOSE 2 #define TCP_REQUEST_CANCEL_MODE_PRESERVE 3 + +#define TCP_REQUEST_STRUCT 255 #define TCP_REQUEST_PENDING_GENERAL 0 #define TCP_REQUEST_PENDING_SEND 1 @@ -49,13 +51,13 @@ typedef struct _TCP_CONTEXT { UCHAR Type; // must be the first member LIST_ENTRY ListEntry; - PADDRESS_FILE AddressFile; + ULONG TcpState; IPPROTO Protocol; TDI_ADDRESS_IP RequestAddress; + PADDRESS_FILE AddressFile; KSPIN_LOCK RequestListLock; LIST_ENTRY RequestListHead; struct tcp_pcb* lwip_tcp_pcb; - ULONG TcpState; } TCP_CONTEXT, *PTCP_CONTEXT; typedef struct _TCP_REQUEST { Modified: branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c?rev=71905&r1=71904&r2=71905&view=diff ============================================================================== --- branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/drivers/network/tcpip/main.c [iso-8859-1] Tue Jul 12 19:22:33 2016 @@ -269,9 +269,9 @@ DPRINT1("\nPTA_IP_ADDRESS dump before\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]);*/ - DPRINT1("Call into TcpIpCreateAddress\n"); + // DPRINT1("Call into TcpIpCreateAddress\n"); Status = TcpIpCreateAddress(Irp, &Address->Address[0].Address[0], Protocol); - DPRINT1("Returned from TcpIpCreateAddress\n"); + // DPRINT1("Returned from TcpIpCreateAddress\n"); if (Status != STATUS_SUCCESS) { goto Quickie;