Author: zhu Date: Thu Jun 23 15:28:39 2016 New Revision: 71661 URL: http://svn.reactos.org/svn/reactos?rev=71661&view=rev Log: Backlogging successful. Server is able to simultaneously receive messages from two different clients. Crashes on client exit due to referencing deallocated memory.
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 branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/opt.h 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=71661&r1=71660&r2=71661&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] Thu Jun 23 15:28:39 2016 @@ -31,11 +31,13 @@ NTSTATUS PrepareIrpForCancel( PIRP Irp, - PDRIVER_CANCEL CancelRoutine + PDRIVER_CANCEL CancelRoutine, + UCHAR CancelMode ) { PIO_STACK_LOCATION IrpSp; - PADDRESS_FILE AddressFile; + PTCP_CONTEXT Context; + PTCP_REQUEST Request; KIRQL OldIrql; DPRINT1("Prepare for cancel\n"); @@ -44,14 +46,27 @@ if (!Irp->Cancel) { + Request = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Request), TAG_ADDRESS_FILE); + if (!Request) + { + return STATUS_NO_MEMORY; + } + Request->PendingIrp = Irp; + Request->CancelMode = CancelMode; + IrpSp = IoGetCurrentIrpStackLocation(Irp); - AddressFile = (PADDRESS_FILE)IrpSp->FileObject->FsContext; - AddressFile->ConnectionContext->PendingIrp = Irp; + Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext; + InsertTailList(&Context->RequestListHead, &Request->ListEntry); IoSetCancelRoutine(Irp, CancelRoutine); IoReleaseCancelSpinLock(OldIrql); + + DPRINT1("Prepared for cancel\n"); + return STATUS_SUCCESS; } + + DPRINT1("Already cancelled\n"); IoReleaseCancelSpinLock(OldIrql); @@ -70,7 +85,10 @@ ) { PIO_STACK_LOCATION IrpSp; - PADDRESS_FILE AddressFile; + PTCP_CONTEXT Context; + PLIST_ENTRY Head; + PLIST_ENTRY Entry; + PTCP_REQUEST Request; UCHAR MinorFunction; KIRQL OldIrql; @@ -79,51 +97,68 @@ IoReleaseCancelSpinLock(Irp->CancelIrql); IrpSp = IoGetCurrentIrpStackLocation(Irp); - AddressFile = (PADDRESS_FILE)IrpSp->FileObject->FsContext; + switch ((ULONG)IrpSp->FileObject->FsContext2) + { + case TDI_TRANSPORT_ADDRESS_FILE : + goto DGRAM_CANCEL; + case TDI_CONNECTION_FILE : + Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext; + goto TCP_CANCEL; + default : + DPRINT1("Cancellation error\n"); + goto FINISH; + } + +TCP_CANCEL: MinorFunction = IrpSp->MinorFunction; - Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; - switch(MinorFunction) { + case TDI_SEND: + DPRINT1("TDI_SEND Cancel\n"); + break; + case TDI_LISTEN: + DPRINT1("TDI_LISTEN Cancel\n"); + break; + case TDI_CONNECT: + DPRINT1("TDI_CONNECT Cancel\n"); + break; case TDI_RECEIVE: DPRINT1("TDI_RECEIVE Cancel\n"); - goto TCP_CANCEL; - case TDI_RECEIVE_DATAGRAM: - DPRINT1("TDI_RECEIVE_DATAGRAM cancelling is handled within TcpIpReceiveDatagram()\n"); - goto DGRAM_CANCEL; - case TDI_SEND: - DPRINT1("TDI_SEND Cancel\n"); - goto TCP_CANCEL; - case TDI_SEND_DATAGRAM: - DPRINT1("TDI_SEND_DATAGRAM Cancel\n"); - goto DGRAM_CANCEL; - case TDI_LISTEN: - DPRINT1("TDI_LISTEN Cancel\n"); - goto TCP_CANCEL; - case TDI_CONNECT: - DPRINT1("TDI_CONNECT Cancel\n"); - goto TCP_CANCEL; + break; case TDI_DISCONNECT: DPRINT1("TDI_DISCONNECT Cancel\n"); - goto TCP_CANCEL; + break; default: - DPRINT1("Invalid MinorFunction for cancelling IRP\n"); - return; - } - -TCP_CANCEL: - if (AddressFile->ConnectionContext) - { - if (AddressFile->ConnectionContext->lwip_tcp_pcb) + DPRINT1("Invalid MinorFunction for TCP_CANCEL\n"); + goto FINISH; + } + + Head = &Context->RequestListHead; + Entry = Head->Flink; + while (Entry != Head) + { + Request = CONTAINING_RECORD(Entry, TCP_REQUEST, ListEntry); + if (Request->PendingIrp == Irp) { - tcp_abort(AddressFile->ConnectionContext->lwip_tcp_pcb); - AddressFile->ConnectionContext->PendingIrp = NULL; - AddressFile->ConnectionContext->lwip_tcp_pcb = NULL; - DPRINT1("TCP_CANCEL\n"); + RemoveEntryList(Entry); + switch (Request->CancelMode) + { + case TCP_REQUEST_CANCEL_MODE_ABORT: + tcp_abort(Context->lwip_tcp_pcb); + break; + case TCP_REQUEST_CANCEL_MODE_CLOSE: + tcp_close(Context->lwip_tcp_pcb); + break; + } + Context->lwip_tcp_pcb = NULL; + Request->PendingIrp = NULL; + goto FINISH; } - } + Entry = Entry->Flink; + } + DPRINT1("No matching TCP_REQUEST found\n"); goto FINISH; DGRAM_CANCEL: @@ -136,7 +171,8 @@ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); - DPRINT1("\n CancelRequestRoutine\n Exiting\n"); + DPRINT1("\n CancelRequestRoutine Exiting\n"); + return; } @@ -263,26 +299,55 @@ err_t err) { PIRP Irp; - PIO_STACK_LOCATION IrpSp; KIRQL OldIrql; + PTCP_REQUEST Request; PADDRESS_FILE AddressFile; + PTCP_CONTEXT Context; + + PLIST_ENTRY Head; + PLIST_ENTRY Entry; + PLIST_ENTRY Temp; DPRINT1("lwIP TCP Accept Callback\n"); AddressFile = (PADDRESS_FILE)arg; - Irp = AddressFile->ConnectionContext->PendingIrp; + if (AddressFile->ContextCount == 0) + { + DPRINT1("\n Callback on address file with no contexts\n"); + return ERR_ABRT; + } + Head = &AddressFile->ConnectionContext->ListEntry; + Entry = Head->Blink; + Irp = NULL; + while (Entry != Head) + { + Context = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry); + if (Context->lwip_tcp_pcb == AddressFile->ConnectionContext->lwip_tcp_pcb) + { + if (IsListEmpty(&Context->RequestListHead)) + { + 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("Found cancelled IRP\n"); + Temp = Entry->Blink; + RemoveEntryList(Entry); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); + Entry = Temp; + continue; + } + break; + } + Entry = Entry->Blink; + } if (!Irp) { - DPRINT1("Callback on canceled IRP\n"); - return ERR_ABRT; - } - IrpSp = IoGetCurrentIrpStackLocation(Irp); - - if (AddressFile != IrpSp->FileObject->FsContext) - { - DPRINT1("AddressFile Mismatch\n"); - tcp_abort(AddressFile->ConnectionContext->lwip_tcp_pcb); - AddressFile->ConnectionContext->lwip_tcp_pcb = NULL; + DPRINT1("Could not find a listening tcp_pcb\n"); return ERR_ABRT; } @@ -291,10 +356,14 @@ Irp->Cancel = FALSE; IoReleaseCancelSpinLock(OldIrql); - AddressFile->ConnectionContext->lwip_tcp_pcb = newpcb; + 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_ADDRESS_FILE); return ERR_OK; } @@ -308,17 +377,18 @@ u16_t len ) { - PADDRESS_FILE AddressFile; + PTCP_REQUEST Request; PIRP Irp; KIRQL OldIrql; DPRINT1("lwIP TCP Sent Callback\n"); - AddressFile = (PADDRESS_FILE)arg; - Irp = AddressFile->ConnectionContext->PendingIrp; + Request = (PTCP_REQUEST)arg; + Irp = Request->PendingIrp; if (!Irp) { - DPRINT1("Callback on canceled IRP\n"); + DPRINT1("Callback on cancelled IRP\n"); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_ABRT; } @@ -330,6 +400,9 @@ Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = len; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_OK; } @@ -346,7 +419,8 @@ { PIRP Irp; PNDIS_BUFFER Buffer; - PADDRESS_FILE AddressFile; + PTCP_CONTEXT Context; + PTCP_REQUEST Request; PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo; KIRQL OldIrql; @@ -359,11 +433,36 @@ DPRINT1("lwIP TCP Receive Callback\n"); - AddressFile = (PADDRESS_FILE)arg; - Irp = AddressFile->ConnectionContext->PendingIrp; + if (err != ERR_OK) + { + DPRINT1("lwIP Error %d\n", err); + return ERR_ABRT; + } + + Request = (PTCP_REQUEST)arg; + Irp = Request->PendingIrp; if (!Irp) { - DPRINT1("Callback on canceled IRP\n"); + DPRINT1("Callback on cancelled IRP\n"); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); + return ERR_ABRT; + } + IrpSp = IoGetCurrentIrpStackLocation(Irp); + Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext; + if (!Context->lwip_tcp_pcb) + { + DPRINT1("Context pcb is NULL\n"); + return ERR_ABRT; + } + if (Context->lwip_tcp_pcb != tpcb) + { + DPRINT1("Receive tcp_pcb mismatch\n"); + tcp_abort(tpcb); + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_ABRT; } @@ -373,7 +472,6 @@ IoReleaseCancelSpinLock(OldIrql); Buffer = (PNDIS_BUFFER)Irp->MdlAddress; - IrpSp = IoGetCurrentIrpStackLocation(Irp); ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters; NdisQueryBuffer(Buffer, &CurrentDestLocation, &RemainingDestBytes); @@ -432,10 +530,15 @@ RETURN: DPRINT1("Receive CopiedLength = %d\n", CopiedLength); + + tcp_recved(tpcb, CopiedLength); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = CopiedLength; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_OK; } @@ -493,19 +596,35 @@ struct tcp_pcb *tpcb, err_t err) { - PADDRESS_FILE AddressFile; + PTCP_REQUEST Request; + PTCP_CONTEXT Context; + PIO_STACK_LOCATION IrpSp; PIRP Irp; KIRQL OldIrql; DPRINT1("lwIP TCP Connected Callback\n"); - AddressFile = (PADDRESS_FILE)arg; - Irp = AddressFile->ConnectionContext->PendingIrp; + Request = (PTCP_REQUEST)arg; + Irp = Request->PendingIrp; if (!Irp) { - DPRINT1("Callback on canceled IRP\n"); + DPRINT1("Callback on cancelled IRP\n"); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_ABRT; } + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + Context = (PTCP_CONTEXT)IrpSp->FileObject->FsContext; + if (Context->AddressFile->ConnectionContext->lwip_tcp_pcb == tpcb) + { + DPRINT1("Same as old pcb\n"); + } + else + { + DPRINT1("Connected callback assigns new pcb\n"); + } + Context->lwip_tcp_pcb = tpcb; + Context->AddressFile->ConnectionContext->lwip_tcp_pcb = NULL; IoAcquireCancelSpinLock(&OldIrql); IoSetCancelRoutine(Irp, NULL); @@ -514,6 +633,9 @@ Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + RemoveEntryList(&Request->ListEntry); + ExFreePoolWithTag(Request, TAG_ADDRESS_FILE); return ERR_OK; } @@ -648,7 +770,7 @@ InitializeListHead(&TcpContext->ListEntry); TcpContext->AddressFile = AddressFile; TcpContext->Protocol = IPPROTO_TCP; - TcpContext->PendingIrp = NULL; + InitializeListHead(&TcpContext->RequestListHead); TcpContext->lwip_tcp_pcb = tcp_new(); AddressFile->ConnectionContext = TcpContext; AddressFile->ContextCount = 0; @@ -696,6 +818,7 @@ Success: IrpSp->FileObject->FsContext = AddressFile; IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; + return STATUS_SUCCESS; } @@ -741,6 +864,7 @@ } Context->Protocol = Protocol; RtlCopyMemory(&Context->RequestAddress, Address, sizeof(*Address)); + InitializeListHead(&Context->RequestListHead); Context->lwip_tcp_pcb = NULL; IrpSp->FileObject->FsContext = (PVOID)Context; @@ -776,10 +900,12 @@ /* remove the lwip pcb */ if (AddressFile->Protocol == IPPROTO_UDP) udp_remove(AddressFile->lwip_udp_pcb); - else if (AddressFile->Protocol == IPPROTO_TCP && AddressFile->ConnectionContext) - { + else if (AddressFile->Protocol == IPPROTO_TCP) + { + DPRINT1("Closing TCP address\n"); if (AddressFile->ContextCount != 0) { + DPRINT1("Closing open contexts\n"); Head = &AddressFile->ConnectionContext->ListEntry; Entry = Head->Flink; while (Entry != Head) @@ -788,6 +914,17 @@ CurrentContext = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry); RemoveEntryList(Entry); + if (!IsListEmpty(&CurrentContext->RequestListHead)) + { + DPRINT1("Address has non-empty request queue\n"); + return STATUS_NOT_IMPLEMENTED; + } + if (CurrentContext->lwip_tcp_pcb != AddressFile->ConnectionContext->lwip_tcp_pcb + && CurrentContext->lwip_tcp_pcb) + { + DPRINT1("Freeing connected tcp_pcb\n"); + tcp_abort(CurrentContext->lwip_tcp_pcb); + } ExFreePoolWithTag(CurrentContext, TAG_ADDRESS_FILE); AddressFile->ContextCount--; Entry = Temp; @@ -801,7 +938,6 @@ if (AddressFile->ConnectionContext->lwip_tcp_pcb) { tcp_close(AddressFile->ConnectionContext->lwip_tcp_pcb); - AddressFile->ConnectionContext->lwip_tcp_pcb = NULL; } ExFreePoolWithTag(AddressFile->ConnectionContext, TAG_ADDRESS_FILE); } @@ -896,7 +1032,8 @@ _Inout_ PIRP Irp) { PIO_STACK_LOCATION IrpSp; - ADDRESS_FILE *AddressFile; + PTCP_CONTEXT Context; + PTCP_REQUEST Request; PTDI_REQUEST_KERNEL_CONNECT Parameters; PTRANSPORT_ADDRESS RemoteTransportAddress; @@ -908,14 +1045,14 @@ IrpSp = IoGetCurrentIrpStackLocation(Irp); /* Check this is really a connection file */ - if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) - { - DPRINT1("File object not an address file\n"); + if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_CONNECTION_FILE) + { + DPRINT1("File object not a connection context\n"); return STATUS_FILE_INVALID; } - AddressFile = IrpSp->FileObject->FsContext; - if (AddressFile->Protocol != IPPROTO_TCP) + Context = IrpSp->FileObject->FsContext; + if (Context->AddressFile->Protocol != IPPROTO_TCP) { DPRINT1("Received TDI_CONNECT for a non-TCP protocol\n"); return STATUS_INVALID_ADDRESS; @@ -932,10 +1069,10 @@ SocketAddressInRemote->sin_addr.s_addr, SocketAddressInRemote->sin_port); DPRINT1("\n Local Address\n Address: %08x\n Port: %04x\n", - AddressFile->ConnectionContext->lwip_tcp_pcb->local_ip, - AddressFile->ConnectionContext->lwip_tcp_pcb->local_port); - - lwip_err = tcp_connect(AddressFile->ConnectionContext->lwip_tcp_pcb, + Context->lwip_tcp_pcb->local_ip, + Context->lwip_tcp_pcb->local_port); + + lwip_err = tcp_connect(Context->lwip_tcp_pcb, (ip_addr_t *)&SocketAddressInRemote->sin_addr.s_addr, SocketAddressInRemote->sin_port, lwip_tcp_Connected_callback); @@ -978,9 +1115,12 @@ } case (ERR_OK) : { -// DPRINT1("lwip ERR_OK\n"); - PrepareIrpForCancel(Irp, CancelRequestRoutine); - tcp_arg(AddressFile->ConnectionContext->lwip_tcp_pcb, AddressFile); + PrepareIrpForCancel(Irp, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_ABORT); + Request = CONTAINING_RECORD( + Context->RequestListHead.Blink, + TCP_REQUEST, + ListEntry); + tcp_arg(Context->lwip_tcp_pcb, Request); break; } default : @@ -1127,9 +1267,6 @@ } KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - - IrpSp->FileObject->FsContext = AddressFile; - IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; Status = STATUS_SUCCESS; LEAVE: @@ -1144,32 +1281,23 @@ { PIO_STACK_LOCATION IrpSp; PTCP_CONTEXT Context; - PTCP_CONTEXT CurrentContext; PADDRESS_FILE AddressFile; KIRQL OldIrql; - LIST_ENTRY *Head; - LIST_ENTRY *Entry; IrpSp = IoGetCurrentIrpStackLocation(Irp); - if ((ULONG)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) - { + if ((ULONG)IrpSp->FileObject->FsContext2 != TDI_CONNECTION_FILE) + { + DPRINT1("Disassociating something that is not a connection context\n"); return STATUS_FILE_INVALID; } - AddressFile = IrpSp->FileObject->FsContext; + Context = IrpSp->FileObject->FsContext; + AddressFile = Context->AddressFile; if (AddressFile->Protocol != IPPROTO_TCP) { DPRINT1("Received TDI_DISASSOCIATE_ADDRESS for non-TCP protocol\n"); return STATUS_INVALID_ADDRESS; } - - Context = AddressFile->ConnectionContext; - if (!Context) - { - DPRINT1("No connection context\n"); - return STATUS_INVALID_PARAMETER; - } - if (Context->Protocol != IPPROTO_TCP) { DPRINT1("Address File and Context have mismatching protocols\n"); @@ -1177,26 +1305,17 @@ } KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); - - Head = &AddressFile->ConnectionContext->ListEntry; - Entry = Head->Flink; - if (Entry == Head) - { - DPRINT1("Disassociating from empty context list\n"); - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - return STATUS_INVALID_ADDRESS; - } - if (AddressFile->ContextCount < 1) - { - DPRINT1("Invalid ContextCount\n"); - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); - return STATUS_INVALID_ADDRESS; - } - CurrentContext = CONTAINING_RECORD(Entry, TCP_CONTEXT, ListEntry); - RemoveEntryList(Entry); - ExFreePoolWithTag(CurrentContext, TAG_ADDRESS_FILE); + RemoveEntryList(&Context->ListEntry); + if (!IsListEmpty(&Context->RequestListHead)) + { + DPRINT1("Disassociating context with pending requests\n"); + } + if (Context->lwip_tcp_pcb != AddressFile->ConnectionContext->lwip_tcp_pcb) + { + tcp_abort(Context->lwip_tcp_pcb); + } + ExFreePoolWithTag(Context, TAG_ADDRESS_FILE); AddressFile->ContextCount--; - KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); return STATUS_SUCCESS; @@ -1211,29 +1330,31 @@ PADDRESS_FILE AddressFile; PTCP_CONTEXT ConnectionContext; + KIRQL OldIrql; + struct tcp_pcb *lpcb; IrpSp = IoGetCurrentIrpStackLocation(Irp); - /* Check this is really an address file */ - if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_TRANSPORT_ADDRESS_FILE) - { - DPRINT1("Not an address file\n"); + /* Check this is really a context file */ + if ((ULONG_PTR)IrpSp->FileObject->FsContext2 != TDI_CONNECTION_FILE) + { + DPRINT1("Not a connection context\n"); return STATUS_FILE_INVALID; } - /* Get address file */ - AddressFile = IrpSp->FileObject->FsContext; - ConnectionContext = AddressFile->ConnectionContext; + /* 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; } - PrepareIrpForCancel(Irp, CancelRequestRoutine); - if (AddressFile->ContextCount <= 1) - { + if (AddressFile->ContextCount == 1) + { + KeAcquireSpinLock(&AddressFile->RequestLock, &OldIrql); /* Call down into lwip to initiate a listen */ lpcb = tcp_listen(ConnectionContext->lwip_tcp_pcb); DPRINT1("lwip tcp_listen returned\n"); @@ -1245,13 +1366,15 @@ DPRINT1("lwip tcp_listen error\n"); return STATUS_INVALID_ADDRESS; } - else - { - ConnectionContext->lwip_tcp_pcb = lpcb; - } + AddressFile->ConnectionContext->lwip_tcp_pcb = lpcb; + ConnectionContext->lwip_tcp_pcb = lpcb; + tcp_arg(ConnectionContext->lwip_tcp_pcb, AddressFile); tcp_accept(ConnectionContext->lwip_tcp_pcb, lwip_tcp_accept_callback); - tcp_arg(ConnectionContext->lwip_tcp_pcb, AddressFile); - } + + KeReleaseSpinLock(&AddressFile->RequestLock, OldIrql); + } + + PrepareIrpForCancel(Irp, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_CLOSE); return STATUS_PENDING; } @@ -1262,8 +1385,8 @@ { PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_SEND Request; - PADDRESS_FILE AddressFile; PTCP_CONTEXT Context; + PTCP_REQUEST TcpRequest; PVOID Buffer; UINT Len; @@ -1272,19 +1395,12 @@ IrpSp = IoGetCurrentIrpStackLocation(Irp); Request = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters; - if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) - { - DPRINT1("TcpIpSend without a TDI_TRANSPORT_ADDRESS_FILE\n"); + if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) + { + DPRINT1("TcpIpSend without a TDI_CONNECTION_FILE\n"); return STATUS_INVALID_PARAMETER; } - AddressFile = IrpSp->FileObject->FsContext; - - if (!AddressFile->ConnectionContext) - { - DPRINT1("TcpIpSend with no TCP_CONTEXT\n"); - return STATUS_INVALID_PARAMETER; - } - Context = AddressFile->ConnectionContext; + Context = IrpSp->FileObject->FsContext; if (!Irp->MdlAddress) { @@ -1323,8 +1439,10 @@ return STATUS_NOT_IMPLEMENTED; } - PrepareIrpForCancel(Irp, CancelRequestRoutine); - tcp_arg(Context->lwip_tcp_pcb, AddressFile); + PrepareIrpForCancel(Irp, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_ABORT); + TcpRequest = CONTAINING_RECORD(Context->RequestListHead.Blink, + TCP_REQUEST, ListEntry); + tcp_arg(Context->lwip_tcp_pcb, TcpRequest); tcp_sent(Context->lwip_tcp_pcb, lwip_tcp_sent_callback); return STATUS_PENDING; @@ -1335,39 +1453,39 @@ _Inout_ PIRP Irp) { PIO_STACK_LOCATION IrpSp; - PADDRESS_FILE AddressFile; PTCP_CONTEXT Context; + PTCP_REQUEST Request; PTDI_REQUEST_KERNEL_RECEIVE RequestInfo; IrpSp = IoGetCurrentIrpStackLocation(Irp); - if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) + if (IrpSp->FileObject->FsContext2 != (PVOID)TDI_CONNECTION_FILE) { DPRINT1("TcpIpReceive on something that is not an address file\n"); return STATUS_INVALID_PARAMETER; } - AddressFile = IrpSp->FileObject->FsContext; - - if (!AddressFile->ConnectionContext) - { - DPRINT1("Receiving on TCP address file with no connection context\n"); - return STATUS_INVALID_ADDRESS; - } - Context = AddressFile->ConnectionContext; + Context = IrpSp->FileObject->FsContext; if (!Context->lwip_tcp_pcb) { DPRINT1("Connection context does not contain a lwIP tcp_pcb\n"); return STATUS_INVALID_ADDRESS; } + if (Context->lwip_tcp_pcb == Context->AddressFile->ConnectionContext->lwip_tcp_pcb) + { + DPRINT1("Has the pcb been assigned by a lwIP callback?\n"); + return STATUS_INVALID_ADDRESS; + } RequestInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters; DPRINT1("\n Request Length = %d\n", RequestInfo->ReceiveLength); - PrepareIrpForCancel(Irp, CancelRequestRoutine); + PrepareIrpForCancel(Irp, CancelRequestRoutine, TCP_REQUEST_CANCEL_MODE_CLOSE); + Request = CONTAINING_RECORD(Context->RequestListHead.Blink, + TCP_REQUEST, ListEntry); + tcp_arg(Context->lwip_tcp_pcb, Request); tcp_recv(Context->lwip_tcp_pcb, lwip_tcp_receive_callback); - tcp_arg(Context->lwip_tcp_pcb, AddressFile); return STATUS_PENDING; } 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=71661&r1=71660&r2=71661&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] Thu Jun 23 15:28:39 2016 @@ -1,5 +1,8 @@ #pragma once + +#define TCP_REQUEST_CANCEL_MODE_ABORT 1 +#define TCP_REQUEST_CANCEL_MODE_CLOSE 2 typedef struct _ADDRESS_FILE { LIST_ENTRY ListEntry; @@ -23,9 +26,15 @@ PADDRESS_FILE AddressFile; IPPROTO Protocol; TDI_ADDRESS_IP RequestAddress; - PIRP PendingIrp; + LIST_ENTRY RequestListHead; struct tcp_pcb* lwip_tcp_pcb; } TCP_CONTEXT, *PTCP_CONTEXT; + +typedef struct _TCP_REQUEST { + LIST_ENTRY ListEntry; + PIRP PendingIrp; + UCHAR CancelMode; +} TCP_REQUEST, *PTCP_REQUEST; void TcpIpInitializeAddresses(void); 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=71661&r1=71660&r2=71661&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] Thu Jun 23 15:28:39 2016 @@ -346,6 +346,7 @@ ) { PIO_STACK_LOCATION IrpSp; + PTCP_CONTEXT Context; NTSTATUS Status; ULONG_PTR FileType; @@ -366,6 +367,11 @@ } Status = TcpIpCloseAddress(IrpSp->FileObject->FsContext); break; + case TDI_CONNECTION_FILE: + DPRINT1("TCPIP Close Connection Context\n"); + Context = IrpSp->FileObject->FsContext; + Status = TcpIpCloseAddress(Context->AddressFile); + break; case TDI_CONTROL_CHANNEL_FILE: /* We didn't allocate anything for this. */ Status = STATUS_SUCCESS; @@ -394,13 +400,26 @@ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; + PTCP_CONTEXT Context; PADDRESS_FILE AddressFile; DPRINT1("TcpIpDispatchInternal\n"); IrpSp = IoGetCurrentIrpStackLocation(Irp); - AddressFile = IrpSp->FileObject->FsContext; + switch ((ULONG)IrpSp->FileObject->FsContext2) + { + case TDI_TRANSPORT_ADDRESS_FILE : + AddressFile = IrpSp->FileObject->FsContext; + break; + case TDI_CONNECTION_FILE : + Context = IrpSp->FileObject->FsContext; + AddressFile = Context->AddressFile; + break; + default : + DPRINT1("Unknown FileObject type\n"); + break; + } switch (IrpSp->MinorFunction) { @@ -423,7 +442,6 @@ if (Status == STATUS_NOT_IMPLEMENTED) { DPRINT1("Received TDI_RECEIVE for non-TCP protocol\n"); - } break; case TDI_RECEIVE_DATAGRAM: Modified: branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/opt.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/opt.h?rev=71661&r1=71660&r2=71661&view=diff ============================================================================== --- branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/opt.h [iso-8859-1] (original) +++ branches/GSoC_2016/lwIP-tcpip/sdk/lib/drivers/lwip/src/include/lwip/opt.h [iso-8859-1] Thu Jun 23 15:28:39 2016 @@ -1023,7 +1023,7 @@ * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. */ #ifndef TCP_LISTEN_BACKLOG -#define TCP_LISTEN_BACKLOG 0 +#define TCP_LISTEN_BACKLOG 1 #endif /**