Author: cgutman Date: Mon May 10 23:14:26 2010 New Revision: 47156
URL: http://svn.reactos.org/svn/reactos?rev=47156&view=rev Log: [AFD] - Fix signaling socket termination events on disconnect - Fixes bug 4951
Modified: trunk/reactos/drivers/network/afd/afd/read.c
Modified: trunk/reactos/drivers/network/afd/afd/read.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/rea... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/read.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/read.c [iso-8859-1] Mon May 10 23:14:26 2010 @@ -26,10 +26,38 @@ #include "tdiconn.h" #include "debug.h"
-static BOOLEAN CantReadMore( PAFD_FCB FCB ) { - UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; - - return !BytesAvailable; +static NTSTATUS RefillSocketBuffer( PAFD_FCB FCB ) { + NTSTATUS Status = STATUS_PENDING; + + if( !FCB->ReceiveIrp.InFlightRequest ) { + AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n")); + + Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, + FCB->Connection.Object, + TDI_RECEIVE_NORMAL, + FCB->Recv.Window, + FCB->Recv.Size, + &FCB->ReceiveIrp.Iosb, + ReceiveComplete, + FCB ); + + if( ( Status == STATUS_SUCCESS && !FCB->ReceiveIrp.Iosb.Information ) || + ( !NT_SUCCESS( Status ) ) ) + { + /* The socket has been closed */ + FCB->PollState |= AFD_EVENT_DISCONNECT; + FCB->Overread = TRUE; + Status = STATUS_FILE_CLOSED; + } + else if( Status == STATUS_SUCCESS ) + { + FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information; + FCB->PollState |= AFD_EVENT_RECEIVE; + } + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + + return Status; }
static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB, @@ -46,7 +74,22 @@ AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n", BytesAvailable));
- if( CantReadMore(FCB) ) return STATUS_PENDING; + if( FCB->Overread ) return STATUS_FILE_CLOSED; + if( !BytesAvailable ) { + FCB->Recv.Content = FCB->Recv.BytesUsed = 0; + Status = RefillSocketBuffer( FCB ); + if ( Status != STATUS_SUCCESS ) + return Status; + + /* If RefillSocketBuffer returns STATUS_SUCCESS, we're good to go + * If RefillSocketBuffer returns STATUS_PENDING, then it's waiting on the transport for data + * If RefillSocketBuffer returns STATUS_FILE_CLOSED, then the connection was terminated + */ + + /* Recalculate BytesAvailable based on new data */ + BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; + ASSERT(BytesAvailable); + }
Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
@@ -88,23 +131,8 @@ if( FCB->Recv.BytesUsed == FCB->Recv.Content ) { FCB->Recv.BytesUsed = FCB->Recv.Content = 0; FCB->PollState &= ~AFD_EVENT_RECEIVE; - PollReeval( FCB->DeviceExt, FCB->FileObject ); - - if( !FCB->ReceiveIrp.InFlightRequest ) { - AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n")); - - Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, - FCB->Connection.Object, - TDI_RECEIVE_NORMAL, - FCB->Recv.Window, - FCB->Recv.Size, - &FCB->ReceiveIrp.Iosb, - ReceiveComplete, - FCB ); - - if( Status == STATUS_SUCCESS ) - FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information; - } + + RefillSocketBuffer( FCB ); }
return STATUS_SUCCESS; @@ -159,7 +187,7 @@ } }
- if( !CantReadMore(FCB) ) { + if( !FCB->Recv.Content ) { FCB->PollState |= AFD_EVENT_RECEIVE; } else FCB->PollState &= ~AFD_EVENT_RECEIVE;