[AFD]
[reactos.git] / reactos / drivers / network / afd / afd / read.c
index 10d2ea9..3c6ddaa 100644 (file)
 #include "tdiconn.h"
 #include "debug.h"
 
-static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
-    UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
+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 !BytesAvailable;
+       return Status;
 }
 
 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
@@ -46,7 +74,22 @@ static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
     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 @@ static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
     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;
@@ -154,11 +182,12 @@ static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
                        RetBytesCopied = TotalBytesCopied;
                }
                if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                (void)IoSetCancelRoutine(NextIrp, NULL);
                IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
           }
     }
 
-    if( !CantReadMore(FCB) ) {
+    if( !FCB->Recv.Content ) {
                FCB->PollState |= AFD_EVENT_RECEIVE;
     } else
                FCB->PollState &= ~AFD_EVENT_RECEIVE;
@@ -188,8 +217,6 @@ NTSTATUS NTAPI ReceiveComplete
 
     AFD_DbgPrint(MID_TRACE,("Called\n"));
 
-    ASSERT_IRQL(APC_LEVEL);
-
     if( !SocketAcquireStateLock( FCB ) )
         return STATUS_FILE_CLOSED;
 
@@ -210,6 +237,7 @@ NTSTATUS NTAPI ReceiveComplete
               NextIrp->IoStatus.Information = 0;
               UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+               (void)IoSetCancelRoutine(NextIrp, NULL);
               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
         }
        SocketStateUnlock( FCB );
@@ -292,6 +320,7 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     } else if( Status == STATUS_PENDING ) {
         AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
         IoMarkIrpPending( Irp );
+        (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
     } else {
         AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
     }
@@ -427,6 +456,7 @@ PacketSocketRecvComplete(
               NextIrp->IoStatus.Information = 0;
               UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+               (void)IoSetCancelRoutine(NextIrp, NULL);
               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
         }
 
@@ -489,6 +519,7 @@ PacketSocketRecvComplete(
                        NextIrp->IoStatus.Information = DatagramRecv->Len;
                        UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
             if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                        (void)IoSetCancelRoutine(NextIrp, NULL);
                        IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
                } else {
                        AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
@@ -499,6 +530,7 @@ PacketSocketRecvComplete(
                        UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
             if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
                        AFD_DbgPrint(MID_TRACE,("Completing\n"));
+                        (void)IoSetCancelRoutine(NextIrp, NULL);
                        IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
                }
     }