Programming With XTI and TLI
This chapter describes the Transport Layer Interface (TLI) and the X/Open Transport Interface (XTI). Advanced topics such as asynchronous execution mode are discussed in "Advanced XTI/TLI Topics".
Some recent additions to XTI, such as scatter/gather data transfer, are discussed in"Additions to the XTI Interface".
The transport layer of the OSI model (layer 4) is the lowest layer of the model that provides applications and higher layers with end-to-end service. This layer hides the topology and characteristics of the underlying network from users. The transport layer also defines a set of services common to many contemporary protocol suites including the OSI protocols, Transmission Control Protocol and TCP/IP Internet Protocol Suite, Xerox Network Systems (XNS), and Systems Network Architecture (SNA).
TLI s modeled on the industry standard Transport Service Definition (ISO 8072). It also can be used to access both TCP and UDP. XTI and TLI are a set of interfaces that constitute a network programming interface. XTI is an evolution from the older TLI interface available on the SunOS 4 platform. The Solaris operating environment supports both interfaces, although XTI represents the future direction of this set of interfaces. The Solaris software implements XTI and TLI as a user library using the STREAMS I/O mechanism.
What Are XTI and TLI?
Note - The interfaces described in this chapter are multithread safe. This means that applications containing XTI/TLI interface calls can be used freely in a multithreaded application. Because these interface calls are not re-entrant, they do not provide linear scalability.
TLI was introduced with AT&T System V, Release 3 in 1986. TLI provided a transport layer interface API. The ISO Transport Service Definition provided the model on which TLI is based. TLI provides an API between the OSI transport and session layers. TLI interfaces evolved further in AT&T System V, Release 4 version of UNIX and were also made available in SunOS 5.6 operating system interfaces.
XTI interfaces are an evolution of TLI interfaces and represent the future direction of this family of interfaces. Compatibility for applications using TLI interfaces is available. You do not need to port TLI applications to XTI immediately. New applications can use the XTI interfaces and you can port older applications to XTI when necessary.
TLI is implemented as a set of interface calls in a library (libnsl) to which the applications link. XTI applications are compiled using the c89 front end and must be linked with the xnet library (libxnet). For additional information on compiling with XTI, see the standards(5) man page.
XTI/TLI code can be independent of current transport providers when used in conjunction with some additional interfaces and mechanisms described in Chapter 4. The SunOS 5 product includes some transport providers (TCP, for example) as part of the base operating system. A transport provider performs services, and the transport user requests the services. The transport user issues service requests to the transport provider. An example is a request to transfer data over a connection TCP and UDP.
XTI/TLI can also be used for transport-independent programming by taking advantage of two components:
Library routines that perform the transport services, in particular, transport selection and name-to-address translation. The network services library includes a set of interfaces that implement XTI/TLI for user processes. See Chapter 8, Transport Selection and Name-to-Address Mapping.
Programs using TLI should be linked with the libnsl network services library by specifying the -l nsl option at compile time.
Programs using XTI should be linked with the xnet library by specifying the -l xnet option at compile time.
State transition rules that define the sequence in which the transport routines can be invoked. For more information on state transition rules, see "State Transitions". The state tables define the legal sequence of library calls based on the state and the handling of events. These events include user-generated library calls, as well as provider-generated event indications. XTI/TLI programmers should understand all state transitions before using the interface.
XTI/TLI Read/Write Interface
A user might want to establish a transport connection using exec(2) on an existing program (such as /usr/bin/cat) to process the data as it arrives over the connection. Existing programs use read(2) and write(2). XTI/TLI does not directly support a read/write interface to a transport provider, but one is available. The interface enables you to issue read(2) and write(2) calls over a transport connection in the data transfer phase. This section describes the read/write interface to the connection mode service of XTI/TLI. This interface is not available with the connectionless mode service.
Example 7-1 Read/Write Interface
The client invokes the read/write interface by pushing tirdwr onto the stream associated with the transport endpoint. See the description of I_PUSH in the streamio(7I) man page. The tirdwr module converts XTI/TLI above the transport provider into a pure read/write interface. With the module in place, the client calls close(2) and dup(2) to establish the transport endpoint as its standard input file, and uses /usr/bin/cat to process the input.
Pushing tirdwr onto the transport provider forces XTI/TLI to use read(2) and write(2) semantics. XTI/TLI does not preserve message boundaries when using read and write semantics. Pop tirdwr from the transport provider to restore XTI/TLI semantics (see the description of I_POP in the streamio(7I) man page.
Caution - Push the tirdwr module onto a stream only when the transport endpoint is in the data transfer phase. After pushing the module, the user cannot call any XTI/TLI routines. If the user invokes an XTI/TLI routine, tirdwr generates a fatal protocol error, EPROTO, on the stream, rendering it unusable. If you then pop the tirdwr module off the stream, the transport connection aborts. See the description of I_POP in the streamio(7I) man page.
After you send data over the transport connection with write(2), tirdwr passes data through to the transport provider. If you send a zero-length data packet, which the mechanism allows, tirdwr discards the message. If the transport connection is aborted, a hang-up condition is generated on the stream, further write(2) calls fail, and errno is set to ENXIO. This problem might occur, for example, because the remote user aborts the connection using t_snddis(3NSL). You can still retrieve any available data after a hang-up.
Receive data that arrives at the transport connection with read(2). tirdwr passes data from the transport provider. The tirdwr module processes any other event or request passed to the user from the provider as follows:
read(2) cannot identify expedited data to the user. If read(2) receives an expedited data request, tirdwr generates a fatal protocol error, EPROTO, on the stream. The error causes further system calls to fail. Do not use read(2) to receive expedited data.
tirdwr discards an abortive disconnect request and generates a hang-up condition on the stream. Subsequent read(2) calls retrieve any remaining data, then return zero for all further calls, indicating end of file.
tirdwr discards an orderly release request and delivers a zero-length message to the user. As described in the read(2) man page, this notifies the user of end of file by returning 0.
If read(2) receives any other XTI/TLI request, tirdwr generates a fatal protocol error, EPROTO, on the stream. This causes further system calls to fail. If a user pushes tirdwr onto a stream after establishing the connection, tirdwr generates no request.
With tirdwr on a stream, you can send and receive data over a transport connection for the duration of the connection. Either user can terminate the connection by closing the file descriptor associated with the transport endpoint or by popping the tirdwr module off the stream. In either case, tirdwr does the following:
If tirdwr receives an orderly release request, it passes the request to the transport provider to complete the orderly release of the connection. The remote user who initiated the orderly release procedure receives the expected request when data transfer completes.
If tirdwr receives a disconnect request, it takes no special action.
If tirdwr receives neither an orderly release nor a disconnect request, it passes a disconnect request to the transport provider to abort the connection.
If an error occurs on the stream and tirdwr does not receive a disconnect request, it passes a disconnect request to the transport provider.
A process cannot initiate an orderly release after pushing tirdwr onto a stream. tirdwr handles an orderly release if the user on the other side of a transport connection initiates the release. If the client in this section is communicating with a server program, the server terminates the transfer of data with an orderly release request. The server then waits for the corresponding request from the client. At that point, the client exits and closes the transport endpoint. After closing the file descriptor, tirdwr initiates the orderly release request from the client's side of the connection. This release generates the request on which the server blocks.
Some protocols, like TCP, require this orderly release to ensure intact delivery of the data.
Advanced XTI/TLI Topics
This section presents additional XTI/TLI concepts: