📄 listen.c
字号:
/* $Id: listen.c 21689 2006-04-21 17:45:51Z tretiakov $
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/listen.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
static VOID SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt,
PIRP Irp,
PFILE_OBJECT NewFileObject,
PAFD_TDI_OBJECT_QELT Qelt ) {
PAFD_FCB FCB = NewFileObject->FsContext;
if( !SocketAcquireStateLock( FCB ) ) return;
/* Transfer the connection to the new socket, launch the opening read */
AFD_DbgPrint(MID_TRACE,("Completing a real accept (FCB %x)\n", FCB));
FCB->State = SOCKET_STATE_CONNECTED;
FCB->Connection = Qelt->Object;
FCB->RemoteAddress =
TaCopyTransportAddress( Qelt->ConnInfo->RemoteAddress );
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
MakeSocketIntoConnection( FCB );
FCB->PollState |= AFD_EVENT_SEND;
PollReeval( DeviceExt, NewFileObject );
SocketStateUnlock( FCB );
}
static VOID SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) {
PAFD_RECEIVED_ACCEPT_DATA ListenReceive =
(PAFD_RECEIVED_ACCEPT_DATA)Irp->AssociatedIrp.SystemBuffer;
PTA_IP_ADDRESS IPAddr;
ListenReceive->SequenceNumber = Qelt->Seq;
AFD_DbgPrint(MID_TRACE,("Giving SEQ %d to userland\n", Qelt->Seq));
AFD_DbgPrint(MID_TRACE,("Socket Address (K) %x (U) %x\n",
&ListenReceive->Address,
Qelt->ConnInfo->RemoteAddress));
TaCopyTransportAddressInPlace( &ListenReceive->Address,
Qelt->ConnInfo->RemoteAddress );
IPAddr = (PTA_IP_ADDRESS)&ListenReceive->Address;
AFD_DbgPrint(MID_TRACE,("IPAddr->TAAddressCount %d\n",
IPAddr->TAAddressCount));
AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressType %d\n",
IPAddr->Address[0].AddressType));
AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressLength %d\n",
IPAddr->Address[0].AddressLength));
AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_port %x\n",
IPAddr->Address[0].Address[0].sin_port));
AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_addr %x\n",
IPAddr->Address[0].Address[0].in_addr));
Irp->IoStatus.Information = ((PCHAR)&IPAddr[1]) - ((PCHAR)ListenReceive);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
}
static NTSTATUS NTAPI ListenComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PAFD_FCB FCB = (PAFD_FCB)Context;
PAFD_TDI_OBJECT_QELT Qelt;
if ( Irp->Cancel ) {
/* FIXME: is this anything else we need to do? */
return STATUS_SUCCESS;
}
if( !SocketAcquireStateLock( FCB ) ) return Status;
FCB->ListenIrp.InFlightRequest = NULL;
if( FCB->State == SOCKET_STATE_CLOSED ) {
SocketStateUnlock( FCB );
DestroySocket( FCB );
return STATUS_SUCCESS;
}
AFD_DbgPrint(MID_TRACE,("Completing listen request.\n"));
AFD_DbgPrint(MID_TRACE,("IoStatus was %x\n", FCB->ListenIrp.Iosb.Status));
Qelt = ExAllocatePool( NonPagedPool, sizeof(*Qelt) );
if( !Qelt ) {
TdiCloseDevice( FCB->Connection.Handle,
FCB->Connection.Object );
} else {
UINT AddressType =
FCB->LocalAddress->Address[0].AddressType;
Qelt->Object = FCB->Connection;
Qelt->Seq = FCB->ConnSeq++;
AFD_DbgPrint(MID_TRACE,("Address Type: %d (RA %x)\n",
AddressType,
FCB->ListenIrp.
ConnectionReturnInfo->RemoteAddress));
TdiBuildNullConnectionInfo( &Qelt->ConnInfo, AddressType );
TaCopyTransportAddressInPlace
( Qelt->ConnInfo->RemoteAddress,
FCB->ListenIrp.ConnectionReturnInfo->RemoteAddress );
InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry );
}
/* Satisfy a pre-accept request if one is available */
if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ) &&
!IsListEmpty( &FCB->PendingConnections ) ) {
PLIST_ENTRY PendingIrp =
RemoveHeadList( &FCB->PendingIrpList[FUNCTION_PREACCEPT] );
PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink;
SatisfyPreAccept
( CONTAINING_RECORD( PendingIrp, IRP,
Tail.Overlay.ListEntry ),
CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT,
ListEntry ) );
}
FCB->NeedsNewListen = TRUE;
/* Trigger a select return if appropriate */
if( !IsListEmpty( &FCB->PendingConnections ) ) {
FCB->PollState |= AFD_EVENT_ACCEPT;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
PAFD_LISTEN_DATA ListenReq;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
if( !(ListenReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
0, NULL, FALSE );
if( FCB->State != SOCKET_STATE_BOUND ) {
Status = STATUS_UNSUCCESSFUL;
AFD_DbgPrint(MID_TRACE,("Could not listen an unbound socket\n"));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}
FCB->DelayedAccept = ListenReq->UseDelayedAcceptance;
AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle));
Status = WarmSocketForConnection( FCB );
FCB->State = SOCKET_STATE_LISTENING;
AFD_DbgPrint(MID_TRACE,("Status from warmsocket %x\n", Status));
TdiBuildNullConnectionInfo
( &FCB->ListenIrp.ConnectionCallInfo,
FCB->LocalAddress->Address[0].AddressType );
TdiBuildNullConnectionInfo
( &FCB->ListenIrp.ConnectionReturnInfo,
FCB->LocalAddress->Address[0].AddressType );
Status = TdiListen( &FCB->ListenIrp.InFlightRequest,
FCB->Connection.Object,
&FCB->ListenIrp.ConnectionCallInfo,
&FCB->ListenIrp.ConnectionReturnInfo,
&FCB->ListenIrp.Iosb,
ListenComplete,
FCB );
if( NT_SUCCESS(Status) || Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}
NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
if( !IsListEmpty( &FCB->PendingConnections ) ) {
PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink;
/* We have a pending connection ... complete this irp right away */
SatisfyPreAccept
( Irp,
CONTAINING_RECORD
( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ) );
AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n"));
FCB->PollState &= ~AFD_EVENT_ACCEPT;
PollReeval( FCB->DeviceExt, FCB->FileObject );
SocketStateUnlock( FCB );
return Status;
} else {
AFD_DbgPrint(MID_TRACE,("Holding\n"));
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_PREACCEPT );
}
}
NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp ) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_DEVICE_EXTENSION DeviceExt =
(PAFD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
PAFD_FCB FCB = FileObject->FsContext;
PAFD_ACCEPT_DATA AcceptData = Irp->AssociatedIrp.SystemBuffer;
PLIST_ENTRY PendingConn;
AFD_DbgPrint(MID_TRACE,("Called\n"));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE );
FCB->EventsFired &= ~AFD_EVENT_ACCEPT;
if( FCB->NeedsNewListen ) {
AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle));
/* Launch new accept socket */
Status = WarmSocketForConnection( FCB );
if( Status == STATUS_SUCCESS ) {
TdiBuildNullConnectionInfo
( &FCB->ListenIrp.ConnectionReturnInfo,
FCB->LocalAddress->Address[0].AddressType );
Status = TdiListen( &FCB->ListenIrp.InFlightRequest,
FCB->Connection.Object,
&FCB->ListenIrp.ConnectionCallInfo,
&FCB->ListenIrp.ConnectionReturnInfo,
&FCB->ListenIrp.Iosb,
ListenComplete,
FCB );
}
FCB->NeedsNewListen = FALSE;
}
for( PendingConn = FCB->PendingConnections.Flink;
PendingConn != &FCB->PendingConnections;
PendingConn = PendingConn->Flink ) {
PAFD_TDI_OBJECT_QELT PendingConnObj =
CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry );
AFD_DbgPrint(MID_TRACE,("Comparing Seq %d to Q %d\n",
AcceptData->SequenceNumber,
PendingConnObj->Seq));
if( PendingConnObj->Seq == AcceptData->SequenceNumber ) {
PFILE_OBJECT NewFileObject = NULL;
RemoveEntryList( PendingConn );
Status = ObReferenceObjectByHandle
( (HANDLE)AcceptData->ListenHandle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID *)&NewFileObject,
NULL );
ASSERT(NewFileObject != FileObject);
ASSERT(NewFileObject->FsContext != FCB);
/* We have a pending connection ... complete this irp right away */
SatisfyAccept( DeviceExt, Irp, NewFileObject, PendingConnObj );
ObDereferenceObject( NewFileObject );
AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n"));
ExFreePool( PendingConnObj );
if( IsListEmpty( &FCB->PendingConnections ) )
FCB->PollState &= ~AFD_EVENT_ACCEPT;
SocketStateUnlock( FCB );
return Status;
}
}
SocketStateUnlock( FCB );
return STATUS_UNSUCCESSFUL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -