[AFD]
[reactos.git] / reactos / drivers / network / afd / afd / read.c
index 1c73a46..3c6ddaa 100644 (file)
 #include "tdiconn.h"
 #include "debug.h"
 
-static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
-    UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
-
-    return !BytesAvailable &&
-        (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
-}
-
-static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, UINT Information ) {
-    if( !NT_SUCCESS(Status) || 
-               (Status == STATUS_SUCCESS && Information == 0) ) {
-        AFD_DbgPrint(MID_TRACE,("Looks like an EOF\n"));
-        FCB->PollState |= AFD_EVENT_DISCONNECT;
+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,
@@ -56,8 +74,22 @@ static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
     AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
                                                        BytesAvailable));
 
-    if( CantReadMore(FCB) ) return STATUS_SUCCESS;
-    if( !BytesAvailable ) 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);
 
@@ -99,24 +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;
-            HandleEOFOnIrp( FCB, Status, FCB->ReceiveIrp.Iosb.Information );
-               }
+        RefillSocketBuffer( FCB );
     }
 
     return STATUS_SUCCESS;
@@ -132,77 +148,46 @@ static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
 
     AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
 
-    if( CantReadMore( FCB ) ) {
-        /* Success here means that we got an EOF.  Complete a pending read
-         * with zero bytes if we haven't yet overread, then kill the others.
-         */
-        while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
-            NextIrpEntry =
-                RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
-            NextIrp =
-                CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
-            NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
-            RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-
-            AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
-                                    TotalBytesCopied));
-            UnlockBuffers( RecvReq->BufferArray,
-                           RecvReq->BufferCount, FALSE );
-            Status = NextIrp->IoStatus.Status =
-                FCB->Overread ? STATUS_END_OF_FILE : STATUS_SUCCESS;
-            NextIrp->IoStatus.Information = 0;
-            if( NextIrp == Irp ) RetStatus = Status;
-            if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
-            IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
-            FCB->Overread = TRUE;
-            //FCB->PollState |= AFD_EVENT_DISCONNECT;
-            PollReeval( FCB->DeviceExt, FCB->FileObject );
-        }
-    } else {
-               /* Kick the user that receive would be possible now */
-               /* XXX Not implemented yet */
-
-               AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
-                                                               FCB, FCB->Recv.Content));
-               /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
-
-               /* Try to clear some requests */
-               while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
-                       NextIrpEntry =
-                               RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
-                       NextIrp =
-                               CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
-                       NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
-                       RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-
-                       AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
-
-                       Status = TryToSatisfyRecvRequestFromBuffer
-                               ( FCB, RecvReq, &TotalBytesCopied );
-
-                       if( Status == STATUS_PENDING ) {
-                               AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
-                               InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
-                                                          &NextIrp->Tail.Overlay.ListEntry);
-                               break;
-                       } else {
-                               AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
-                                                                               TotalBytesCopied));
-                               UnlockBuffers( RecvReq->BufferArray,
-                                                          RecvReq->BufferCount, FALSE );
-                               NextIrp->IoStatus.Status = Status;
-                               NextIrp->IoStatus.Information = TotalBytesCopied;
-                               if( NextIrp == Irp ) { 
-                                       RetStatus = Status;
-                                       RetBytesCopied = TotalBytesCopied;
-                               }
-                               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
-                               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
-                       }
+    /* Kick the user that receive would be possible now */
+    /* XXX Not implemented yet */
+
+    AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
+                                               FCB, FCB->Recv.Content));
+
+    /* Try to clear some requests */
+    while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+          NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+          NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+          NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+          RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+
+          AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
+
+          Status = TryToSatisfyRecvRequestFromBuffer( FCB, RecvReq, &TotalBytesCopied );
+
+          if( Status == STATUS_PENDING ) {
+               AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
+               InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
+                                          &NextIrp->Tail.Overlay.ListEntry);
+               break;
+          } else {
+               AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
+                                                               TotalBytesCopied));
+               UnlockBuffers( RecvReq->BufferArray,
+                                          RecvReq->BufferCount, FALSE );
+               NextIrp->IoStatus.Status = Status;
+               NextIrp->IoStatus.Information = TotalBytesCopied;
+               if( NextIrp == Irp ) { 
+                       RetStatus = Status;
+                       RetBytesCopied = TotalBytesCopied;
                }
+               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                (void)IoSetCancelRoutine(NextIrp, NULL);
+               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+          }
     }
 
-    if( FCB->Recv.Content ) {
+    if( !FCB->Recv.Content ) {
                FCB->PollState |= AFD_EVENT_RECEIVE;
     } else
                FCB->PollState &= ~AFD_EVENT_RECEIVE;
@@ -232,8 +217,6 @@ NTSTATUS NTAPI ReceiveComplete
 
     AFD_DbgPrint(MID_TRACE,("Called\n"));
 
-    ASSERT_IRQL(APC_LEVEL);
-
     if( !SocketAcquireStateLock( FCB ) )
         return STATUS_FILE_CLOSED;
 
@@ -254,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 );
@@ -264,11 +248,7 @@ NTSTATUS NTAPI ReceiveComplete
         return STATUS_INVALID_PARAMETER;
     }
 
-    HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
-
        ReceiveActivity( FCB, NULL );
-
-       PollReeval( FCB->DeviceExt, FCB->FileObject );
                
     SocketStateUnlock( FCB );
 
@@ -303,9 +283,6 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                                                           Irp, 0 );
     }
 
-    FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
-    PollReeval( FCB->DeviceExt, FCB->FileObject );
-
     if( !(RecvReq = LockRequest( Irp, IrpSp )) )
                return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
                                                                           Irp, 0 );
@@ -332,7 +309,7 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     Status = ReceiveActivity( FCB, Irp );
 
-    if( Status == STATUS_PENDING && RecvReq->AfdFlags & AFD_IMMEDIATE ) {
+    if( Status == STATUS_PENDING && (RecvReq->AfdFlags & AFD_IMMEDIATE) ) {
         AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
         Status = STATUS_CANT_WAIT;
         TotalBytesCopied = 0;
@@ -343,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));
     }
@@ -478,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 );
         }
 
@@ -540,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"));
@@ -550,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 );
                }
     }
@@ -595,8 +576,6 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
 
-    FCB->EventsFired &= ~AFD_EVENT_RECEIVE;
-
     /* Check that the socket is bound */
     if( FCB->State != SOCKET_STATE_BOUND )
                return UnlockAndMaybeComplete
@@ -660,10 +639,12 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
                AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
                Status = STATUS_CANT_WAIT;
+               FCB->PollState &= ~AFD_EVENT_RECEIVE;
                PollReeval( FCB->DeviceExt, FCB->FileObject );
                UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
                return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
     } else {
+               FCB->PollState &= ~AFD_EVENT_RECEIVE;
                PollReeval( FCB->DeviceExt, FCB->FileObject );
                return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
     }