The following TLI routines are used to access SPX:
The following header files must be included in the order listed in any program that uses the TLI interface to SPX:
The t_bind call works as specified in t_bind(NET), with the following additions:
The qlen field of the t_bind structure is used to indicate the total number of outstanding connection requests allowed on this endpoint. Applications that do not service connection requests should set this field to 0. Applications that service connection requests should set this field to 1. See ``Connection requests'' for more information .
The t_bind call allows an endpoint to bind to a socket number. The socket number can be either dynamic or static. SPX keeps track of which socket number is bound to which transport endpoint. The net and node fields do not need to be filled in the ipxAddr_t structure, but the sock field must be initialized to either a static or dynamic socket value. ``Socket numbers'' presents procedures for obtaining both static and dynamic socket numbers.
The t_connect call works as specified in t_connect(NET), with the following additions:
SPX supports both synchronous and asynchronous modes.
On input, sndcall passes a pointer to a t_call structure that contains the IPX address of the server with which the SPX client wants to connect; rcvcall passes a pointer to a t_call structure that contains the server's connection information upon successful completion of the call.
On output, rcvcall receives the server's connection information: network number, node number, socket number, connection ID, and allocation number.
The SPX driver tries a certain number of times (as specified in the spx_tune.h file) to connect with the remote transport endpoint. After trying the specified number of times without receiving an acknowledgment, the SPX driver generates a disconnect indication of TLI_SPX_CONNECTION_FAILED -- see ``t_rcvdis''. If this error occurs, the state of the stream is set to T_IDLE.
See t_connect(NET) for other possible errors.
The SPX driver does not use the udata structure in the t_call structure; its fields should be initialized. You must set the udata.len and udata.maxlen fields to 0 and the udata.buf field to NULL.
The SPX driver does not use the sequence field in the t_call structure.
All information passed in the ipxAddr_t structure must be in high-to-low byte order. See ``Network byte ordering'' for more information.
The sndcall.opt.len and sndcall.opt.maxlen fields must be initialized to the size of an SPX_OPTS or equivalent structure. The sndcall.opt.buf field must point to an SPX_OPTS structure, which is returned by the service provider.
The t_connect call uses two t_call structures: sndcall and rcvcall.
The t_connect call sends an SPX connection request to the SPX address specified in sndcall.addr. The sndcall.addr.len and sndcall.addr.maxlen fields must be initialized to the size of an ipxAddr_t or equivalent structure. The sndcall.addr.buf field must point to an ipxAddr_t structure. The ipxAddr_t structure must be initialized to the server's IPX address.
If the rcvcall structure is passed in t_connect, the server's address and connection information is returned. If a rcvcall structure is passed, maxlen, len, and buf must be set appropriately to receive the ipxAddr_t and SPX_OPTS structures. The server's IPX address is returned in the rcvcall.addr.buf field. The server's connection ID and allocation number is passed back in the rcvcall.opt.buf field.
The state after a successful connection establishment is T_DATAXFER for both the client and server. The state after an unsuccessful connection establishment is T_BND.
The t_listen call works as specified in t_listen(NET), with the following additions:
The udata fields in the t_call structure are not used but must be initialized. Set the udata.len and udata.maxlen fields to 0, and set the udata.buf to NULL. A value is placed in the sequence field when the t_listen receives a connection request. The application uses the sequence value to reject the connection request with a t_snddis call or to accept the connection request with a t_accept.
The addr.len and addr.maxlen fields must be initialized to the size of an ipxAddr_t structure. The addr.buf field must point to an ipxAddr_t structure.
The opt.len and opt.maxlen fields must be initialized to the size of an SPX_OPTS structure. The opt.buf field must point to an SPX_OPTS structure.
If t_listen returns successfully, call.addr points to an ipxAddr_t structure that contains the net, node, and sock of the remote transport endpoint requesting the connection. The net, node, and sock are in high-to-low byte order. The call.opt points to an SPX_OPTS structure that contains the remote transport endpoint's connection ID and allocation number. The call.udata contains nothing.
The t_listen call retrieves any connection requests residing on the stream head. The t_listen call can function synchronously or asynchronously.
SPX ensures that each connection indication is unique by dropping any duplicate connection requests. A duplicate request is a request that comes from the same network, node, socket, and source connection ID as a previous request.
When a t_connect call has been received from a client, the SPX server can either accept or reject the connection request.
The client issuing the connection request learns that the connection request has been rejected by retrying the connection request and eventually timing out. This differs from the DOS/SPX/TLI library in that DOS sends terminate connection indication if the application issues a t_snddis after a t_listen return.
This call can be issued only from the T_BND state.
The t_open call works as specified in t_open(NET), with the following additions:
On input, path passes a pointer to the path of the SPX driver. The path is /dev/nspx.
On output, spxInfo receives the SPX protocol information as a t_info structure. The t_open call returns a value greater than or equal to 0 if successful, or 1 if not. If the t_open call is successful, the value returned is a file descriptor that identifies the local transport endpoint. This document uses the variable fd to refer to this value. If t_open returns an error, errno may be set to:
SPX may be used either synchronously or asynchronously.
The path and name of the clonable SPX device is /dev/nspx.
The t_open call returns a file descriptor and a TLI information structure (of type t_info) upon the successful return of an open call. ``t_info structure fields'' describes the fields in the t_info structure.
t_info structure fields
|addr||12||The address is 12 bytes and consists of: network number (4 bytes), node number (6 bytes), and socket number (2 bytes).|
|options||4||SPX supports 4 bytes of options data.|
|tsdu||-1||There is no limit on the amount of data that can be sent during a connection.|
|servtype||T_COTS||The service type is always T_COTS. SPX is a connection-oriented service with a disorderly release.|
t_open changes the state of the service
connection to T_UNBND (unbound).
The t_optmgmt call works as specified in t_optmgmt(NET), with the following additions:
The t_optmgmt call enables the SPX user to set the maximum number of retries for a connection request or for a data unit delivery.
On input, req passes the address of the t_optmgmt structure that contains the requested retry count value for a connection request or for a data unit delivery; ret passes the address of a t_optmgmt structure that contains the granted retry count value.
On output, ret receives the granted retry count value in the t_optmgmt structure.
On completion, the t_optmgmt call returns 0 if successful or 1 if unsuccessful. If t_optmgmt returns an error, t_errno may be set to one of the following:
This call has one negotiable option. It enables the SPX user to set the maximum number of retries when the SPX driver tries to deliver data reliably to the opposite transport endpoint.
The req.opt.buf field and ret.opt.buf field must point to an SPX_OPTMGMT structure.
The SPX driver does not support spxo_watchdog_flag or spxo_min_retry_delay.
The value in spxo_retry_count becomes the new maximum number of retries unless its value exceeds the maximum retry value in spx_tune.h (the SPX_MAX_TRETRIES parameter).
The flags field in the t_optmgmt
structure must be initialized to the appropriate value.
The flags supported are:
The t_rcv call works as specified in t_rcv(NET), with the following additions:
The T_EXPEDITED flag is never set. On input, flags passes the address of an integer that indicates whether there is more data to receive. SPX does not support the T_EXPEDITED flag.
The SPX watchdog in the SPX driver prevents transport endpoints from blocking forever waiting for a packet. For example, suppose a local transport endpoint blocks waiting for an incoming packet. While the local transport blocks, the remote transport endpoint goes down before sending the packet. In this situation, the local transport endpoint could block forever. The SPX watchdog solves this problem by periodically checking all active connections. If the SPX watchdog determines that the remote transport endpoint is no longer participating in the connection, the SPX watchdog generates a disconnect indication, causing t_rcv to return with an error. (See ``t_rcvdis'' for more information.)
SPX does flow control. If SPX determines that the remote endpoint is sending data faster than the application can receive the data, SPX sends a packet notifying the remote endpoint to stop sending data. When the application receives all of the data queued for it, SPX notifies the remote endpoint to begin sending data again.
t_rcv can be called only if SPX is in the T_DATAXFER state. This state does not change on successful completion of the call.
The t_rcvdis call works as specified in t_rcvdis(NET), with the following additions:
On completion, the t_rcvdis call
returns 0 if successful or 1 if unsuccessful.
If any of the following conditions occur,
a disconnect indication is generated and
passed to the stream head.
The reason integer of the
t_discon structure (described below)
is set accordingly in the following situations:
Alternatively, the SPX driver could not reliably deliver the data or connection request. The remote transport endpoint does not acknowledge transmissions.
Alternatively, SPX has tried a number of times to allocate memory and has failed.
The SPX driver does not use the udata field in the t_discon structure. SPX does not support the transmission of user data with a disconnect request.
Upon receiving a disconnect request, SPX sets the stream to the T_IDLE state.
The t_snd call works as specified in t_snd(NET), with the following additions:
A known problem with TLI is its inability to notify the user within a reasonable amount of time that a call to t_snd has failed. The t_snd call does not check for disconnect indications before and after doing the t_snd. If the remote transport endpoint has gone down or fails to acknowledge the transmitted data, the SPX driver generates a disconnect indication and changes the state of the local transport endpoint to T_IDLE. Following the TLI specification, any t_snd issued in the T_IDLE state is dropped by the SPX driver. This indication is not detected by the application until a routine other than t_snd is called. The application should check the return code in the disconnect indication to make sure it is TLI_SPX_CONNECTION_TERMINATED.
The following errors can occur during the send request:
Alternatively, the size of the data request header or data portion of the message received by SPX was invalid (too small or too large). This transport endpoint is no longer valid and must be closed.
All data is sent on a first-come, first-served basis. The application must take care not to close the connection before all the data is sent. The t_snd call returns before the data has actually been transmitted.
When writing an application that communicates with an unknown machine type, consider the byte order of data sent. See ``Network byte ordering'' for more information.
During the connection, SPX uses the most recent round trip delay multiplied by 1.5 as the timeout for the next transmission.
The T_MORE flag is supported by SPX as follows:
TLI breaks any large send request into a sequence of maximum packets for the given connection.
The SPX driver does not send empty SPX packets. If nbytes is 0, no data or packet is sent.
t_snd can be called only if
SPX is in the T_DATAXFER state.
If errors occur, the state changes to T_IDLE.
The t_snddis call works as specified in t_snddis(NET), with the following additions:
SPX does not support the TLI concept of an orderly release. The correct procedure for aborting or terminating a connection is to use the combination of t_snddis and t_rcvdis.
A t_snddis call sends a connection termination request to the remote transport endpoint. This call is used to abort or break a connection. t_snddis generates an SPX terminate connection request, and releases all outstanding data messages on both the local and remote transport endpoints. The terminate request is not delivered reliably and only one terminate request is sent. After an application calls t_snddis, the application can call t_unbind and t_close without waiting.
SPX does not allow sending address options or user data along with a disconnect request.
The correct procedure for terminating an SPX connection is for both transport endpoints to correlate the moment that the connection is no longer needed, then call t_snddis and t_rcvdis to terminate the connection.
Regardless of the outcome of the call to t_snddis, the transport endpoint remains in the T_UNBND state.
The t_unbind call works as specified in t_unbind(NET), with the following additions:
This call releases the socket number used by the transport endpoint for future use. This allows the callng process to bind to a new socket number.
This call places the transport endpoint
in the T_UNBND state.