Author: cgutman Date: Thu Jul 7 00:29:30 2011 New Revision: 52552
URL: http://svn.reactos.org/svn/reactos?rev=52552&view=rev Log: [AFD] - Rewrite user-mode send IRP handling so send errors get returned to the user properly - Fixes OskitTCP: ESHUTDOWN/EPIPE debug log spam when a chargen telnet session is terminated by the remote side
Modified: trunk/reactos/drivers/network/afd/afd/write.c
Modified: trunk/reactos/drivers/network/afd/afd/write.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/wri... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] Thu Jul 7 00:29:30 2011 @@ -23,7 +23,7 @@ PIO_STACK_LOCATION NextIrpSp; PAFD_SEND_INFO SendReq = NULL; PAFD_MAPBUF Map; - UINT TotalBytesCopied = 0, SpaceAvail, i; + UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
/* * The Irp parameter passed in is the IRP of the stream between AFD and @@ -99,7 +99,42 @@ RtlMoveMemory( FCB->Send.Window, FCB->Send.Window + FCB->Send.BytesUsed, FCB->Send.BytesUsed - Irp->IoStatus.Information ); - FCB->Send.BytesUsed -= Irp->IoStatus.Information; + + TotalBytesProcessed = 0; + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && + TotalBytesProcessed != Irp->IoStatus.Information) { + NextIrpEntry = + RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); + NextIrp = + CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); + NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); + SendReq = GetLockedData(NextIrp, NextIrpSp); + Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); + + TotalBytesCopied = 0; + + for( i = 0; i < SendReq->BufferCount; i++ ) + TotalBytesCopied += SendReq->BufferArray[i].len; + + NextIrp->IoStatus.Status = Irp->IoStatus.Status; + NextIrp->IoStatus.Information = TotalBytesCopied; + + TotalBytesProcessed += TotalBytesCopied; + + (void)IoSetCancelRoutine(NextIrp, NULL); + + UnlockBuffers( SendReq->BufferArray, + SendReq->BufferCount, + FALSE ); + + if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); + + IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); + } + + ASSERT(TotalBytesProcessed == Irp->IoStatus.Information); + + FCB->Send.BytesUsed -= TotalBytesProcessed;
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = @@ -139,19 +174,6 @@ if (NextIrp != NULL) { FCB->Send.BytesUsed += TotalBytesCopied; - - NextIrp->IoStatus.Status = STATUS_SUCCESS; - NextIrp->IoStatus.Information = TotalBytesCopied; - - (void)IoSetCancelRoutine(NextIrp, NULL); - - UnlockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - FALSE ); - - if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); - - IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); } else break; @@ -198,6 +220,7 @@ PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; + PAFD_SEND_INFO SendReq;
AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n", Irp->IoStatus.Status, @@ -210,29 +233,47 @@ FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */
- if (Irp->IoStatus.Status == STATUS_SUCCESS) - { - FCB->PollState |= AFD_EVENT_SEND; - FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } - if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { - NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); - NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); - NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; - NextIrp->IoStatus.Information = 0; - if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); - (void)IoSetCancelRoutine(NextIrp, NULL); - IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); - } - SocketStateUnlock( FCB ); - return STATUS_FILE_CLOSED; - } - - SocketStateUnlock( FCB ); + NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); + NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); + SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); + NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; + NextIrp->IoStatus.Information = 0; + (void)IoSetCancelRoutine(NextIrp, NULL); + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); + IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); + } + SocketStateUnlock( FCB ); + return STATUS_FILE_CLOSED; + } + + ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])); + + /* TDI spec guarantees FIFO ordering on IRPs */ + NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); + NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); + + SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); + + NextIrp->IoStatus.Status = Irp->IoStatus.Status; + NextIrp->IoStatus.Information = Irp->IoStatus.Information; + + (void)IoSetCancelRoutine(NextIrp, NULL); + + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + + UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); + + IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); + + FCB->PollState |= AFD_EVENT_SEND; + FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; + PollReeval(FCB->DeviceExt, FCB->FileObject); + + SocketStateUnlock(FCB);
return STATUS_SUCCESS; } @@ -244,7 +285,6 @@ PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO SendReq; - ULONG Information; UINT TotalBytesCopied = 0, i, SpaceAvail = 0; BOOLEAN NoSpace = FALSE;
@@ -278,29 +318,33 @@
Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
- if( NT_SUCCESS(Status) ) { - Status = TdiSendDatagram - ( &FCB->SendIrp.InFlightRequest, - FCB->AddressFile.Object, - SendReq->BufferArray[0].buf, - SendReq->BufferArray[0].len, - TargetAddress, - &FCB->SendIrp.Iosb, - PacketSocketSendComplete, - FCB ); - - ExFreePool( TargetAddress ); - } - - if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; - - AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status)); - - /* Even if we were pended, we're done with the user buffer at this - * point. */ - Information = SendReq->BufferArray[0].len; - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); - return UnlockAndMaybeComplete( FCB, Status, Irp, Information ); + if( NT_SUCCESS(Status) ) { + FCB->PollState &= ~AFD_EVENT_SEND; + + Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); + if (Status == STATUS_PENDING) + { + TdiSendDatagram(&FCB->SendIrp.InFlightRequest, + FCB->AddressFile.Object, + SendReq->BufferArray[0].buf, + SendReq->BufferArray[0].len, + TargetAddress, + &FCB->SendIrp.Iosb, + PacketSocketSendComplete, + FCB); + } + + ExFreePool( TargetAddress ); + + SocketStateUnlock(FCB); + + return STATUS_PENDING; + } + else + { + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); + } }
if (FCB->DisconnectPending && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE)) @@ -370,6 +414,7 @@
return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_OVERFLOW, Irp, 0); } + SpaceAvail += TotalBytesCopied; NoSpace = TRUE; break; } @@ -394,12 +439,38 @@ return UnlockAndMaybeComplete ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); } - + + if (SpaceAvail) + { + FCB->PollState |= AFD_EVENT_SEND; + FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + else + { + FCB->PollState &= ~AFD_EVENT_SEND; + } + if (!NoSpace) { - UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); FCB->Send.BytesUsed += TotalBytesCopied; - AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied)); + AFD_DbgPrint(MID_TRACE,("Copied %d bytes\n", TotalBytesCopied)); + + Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); + if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) + { + TdiSend(&FCB->SendIrp.InFlightRequest, + FCB->Connection.Object, + 0, + FCB->Send.Window, + FCB->Send.BytesUsed, + &FCB->SendIrp.Iosb, + SendComplete, + FCB); + } + SocketStateUnlock(FCB); + + return STATUS_PENDING; } else { @@ -414,38 +485,6 @@ return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND ); } } - - if (!FCB->SendIrp.InFlightRequest) - { - Status = TdiSend( &FCB->SendIrp.InFlightRequest, - FCB->Connection.Object, - 0, - FCB->Send.Window, - FCB->Send.BytesUsed, - &FCB->SendIrp.Iosb, - SendComplete, - FCB ); - - if( Status == STATUS_PENDING ) - Status = STATUS_SUCCESS; - - AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n", - Status, TotalBytesCopied)); - } - - if (SpaceAvail) - { - FCB->PollState |= AFD_EVENT_SEND; - FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - } - else - { - FCB->PollState &= ~AFD_EVENT_SEND; - } - - return UnlockAndMaybeComplete - ( FCB, Status, Irp, TotalBytesCopied ); }
NTSTATUS NTAPI @@ -456,7 +495,6 @@ PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO_UDP SendReq; - ULONG Information;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
@@ -514,27 +552,29 @@ if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND;
- Status = TdiSendDatagram - ( &FCB->SendIrp.InFlightRequest, - FCB->AddressFile.Object, - SendReq->BufferArray[0].buf, - SendReq->BufferArray[0].len, - TargetAddress, - &FCB->SendIrp.Iosb, - PacketSocketSendComplete, - FCB ); + Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); + if (Status == STATUS_PENDING) + { + TdiSendDatagram(&FCB->SendIrp.InFlightRequest, + FCB->AddressFile.Object, + SendReq->BufferArray[0].buf, + SendReq->BufferArray[0].len, + TargetAddress, + &FCB->SendIrp.Iosb, + PacketSocketSendComplete, + FCB); + }
ExFreePool( TargetAddress ); - } - - if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; - - AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status)); - - /* Even if we were pended, we're done with the user buffer at this - * point. */ - Information = SendReq->BufferArray[0].len; - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); - return UnlockAndMaybeComplete( FCB, Status, Irp, Information ); + + SocketStateUnlock(FCB); + + return STATUS_PENDING; + } + else + { + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); + } }