VOID
TdiBuildListen (
IN PIRP Irp,
IN PDEVICE_OBJECT DevObj,
IN PFILE_OBJECT FileObj,
IN PVOID CompRoutine,
IN PVOID Contxt,
IN ULONG Flags,
IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
);
TdiBuildListen sets up an internal device control IRP for a TDI_LISTEN request to the underlying transport in which the local-node client has already associated an address and a connection endpoint.
Parameters
Irp
Points to a client-supplied IRP, either originating in a higher level network component or allocated with TdiBuildInternalDeviceControlIrp.
DevObj
Points to the device object created by the next lower TDI transport driver.
FileObj
Points to a file object representing the connection endpoint. The client previously made a successful request, set up with TdiBuildAssociateAddress, to the transport to set up an association between this connection and a local-node address.
CompRoutine
Specifies the entry point of a client-supplied IoCompletion routine or NULL. The I/O Manager calls this routine when the given IRP is completed, unless the client sets this parameter to NULL.
Contxt
Points to a client-determined context. This client-supplied pointer is passed in to the client's IoCompletion routine when it is called with the completed IRP. Contxt should be NULL if CompRoutine is NULL.
Flags
Specifies zero or, possibly, TDI_QUERY_ACCEPT if the underlying transport supports delayed-connection acceptances.
If Flags is zero, the underlying transport accepts the connection from the remote node as soon as it is offered. The client can assume the endpoint-to-endpoint connection is fully operational when its listen request completes. In fact, receives on the connection endpoint can occur even before this listen IRP is fully completed back to the client.
If the transport supports delayed-connection acceptances and its client sets TDI_QUERY_ACCEPT, that client must either accept or reject the offered connection as quickly as possible when the listen request completes. That is, on completion of this IRP, the client must set up another request to the transport with either TdiBuildAccept or TdiBuildDisconnect, respectively.
RequestConnectionInfo
Points to a client-supplied buffer containing a TDI_CONNECTION_INFORMATION structure that specifies the remote-node client address from which the local-node client expects an endpoint-to-endpoint connection offer.
Depending on the value of Flags, the client also provides additional information in the following members of this structure:
UserData
Points to a buffer of data the client wants sent with an acceptance of the connection from the remote node if Flags is zero.
A client sets this member to NULL if the underlying transport supports delayed-connection acceptances and the client sets Flags to TDI_QUERY_ACCEPT. Such a client can provide accept data when it subsequently accepts an offered connection, assuming it does.
UserDataLength
Specifies the size in bytes of the buffer at UserData. This member is zero if UserData is NULL.
Options
Set to the same value as Flags.
OptionsLength
Set to sizeof(ULONG).
RemoteAddress
Points to a buffer specifying the remote-node client transport address from which the local-node client expects a connection offer that the local-node client will accept. This member can be NULL if an offered connection from any remote node is acceptable to the client.
For some transports, a local-node client can specify a partial address. However, TDI drivers vary in their ability to handle partial addresses. Because the syntax of any transport address is TDI-driver-specific, the underlying transport defines the conventions for specifying a partial address if it supports partial-address specifications.
RemoteAddressLength
Specifies the size in bytes of the buffer at RemoteAddress. This member should be set to zero if RemoteAddress is NULL.
ReturnConnectionInfo
Points to a caller–supplied buffer in which the transport returns the remote-node address from which a connection offer was made. This buffer is also formatted as TDI_CONNECTION_INFORMATION structure.
If the local-node client set Flags to TDI_QUERY_ACCEPT, it examines the returned information to determine whether to accept or reject the connection when this listen request completes.
If the client requires no output information or if the underlying transport does not return such information, this parameter should be NULL.
Comments
TdiBuildListen sets IRP_MJ_INTERNAL_DEVICE_CONTROL as the MajorFunction and TDI_LISTEN as the MinorFunction codes in the transport's I/O stack location of the given IRP.
Before it calls the underlying transport with the IRP set up by TdiBuildListen, a client must make a preceding associate-address request, set up with TdiBuildAssociateAddress, that succeeded in associating an idle connection endpoint with a local-node address. After this association is established, a client can issue numerous listen requests until it accepts an offered endpoint-to-endpoint connection.
The underlying transport usually processes each client's listen requests in FIFO order unless it supports quality-of-service (QOS) for its clients and, therefore, prioritizes incoming listen requests. However, a client cannot make assumptions about the order in which the underlying transport processes requests from all its current clients.
Client-supplied addressing information at RequestConnectionInfo acts as a filter that the underlying transport driver applies, before checking whether the client set TDI_QUERY_ACCEPT if the transport supports delayed-connection acceptances. If an incoming connection offer does not match an address specified in the client's listen request, the transport cannot complete the listen request for the client. Otherwise, when an incoming connection offer is made from a specified remote-node address, the local-node client's listen request is completed in one of the following ways:
·If the client set Flags to TDI_QUERY_ACCEPT indicating delayed-connection acceptance, the transport completes the listen request, and the client must either accept or reject the offered endpoint-to-endpoint connection by issuing a TDI_ACCEPT or TDI_DISCONNECT request to the transport immediately.
·If the client set Flags to zero, possibly because the underlying transport does not support delayed-connection acceptances, the transport transmits an acceptance, along with any accept data the client supplied, to the remote node and completes the listen request.
Before making a listen request, a client can set up one or more IRPs with TdiBuildSetEventHandler and register its ClientEvent(Chained)Receive(Expedited) handler(s) for the local address associated with the connection endpoint. If it does this, the ClientEvent(Chained)Receive(Expedited) routine(s) can receive TSDUs before the client's listen request completes. Such a client must be prepared to accept an immediate connection when it makes a listen request.
While a listen for a client's connection endpoint is pending on a particular local-node address, that client's ClientEventConnect function cannot be called except under special circumstances. That is, the underlying transport can call ClientEventConnect if a listen operation is pending and the transport determines that the remote address acceptance criteria would prevent the listen operation from being completed.
As mentioned previously, some transports support the specification of remote-node partial addresses on listens. A transport also might support the specification of QOS options. For example, such a TDI transport's clients might specify the QOS for a listen using a variable-length counted string with transport-defined syntax and semantics.
See Also
ClientEventChainedReceive, ClientEventChainedReceiveExpedited, ClientEventConnect, ClientEventReceive, ClientEventReceiveExpedited, TdiBuildAccept, TdiBuildDisconnect, TdiBuildInternalDeviceControlIrp, TdiBuildSetEventHandler, TDI_LISTEN, TDI_CONNECTION_INFORMATION