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/wr…
==============================================================================
--- 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 );
+ }
}