About TDI and connection acceptance.

Hi,

I would like to know how to use the TDI interface to accept
an incoming connection, after a TDI_LISTEN irp is issued.

I know that it can also be done by not using TDI_LISTEN,
and accepting the call in the connect event handler.
But I would like to know how to accept connections using the
“listen” method.

I am working on a test driver which iteratively listens to connect
attempts from clients and sends each client the time of the day
after accepting the call.

Thanks in advance.
Regards
Taher

> I know that it can also be done by not using TDI_LISTEN,

and accepting the call in the connect event handler.
But I would like to know how to accept connections using the
“listen” method.

Why?
In ClientEventConnect, allocate the TDI_ACCEPT IRP, do not forget to call IoSetNextIrpStackLocation on it. Register a completion
routine in it.
Return it to TDI with STATUS_MORE_PROCESSING_REQUIRED.
In the completion routine, the TDI’s file object referenced by this IRP is a complete connection, you can transfer data on it.

Note that you must pre-create this file object (or usually many file objects) and put it to some list for ClientEventConnect to pick
it from this list while building the TDI_ACCEPT IRP. This is called “listen backlog” and natively implemented in AFD.SYS.

Max

Hi,

Try something like this…

Regards,
Anton Kolomyeytsev

NTSTATUS
KsockCoreCallEx(
IN PFILE_OBJECT pFileObjectConnection,
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PKEVENT pkEvent,
IN PIO_STATUS_BLOCK pIoStatusBlock,
IN ULONG ulongTimeOutInMsec
)

/*++

Routine Description:

Calls underlying device object in a sync way

Arguments:

Ptr to file connection object
Ptr to connection file object
Ptr to IRP pass to device
Ptr to kernel event use for sync
Ptr to I/O status block
Time out in milliseconds

Return Value:

Execution status

–*/

{
NTSTATUS ntStatus;

LARGE_INTEGER largeIntegerTimeout;

kiprint( “Ksock:KsockCoreCallEx(): ENTERed…\n” );

//
// try to call underlying device object
//
ntStatus =
IoCallDriver(
pDeviceObject,
pIrp
);

//
// check for the status of IoCallDriver(…)
//
if ( ntStatus == STATUS_PENDING )
{
kiprint( “Ksock:KsockCoreCallEx(): IoCallDriver() is pending…\n” );

//
// prepare timeout…
//

largeIntegerTimeout.QuadPart = 10000L; // in milliseconds…

largeIntegerTimeout.QuadPart *= ulongTimeOutInMsec;

largeIntegerTimeout.QuadPart = -( largeIntegerTimeout.QuadPart ); //
relative time to wait…

//
// wait for async I/O completion (wait with timeout…)
//
ntStatus =
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
&largeIntegerTimeout
);

//
// check if this is timeout
//
if ( ntStatus == STATUS_TIMEOUT )
{
keprint( “Ksock:KsockCoreCallEx(): call timeouted…\n” );

//
// try to disconnect endpoint
//
KsockCoreDisconnectEndpoint( pFileObjectConnection );

//
// wait for async I/O completion (wait forever…)
//
ntStatus =
KeWaitForSingleObject(
pkEvent,
Executive,
KernelMode,
FALSE,
NULL
);
}
}

//
// check for the status of KeWaitForSingleObject() or IoCallDriver()
call…
//
if ( NT_SUCCESS( ntStatus ) == FALSE )
{
keprint(
“Ksock:KsockCoreCallEx(): KeWaitForSingleObject() or IoCallDriver()
failed, status == 0x%08X!\n”,
ntStatus
);

//
// return bad status
//
return ntStatus;
}

kiprint(
“Ksock:KsockCoreCallEx(): EXITing with success, async I/O status ==
0x%08X…\n”,
pIoStatusBlock->Status
);

//
// return final status
//
return pIoStatusBlock->Status;
}

NTSTATUS
KsockCoreAccept(
IN PFILE_OBJECT pFileObjectConnection,
IN ULONG ulongTimeOutInMsec
)

/*++

Routine Description:

Accepts incoming client

Arguments:

Ptr to handle of connection
Timeout in msec

Return Value:

Execution status

–*/

