Author: cgutman Date: Thu Jul 7 20:44:47 2011 New Revision: 52561
URL: http://svn.reactos.org/svn/reactos?rev=52561&view=rev Log: [AFD] - Implement IOCTL_AFD_RECV for connection-less sockets - Fix a parameter check - Fixes recv() on datagram sockets
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] Thu Jul 7 20:44:47 2011 @@ -44,6 +44,48 @@ return !BytesAvailable && (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_ABORT)); +} + +static BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp) +{ + if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) + { + if (IrpSp->MajorFunction == IRP_MJ_READ) + { + /* read() call - no extra buffers */ + return FALSE; + } + else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL) + { + if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM) + { + /* recvfrom() call - extra buffers */ + return TRUE; + } + else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV) + { + /* recv() call - no extra buffers */ + return FALSE; + } + else + { + /* Unknown IOCTL */ + ASSERT(FALSE); + return FALSE; + } + } + else + { + /* Unknown IRP_MJ code */ + ASSERT(FALSE); + return FALSE; + } + } + else + { + /* Connection-oriented never has extra buffers */ + return FALSE; + } }
static VOID RefillSocketBuffer( PAFD_FCB FCB ) { @@ -292,6 +334,97 @@ return STATUS_SUCCESS; }
+static NTSTATUS NTAPI +SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, + PAFD_STORED_DATAGRAM DatagramRecv, + PUINT TotalBytesCopied ) { + NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); + PAFD_RECV_INFO RecvReq = + GetLockedData(Irp, IrpSp); + UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0; + PAFD_MAPBUF Map; + + Map = (PAFD_MAPBUF)(RecvReq->BufferArray + + RecvReq->BufferCount + + EXTRA_LOCK_BUFFERS); + + BytesToCopy = + MIN( RecvReq->BufferArray[0].len, BytesAvailable ); + + AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy, + RecvReq->BufferArray[0].len)); + + if( Map[0].Mdl ) { + /* Copy the address */ + if( Map[1].Mdl && Map[2].Mdl ) { + AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n")); + + if( DatagramRecv->Address->TAAddressCount != 1 ) { + AFD_DbgPrint + (MID_TRACE, + ("Wierd address count %d\n", + DatagramRecv->Address->TAAddressCount)); + } + + AFD_DbgPrint(MID_TRACE,("Computing addr len\n")); + + AddrLen = MIN(DatagramRecv->Address->Address->AddressLength + + sizeof(USHORT), + RecvReq->BufferArray[1].len); + + AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen)); + + Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode ); + + AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n")); + + RtlCopyMemory( Map[1].BufferAddress, + &DatagramRecv->Address->Address->AddressType, + AddrLen ); + + MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl ); + + AFD_DbgPrint(MID_TRACE,("Copying address len\n")); + + Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode ); + *((PINT)Map[2].BufferAddress) = AddrLen; + MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl ); + } + + AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n")); + + Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode ); + + AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n", + 0, + Map[0].BufferAddress, + BytesToCopy)); + + RtlCopyMemory( Map[0].BufferAddress, + DatagramRecv->Buffer, + BytesToCopy ); + + MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl ); + + *TotalBytesCopied = BytesToCopy; + } + + Status = Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = BytesToCopy; + + if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) + { + FCB->Recv.Content -= *TotalBytesCopied; + ExFreePool( DatagramRecv->Address ); + ExFreePool( DatagramRecv ); + } + + AFD_DbgPrint(MID_TRACE,("Done\n")); + + return Status; +} + NTSTATUS NTAPI AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, BOOLEAN Short) { @@ -300,40 +433,95 @@ PAFD_FCB FCB = FileObject->FsContext; PAFD_RECV_INFO RecvReq; UINT TotalBytesCopied = 0; + PAFD_STORED_DATAGRAM DatagramRecv; + PLIST_ENTRY ListEntry;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
- if( FCB->State != SOCKET_STATE_CONNECTED && + if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) && + FCB->State != SOCKET_STATE_CONNECTED && FCB->State != SOCKET_STATE_CONNECTING ) { AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n", FCB->State)); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } + + if( !(RecvReq = LockRequest( Irp, IrpSp )) ) + return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, + Irp, 0 ); + + AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); + + RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, + RecvReq->BufferCount, + NULL, NULL, + TRUE, FALSE ); + + if( !RecvReq->BufferArray ) { + return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, + Irp, 0 ); + }
if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { - AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n")); - return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED, - Irp, 0 ); - } - - if( !(RecvReq = LockRequest( Irp, IrpSp )) ) - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, - Irp, 0 ); - - AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags)); - - RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray, - RecvReq->BufferCount, - NULL, NULL, - TRUE, FALSE ); - - if( !RecvReq->BufferArray ) { - return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, - Irp, 0 ); + if( !IsListEmpty( &FCB->DatagramList ) ) { + ListEntry = RemoveHeadList( &FCB->DatagramList ); + DatagramRecv = CONTAINING_RECORD + ( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); + if( DatagramRecv->Len > RecvReq->BufferArray[0].len && + !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) { + InsertHeadList( &FCB->DatagramList, + &DatagramRecv->ListEntry ); + Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = DatagramRecv->Len; + + if( !IsListEmpty( &FCB->DatagramList ) ) { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); + + return UnlockAndMaybeComplete + ( FCB, Status, Irp, Irp->IoStatus.Information ); + } else { + Status = SatisfyPacketRecvRequest + ( FCB, Irp, DatagramRecv, + (PUINT)&Irp->IoStatus.Information ); + + if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) + { + InsertHeadList(&FCB->DatagramList, + &DatagramRecv->ListEntry); + } + + if( !IsListEmpty( &FCB->DatagramList ) ) { + FCB->PollState |= AFD_EVENT_RECEIVE; + FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } else + FCB->PollState &= ~AFD_EVENT_RECEIVE; + + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); + + return UnlockAndMaybeComplete + ( FCB, Status, Irp, Irp->IoStatus.Information ); + } + } else if( (RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking) ) { + AFD_DbgPrint(MID_TRACE,("Nonblocking\n")); + Status = STATUS_CANT_WAIT; + FCB->PollState &= ~AFD_EVENT_RECEIVE; + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); + } else { + FCB->PollState &= ~AFD_EVENT_RECEIVE; + return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); + } }
Irp->IoStatus.Status = STATUS_PENDING; @@ -367,98 +555,6 @@ return Status; }
- -static NTSTATUS NTAPI -SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp, - PAFD_STORED_DATAGRAM DatagramRecv, - PUINT TotalBytesCopied ) { - NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); - PAFD_RECV_INFO RecvReq = - GetLockedData(Irp, IrpSp); - UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0; - PAFD_MAPBUF Map; - - Map = (PAFD_MAPBUF)(RecvReq->BufferArray + - RecvReq->BufferCount + - EXTRA_LOCK_BUFFERS); - - BytesToCopy = - MIN( RecvReq->BufferArray[0].len, BytesAvailable ); - - AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy, - RecvReq->BufferArray[0].len)); - - if( Map[0].Mdl ) { - /* Copy the address */ - if( Map[1].Mdl && Map[2].Mdl ) { - AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n")); - - if( DatagramRecv->Address->TAAddressCount != 1 ) { - AFD_DbgPrint - (MID_TRACE, - ("Wierd address count %d\n", - DatagramRecv->Address->TAAddressCount)); - } - - AFD_DbgPrint(MID_TRACE,("Computing addr len\n")); - - AddrLen = MIN(DatagramRecv->Address->Address->AddressLength + - sizeof(USHORT), - RecvReq->BufferArray[1].len); - - AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen)); - - Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode ); - - AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n")); - - RtlCopyMemory( Map[1].BufferAddress, - &DatagramRecv->Address->Address->AddressType, - AddrLen ); - - MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl ); - - AFD_DbgPrint(MID_TRACE,("Copying address len\n")); - - Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode ); - *((PINT)Map[2].BufferAddress) = AddrLen; - MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl ); - } - - AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n")); - - Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode ); - - AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n", - 0, - Map[0].BufferAddress, - BytesToCopy)); - - RtlCopyMemory( Map[0].BufferAddress, - DatagramRecv->Buffer, - BytesToCopy ); - - MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl ); - - *TotalBytesCopied = BytesToCopy; - } - - Status = Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = BytesToCopy; - - if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) - { - FCB->Recv.Content -= *TotalBytesCopied; - ExFreePool( DatagramRecv->Address ); - ExFreePool( DatagramRecv ); - } - - AFD_DbgPrint(MID_TRACE,("Done\n")); - - return Status; -} - NTSTATUS NTAPI PacketSocketRecvComplete( PDEVICE_OBJECT DeviceObject, @@ -491,7 +587,7 @@ RecvReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; - UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); + UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp)); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); @@ -561,7 +657,7 @@ &DatagramRecv->ListEntry ); Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; NextIrp->IoStatus.Information = DatagramRecv->Len; - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); @@ -576,7 +672,7 @@ &DatagramRecv->ListEntry); } AFD_DbgPrint(MID_TRACE,("Unlocking\n")); - UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE ); + UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); AFD_DbgPrint(MID_TRACE,("Completing\n")); (void)IoSetCancelRoutine(NextIrp, NULL);