⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connect.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
字号:
/* $Id: connect.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/connect.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"

NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) {
    NTSTATUS Status;

    if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) {
	AFD_DbgPrint(MID_TRACE,("Null Device\n"));
	return STATUS_NO_SUCH_DEVICE;
    }

    Status = TdiOpenConnectionEndpointFile
	( &FCB->TdiDeviceName,
	  &FCB->Connection.Handle,
	  &FCB->Connection.Object );

    if( NT_SUCCESS(Status) ) {
	Status = TdiAssociateAddressFile
	    ( FCB->AddressFile.Handle,
	      FCB->Connection.Object );
    }

    if( !NT_SUCCESS(Status) ) {
	TdiCloseDevice( &FCB->Connection.Handle,
			FCB->Connection.Object );
	RtlZeroMemory( &FCB->Connection, sizeof(FCB->Connection) );
    }

    return Status;
}

NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) {
    NTSTATUS Status = STATUS_NO_MEMORY;

    /* Allocate the receive area and start receiving */
    FCB->Recv.Window =
	ExAllocatePool( NonPagedPool, FCB->Recv.Size );
    FCB->Send.Window =
	ExAllocatePool( NonPagedPool, FCB->Send.Size );

    FCB->State = SOCKET_STATE_CONNECTED;

    if( FCB->Recv.Window ) {
	Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
			     FCB->Connection.Object,
			     TDI_RECEIVE_NORMAL,
			     FCB->Recv.Window,
			     FCB->Recv.Size,
			     &FCB->ReceiveIrp.Iosb,
			     ReceiveComplete,
			     FCB );
    }

    return Status;
}

static NTSTATUS NTAPI StreamSocketConnectComplete
( PDEVICE_OBJECT DeviceObject,
  PIRP Irp,
  PVOID Context ) {
    NTSTATUS Status = Irp->IoStatus.Status;
    PAFD_FCB FCB = (PAFD_FCB)Context;
    PLIST_ENTRY NextIrpEntry;
    PIRP NextIrp;

    AFD_DbgPrint(MID_TRACE,("Called: FCB %x, FO %x\n",
			    Context, FCB->FileObject));

    /* I was wrong about this before as we can have pending writes to a not
     * yet connected socket */
    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );

    AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n",
			    Irp->IoStatus.Status));

    if( NT_SUCCESS(Irp->IoStatus.Status) ) {
	FCB->PollState |= AFD_EVENT_CONNECT | AFD_EVENT_SEND;
	FCB->State = SOCKET_STATE_CONNECTED;
	AFD_DbgPrint(MID_TRACE,("Going to connected state %d\n", FCB->State));
	PollReeval( FCB->DeviceExt, FCB->FileObject );
    } else {
	FCB->PollState |= AFD_EVENT_CONNECT_FAIL | AFD_EVENT_RECEIVE;
	AFD_DbgPrint(MID_TRACE,("Going to bound state\n"));
	FCB->State = SOCKET_STATE_BOUND;
	PollReeval( FCB->DeviceExt, FCB->FileObject );
    }

    /* Succeed pending irps on the FUNCTION_CONNECT list */
    while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) {
	NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]);
	NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
	AFD_DbgPrint(MID_TRACE,("Completing connect %x\n", NextIrp));
	NextIrp->IoStatus.Status = Status;
	NextIrp->IoStatus.Information = 0;
	IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
    }

    if( NT_SUCCESS(Status) ) {
	Status = MakeSocketIntoConnection( FCB );

	if( FCB->Send.Window &&
	    !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
	    NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
	    NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP,
					Tail.Overlay.ListEntry);
	    AFD_DbgPrint(MID_TRACE,("Launching send request %x\n", NextIrp));
	    Status = AfdConnectedSocketWriteData
		( DeviceObject,
		  NextIrp,
		  IoGetCurrentIrpStackLocation( NextIrp ),
		  FALSE );
	}

	if( Status == STATUS_PENDING )
	    Status = STATUS_SUCCESS;
    }

    SocketStateUnlock( FCB );

    AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));

    return Status;
}

/* Return the socket object for ths request only if it is a connected or
   stream type. */
NTSTATUS STDCALL
AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
		       PIO_STACK_LOCATION IrpSp) {
    NTSTATUS Status = STATUS_INVALID_PARAMETER;
    PTDI_CONNECTION_INFORMATION TargetAddress;
    PFILE_OBJECT FileObject = IrpSp->FileObject;
    PAFD_FCB FCB = FileObject->FsContext;
    PAFD_CONNECT_INFO ConnectReq;
    AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));

    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
    if( !(ConnectReq = LockRequest( Irp, IrpSp )) )
	return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp,
				       0, NULL, TRUE );

    AFD_DbgPrint(MID_TRACE,("Connect request:\n"));
#if 0
    OskitDumpBuffer
	( (PCHAR)ConnectReq,
	  IrpSp->Parameters.DeviceIoControl.InputBufferLength );
#endif

    switch( FCB->State ) {
    case SOCKET_STATE_CONNECTED:
	Status = STATUS_SUCCESS;
	break;

    case SOCKET_STATE_CONNECTING:
	return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );

    case SOCKET_STATE_CREATED: {
	FCB->LocalAddress =
	    TaCopyTransportAddress( &ConnectReq->RemoteAddress );

	if( FCB->LocalAddress ) {
	    RtlZeroMemory( FCB->LocalAddress,
			   TaLengthOfTransportAddress
			   ( &ConnectReq->RemoteAddress ) );

	    FCB->LocalAddress->TAAddressCount = 1;
	    FCB->LocalAddress->Address[0].AddressType =
		ConnectReq->RemoteAddress.Address[0].AddressType;
	    FCB->LocalAddress->Address[0].AddressLength =
		ConnectReq->RemoteAddress.Address[0].AddressLength;

	    Status = WarmSocketForBind( FCB );

	    if( NT_SUCCESS(Status) )
		FCB->State = SOCKET_STATE_BOUND;
	    else
		return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL,
					       TRUE );
	} else
	    return UnlockAndMaybeComplete
		( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, TRUE );
    } /* Drop through to SOCKET_STATE_BOUND */

    case SOCKET_STATE_BOUND:
	FCB->RemoteAddress =
	    TaCopyTransportAddress( &ConnectReq->RemoteAddress );

	if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
	{
	    Status = STATUS_SUCCESS;
	    break;
	}

	Status = WarmSocketForConnection( FCB );

	if( !NT_SUCCESS(Status) )
	    break;

	FCB->State = SOCKET_STATE_CONNECTING;

	TdiBuildConnectionInfo
	    ( &TargetAddress,
	      &ConnectReq->RemoteAddress );

	if( TargetAddress ) {
	    Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest,
				 FCB->Connection.Object,
				 TargetAddress,
				 &FCB->ConnectIrp.Iosb,
				 StreamSocketConnectComplete,
				 FCB );

	    ExFreePool( TargetAddress );

	    AFD_DbgPrint(MID_TRACE,("Queueing IRP %x\n", Irp));

	    if( Status == STATUS_PENDING )
		return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT );
	} else Status = STATUS_NO_MEMORY;
	break;

    default:
	AFD_DbgPrint(MID_TRACE,("Inappropriate socket state %d for connect\n",
				FCB->State));
	break;
    }

    return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -