TDI_LISTEN

When a kernel-mode client makes a TDI_LISTEN request, it asks the underlying TDI transport driver to listen for an offer to make an endpoint-to-endpoint connection from a remote node.

IRP

The transport calls IoGetCurrentIrpStackLocation with the given Irp to get a pointer to its own I/O stack location in the IRP, shown in the following list as IrpSp. IRP members relevant to this request include the following:

IoStatus.Status
Specifies the final status of the listen request. The transport sets this member before it completes the IRP, possibly to one of the following:

STATUS_SUCCESS
STATUS_PENDING
STATUS_INSUFFICIENT_RESOURCES
STATUS_INVALID_CONNECTION

IrpSp->MajorFunction
Specifies IRP_MJ_INTERNAL_DEVICE_CONTROL. The transport can ignore this member if it exports a TdiDispatchInternalDeviceControl routine that handles only TDI_XXX requests.
IrpSp->MinorFunction
Specifies TDI_LISTEN.
IrpSp->FileObject
Points to an open file object representing the connection endpoint. The transport uses the FsContext and, possibly, FsContext2 fields to access the state it maintains about this connection.

This connection endpoint was previously associated with a local-node address when the client made a successful TDI_ASSOCIATE_ADDRESS request to the transport.

IrpSp->Parameters
Points to a TDI_REQUEST_KERNEL_LISTEN structure, equivalent to the TDI_REQUEST_KERNEL structure.

A client can set the RequestFlags member with TDI_QUERY_ACCEPT, directing the transport to make a delayed-connection acceptance: that is, to complete this listen request to the client when an appropriate connection offer, as specified by RequestConnectionInformation, comes in from the remote node so the client can determine whether to accept the connection by issuing a TDI_ACCEPT request or to reject the remote-node connection offer with a TDI_DISCONNECT request.

Otherwise, when RequestFlags is zero, the underlying transport should accept any appropriate incoming connection offer immediately. If TDI_QUERY_ACCEPT is set but the transport does not support delayed-connection acceptances, the transport fails this listen request.

The client supplies information in the TDI_CONNECTION_INFORMATION-type buffer at RequestConnectionInformation that the transport subsequently uses to determine whether to accept a connection offer from a remote node, as follows:

UserData
Points to a buffer of client-supplied data for the tranport to transmit to the remote node that requests a connection. This member is NULL if the transport supports delayed-connection acceptances and the client set RequestFlags with TDI_QUERY_ACCEPT.
UserDataLength
Specifies the size in bytes of the buffer at UserData, zero if UserData is NULL.
Options
Matches the value set in the RequestFlags member of the TDI_REQUEST_KERNEL_LISTEN structure.
OptionsLength
Should be set to sizeof(ULONG); irrelevant if TDI_QUERY_ACCEPT is not set in RequestFlags.
RemoteAddress
Points to a buffer specifying the remote-node address for which the local-node client listens in anticipation of a connection offer. This specification can be a partial address if the underlying transport defines the conventions and syntax for specifying partial addresses. This member also can be NULL, indicating that the client will accept an endpoint-to-endpoint connection offer from any remote node.
RemoteAddressLength
Specifies the size in bytes of the buffer at RemoteAddress. Zero indicates that a connection offer from any remote node is acceptable to this client.

The client-supplied buffer at ReturnConnectionInformation in the TDI_REQUEST_KERNEL structure is also formatted as a TDI_CONNECTION_INFORMATION structure. The transport returns information about the connection offer from the remote node in this buffer on completion of this listen request.

Comments

Depending on whether TDI_QUERY_ACCEPT is set in the RequestFlags, the transport completes the listen request either by accepting an offered remote-node connection on behalf of its local-node client or by deferring acceptance or rejection of such an offer to that client.

To initiate a listen request successfully, the local-node client must have its transport address already associated with an idle connection endpoint. That is, the transport has previously satisfied a TDI_ASSOCIATE_ADDRESS request for the file object at IrpSp->FileObject that represents the connection. Part of the context that each transport maintains at FsContext or FsContext2 for a connection endpoint is a pointer to the file object that represents the associated address, which the transport sets up when it makes the association.

After issuing a successful TDI_ASSOCIATE_ADDRESS request, a client can then issue any number of TDI_LISTEN requests, which the transport driver should process in FIFO order until the client accepts an offered connection.

The transport can process requests coming in from all its clients in any driver-determined order.

If a client registered its ClientEvent(Chained)Receive and/or ClientEvent(Chained)ReceiveExpedited handler(s) on the address associated with the connection endpoint before making its TDI_LISTEN request, receives can come in for that client as soon as the transport accepts the connection from a remote node, even before the transport has completed the client's listen request. Such a client must be prepared for an endpoint-to-endpoint connection to be established as soon as it makes a listen request, and the tranport must be prepared to indicate receives to that client concurrently with completion of the listen request.

In general, a TDI transport driver cannot call a registered ClientEventConnect handler as long as a listen request is pending on the client's open file object that represents the associated local-node address. However, the driver can call ClientEventConnect when such a listen is pending if the transport determines that the remote-address acceptance criteria supplied at IrpSp->Parameters.RequestConnectionInformation will prevent the listen operation from being completed.

Client-supplied remote-node addressing information acts as a filter that the transport applies before checking the RequestFlags for a pending listen request. When an incoming connection offer comes from a remote-node address that does not match the address specified in the listen IRP, the transport cannot complete the listen for its client. When an incoming connection offer from a remote node satisfies the given address-acceptance criteria, the transport can satisfy the client's listen request in either of the following ways:

TDI drivers vary in how they handle partial addresses. Because the syntax of a transport address is TDI-driver-specific, the mechanism for specifying a partial address is also specific to each transport driver.

In addition to supporting partial-address specifications on listens, TDI transports can support quality-of-service (QOS) specifications by their clients. For example, a transport might allow its clients to specify QOS using a variable-length counted string with TDI-driver-specific syntax and semantics.

TdiBuildListen is the macro a client uses to fill in this IRP.

See Also

ClientEventConnect, ClientEventChainedReceive, ClientEventChainedReceiveExpedited, ClientEventReceive, ClientEventReceiveExpedited, TDI_ACCEPT, TDI_ASSOCIATE_ADDRESS, TdiBuildListen, TDI_CONNECTION_INFORMATION, TDI_DISCONNECT, TdiDispatchInternalDeviceControl, TDI_REQUEST_KERNEL, TDI_SET_EVENT_HANDLER