A user might want to establish a transport connection using exec() on an existing program (such as /usr/bin/cat) to process the data as it arrives over the connection. Existing programs use read() and write(). XTI/TLI does not directly support a read/write interface to a transport provider, but one is available. The interface lets you issue read() and write() 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.
The read/write interface is presented using the client example of "Connection Mode Service" with modifications. The clients are identical until the data transfer phase. Then the client uses the read/write interface and cat to process incoming data. cat is run without change over the transport connection. Only the differences between this client and that of the client in Example 3-3 are shown in Example 3-8.
The client invokes the read/write interface by pushing tirdwr onto the stream associated with the transport endpoint. See I_PUSH in streamio(7I). tirdwr converts XTI/TLI above the transport provider into a pure read/write interface. With the module in place, the client calls close() and dup() to establish the transport endpoint as its standard input file, and uses /usr/bin/cat to process the input.
By pushing tirdwr onto the transport provider, XTI/TLI is changed. The semantics of read() and write() must be used, and message boundaries are not preserved. tirdwr can be popped from the transport provider to restore XTI/TLI semantics (see I_POP in streamio(7I).
The tirdwr module can only be pushed onto a stream when the transport endpoint is in the data transfer phase. After the module is pushed, the user can not call any XTI/TLI routines. If a XTI/TLI routine is invoked, 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 is aborted. See I_POP in streamio(7I).
Send data over the transport connection with write(). 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 (for example, because the remote user aborts the connection using t_snddis()), a hang-up condition is generated on the stream, further write() calls fail, and errno is set to ENXIO. You can still retrieve any available data after a hang-up.
Receive data that arrives at the transport connection with read(). tirdwr which passes data from the transport provider. Any other event or request passed to the user from the provider is processed by tirdwr as follows:
read() cannot identify expedited data to the user. If an expedited data request is received, tirdwr generates a fatal protocol error, EPROTO, on the stream. The error causes further system calls to fail. Do not use read() to receive expedited data.
tirdwr discards an abortive disconnect request and generates a hang-up condition on the stream. Subsequent read() 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 read(), this notifies the user of end of file by returning 0.
If any other XTI/TLI request is received, 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 the connection has been established, no request is generated.
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 an orderly release request was previously received by tirdwr, it is passed 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 a disconnect request was previously received by tirdwr, no special action is taken.
If neither an orderly release nor a disconnect request was previously received by tirdwr, a disconnect request is passed to the transport provider to abort the connection.
If an error previously occurred on the stream and a disconnect request has not been received by tirdwr, a disconnect request is passed to the transport provider.
A process cannot initiate an orderly release after tirdwr is pushed onto a stream. tirdwr handles an orderly release if it is initiated by the user on the other side of a transport connection. If the client in this section is communicating with the server program in "Connection Mode Service", 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 the transport endpoint is closed. When the file descriptor is closed, tirdwr initiates the orderly release request from the client's side of the connection. This generates the request that the server is blocked on.
Some protocols, like TCP, require this orderly release to ensure that the data is delivered intact.