{
KEVENT kEvent;

PDEVICE_OBJECT pDeviceObject;

IO_STATUS_BLOCK ioStatusBlock;

PIRP pIrp;

NTSTATUS ntStatus;

TA_IP_ADDRESS taIpAddress;

TDI_CONNECTION_INFORMATION tdiConnectionInformation;

kiprint( “Ksock:KsockCoreAccept(): ENTERed…\n” );

//
// init IP address
//

RtlZeroMemory(
&taIpAddress,
sizeof( taIpAddress )
);

taIpAddress.TAAddressCount = 1;

taIpAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;

taIpAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;

//
// init connection info
//

RtlZeroMemory(
&tdiConnectionInformation,
sizeof( tdiConnectionInformation ),
);

tdiConnectionInformation.RemoteAddressLength = sizeof( taIpAddress );

tdiConnectionInformation.RemoteAddress = &taIpAddress;

//
// get underlying device object
//
pDeviceObject = IoGetRelatedDeviceObject( pFileObjectConnection );

//
// initalize event as notify one
//
KeInitializeEvent(
&kEvent,
NotificationEvent,
FALSE
);

//
// build I/O request packet
//
pIrp =
TdiBuildInternalDeviceControlIrp(
TDI_ACCEPT,
pDeviceObject,
pFileObjectConnection,
&kEvent,
&ioStatusBlock
);

//
// check for allocated IRP
//
if ( pIrp == NULL )
{
keprint( “Ksock:KsockCoreAccept(): TdiBuildInternalDeviceControlIrp()
failed!\n” );

//
// return bad status
//
return STATUS_NO_MEMORY;
}

//
// build IOCTL
//
TdiBuildAccept(
pIrp,
pDeviceObject,
pFileObjectConnection,
NULL,
NULL,
&tdiConnectionInformation,
NULL
);

//
// call the device
//
ntStatus =
KsockCoreCallEx(
pFileObjectConnection,
pDeviceObject,
pIrp,
&kEvent,
&ioStatusBlock,
ulongTimeOutInMsec
);

//
// check for success
//
if ( NT_SUCCESS( ntStatus ) == FALSE )
{
keprint(
“Ksock:KsockCoreAccept(): KsockCoreCallEx() failed, status ==
0x%08X!\n”,
ntStatus
);

//
// return bad status
//
return ntStatus;
}

kiprint( “Ksock:KsockCoreAccept(): EXITing with success…\n” );

//
// return good status
//
return STATUS_SUCCESS;
}

Hi,

I would like to know how to use the TDI interface to accept
an incoming connection, after a TDI_LISTEN irp is issued.

I know that it can also be done by not using TDI_LISTEN,
and accepting the call in the connect event handler.
But I would like to know how to accept connections using the
“listen” method.

I am working on a test driver which iteratively listens to connect
attempts from clients and sends each client the time of the day
after accepting the call.

Thanks in advance.
Regards
Taher

Hi Max,
I got what you are trying to drive at but I have a small query…

>>Note that you must pre-create this file object
>>(or usually many file objects) and put it to some list for
>>ClientEventConnect to pick it from this list while building the
>>TDI_ACCEPT IRP. This is called “listen backlog” and
>>natively implemented in AFD.SYS.

I would like to know how exactly do I specify this “precreated” file object
to the TDI_ACCEPT IRP.
If I specify the precreated connection object directly as a parameter to
TDIBuildAccept, I get an error
STATUS_CONNECTION_INVALID. How do I tell the TDI_ACCEPT IRP that I want to
use a specific connection
object, (which is not the one that I had called TDI_LISTEN on) ?

Thanks in advance,
-Taher

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Maxim S. Shatskih
Sent: Tuesday, April 09, 2002 9:19 AM
To: NT Developers Interest List
Subject: [ntdev] Re: About TDI and connection acceptance.

I know that it can also be done by not using TDI_LISTEN,
and accepting the call in the connect event handler.
But I would like to know how to accept connections using the
“listen” method.

Why?
In ClientEventConnect, allocate the TDI_ACCEPT IRP, do not forget to call
IoSetNextIrpStackLocation on it. Register a completion
routine in it.
Return it to TDI with STATUS_MORE_PROCESSING_REQUIRED.
In the completion routine, the TDI’s file object referenced by this IRP is a
complete connection, you can transfer data on it.

Note that you must pre-create this file object (or usually many file
objects) and put it to some list for ClientEventConnect to pick
it from this list while building the TDI_ACCEPT IRP. This is called “listen
backlog” and natively implemented in AFD.SYS.

Max


You are currently subscribed to ntdev as: xxxxx@veritas.com
To unsubscribe send a blank email to %%email.unsub%%

> If I specify the precreated connection object directly as a parameter to

TDIBuildAccept, I get an error
STATUS_CONNECTION_INVALID.

Preallocate the connection file object early by ZwCreateFile and then “associate address”. Put it to some list.
Then, the ClientEventConnect will take it from the list and pass to TdiBuildAccept.

Max