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.
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:
STATUS_SUCCESS
STATUS_PENDING
STATUS_INSUFFICIENT_RESOURCES
STATUS_INVALID_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.
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:
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.
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.
ClientEventConnect, ClientEventChainedReceive, ClientEventChainedReceiveExpedited, ClientEventReceive, ClientEventReceiveExpedited, TDI_ACCEPT, TDI_ASSOCIATE_ADDRESS, TdiBuildListen, TDI_CONNECTION_INFORMATION, TDI_DISCONNECT, TdiDispatchInternalDeviceControl, TDI_REQUEST_KERNEL, TDI_SET_EVENT_HANDLER