The X/Open Transport Interface (XTI) is a transport layer application interface that consists of a series of functions designed to be independent of the specific transport provider used. In the Digital UNIX operating system XTI is implemented according to the XPG3 and XPG4 specifications. XPG4 is the default. (XPG3 is provided for backward compatibility and is available by using a compiler switch.) For more information about XPG3 and XPG4, see the X/Open Portability Guide Volume 7: Networking Services. The Digital UNIX implementation of XTI is also thread safe.
Although similar in concept to the Berkeley socket interface, XTI is based on the AT&T Transport Layer Interface (TLI). TLI, in turn, is based on the transport service definition for the Open Systems Interconnection (OSI) model.
Note
Digital UNIX includes the Transport Control Protocol (TCP) and User Datagram Protocol (UDP) transport providers. Although the information provided in this chapter applies to all transport providers that Digital UNIX XTI supports, such as DECnet/OSI, the examples are specific to TCP or UDP. For more specific information using XTI over TCP and UDP, see the
xti_internet
(7) reference page. For examples and information specific to other transport providers, see the documentation that accompanies their software.
This chapter contains the following information:
Figure 3-1 highlights XTI and its relationship to the Digital UNIX implementation of the Internet Protocol suite. It also shows how XTI and the Internet Protocol suite fit into the rest of the network programming environment.
XTI involves the interaction of the following entities:
A transport provider is a transport protocol, such as TCP or UDP, that offers transport layer services.
A transport user is an application program that requires the services of a transport provider to send data to or receive data from another program. A transport user communicates with a transport provider over a communications path identified by a transport endpoint.
A
transport endpoint
is created when an application issues a
t_open
library call. All of the
transport user's requests to the transport provider
pass through the endpoint associated with that provider.
The transport user activates a transport endpoint by binding a transport address to it. Once an endpoint is active, a transport user can send data over it. The transport provider routes the data to the appropriate peer user or other destination.
When using a connection-oriented transport service, such as TCP,
the transport user must establish a connection between itself and a peer
transport user with a
t_connect
function, specifying an active endpoint, before sending data.
In a transport connection, the
transport user initiating the connection is the
active user,
or client, and the peer transport user responding to the connection
request is the
passive user,
or server.
Figure 3-2
summarizes the relationship between transport providers, transport users, and
transport endpoints.
XTI consists of library calls, header files, and the rules and restrictions elaborating how XTI processes work and interact. This section describes the library calls and header files, as well as the regulations that govern the interaction between communicating processes.
Transport users use different service modes and execution modes to determine how data is exchanged with transport providers. The following sections introduce the service modes and execution modes available in XTI.
In XTI, an endpoint can support one of the following modes of service:
A circuit-oriented service that transfers data over an established connection in a reliable, sequenced manner.
Connection-oriented transport is useful for applications that require long, order dependent and reliable, stream-oriented interactions. With connection-oriented transport, transport users and providers can negotiate the parameters and options that govern data transfer. In addition, because a connection provides identification of both parties, the transport user avoids the overhead of transmitting and resolving addresses during data transfer. A connection also provides a context that logically relates successive units of data.
A message-oriented service that transfers data in self-contained units or datagrams, which have no logical sequence with respect to one another.
Connectionless transport is best suited for applications that have the following qualities:
Each data unit is self-contained and has no relationship to previous or successive data units, so the transport provider can route it independently.
Execution modes provide a means for transport users to handle completion of functions and receipt of events. An event is an occurrence or happening that is significant to a transport user. XTI supports two execution modes:
Waits for transport primitives to complete before returning control to the transport user. Also known as blocking mode.
Synchronous mode is suited for applications that want to wait for
functions to complete or maintain only a single transport connection. In
synchronous mode, the transport user cannot perform other tasks while waiting
for a function to complete. For example, if the transport user issues a
t_rcv
function in synchronous mode,
t_rcv
waits until data is received
before returning control to the transport user.
Even while using synchronous mode, it is possible to get some event notification, which the transport user does not ordinarily expect. Such asynchronous events are returned to the user through a special error, TLOOK.
If an asynchronous
event occurs while a function is executing, the function returns the TLOOK
error; the transport user can then issue the
t_look
function to
retrieve the event.
Returns control to the transport user before transport primitives complete. Also known as nonblocking mode.
Asynchronous mode is useful for applications that have long delays between
completion of functions and other tasks to perform in the meantime. This
mode is also useful for applications that handle multiple connections
simultaneously. Many applications handle networking functions in asynchronous
mode because they can perform useful work while waiting for particular
networking functions to complete. For example, if a transport user
issues a
t_rcv
function call
in asynchronous mode, the function returns control to
the user immediately if no data is available. The user periodically polls
for data until the data arrives.
By default, all functions that process incoming events
operate in synchronous mode, blocking until the task completes. To select
asynchronous mode, the transport user specifies the O_NONBLOCK flag with
the
t_open
function when the endpoint is created or before executing
a function or group of functions with the
fcntl
operating system call.
For a full discussion of the specific events supported by XTI, see Section 3.2.3.
XTI functions are implemented as part of the XTI library,
libxti.a
.
TLI functions are implemented in a separate TLI library,
libtli.a
.
There are also shared versions of these libraries,
libxti.so
and
libtli.so
.
Digital UNIX provides shared library support by default when you link an XTI or TLI application with the XTI or TLI library.
For XTI or TLI applications built in the Digital UNIX Version 1.2 environment to use shared library support, you must relink the required object files with the appropriate library. You do not need to recompile source files.
The first of the following examples illustrates how to relink an XTI application's object files with the XTI shared library; the second illustrates how to relink a TLI application's object files with the TLI shared library:
%
cc -o XTI
app
XTI
appmain
.o
XTI
apputil
.o -lxti
%
cc -o TLI
app
TLI
appmain
.o
TLI
apputil
.o -ltli
To link programs statically
with the XTI or TLI libraries (as was the default in Digital UNIX Version 1.2),
use the
non_shared
option to the
cc
command.
The following example illustrates how to link an XTI application's object files to the XTI library statically:
%
cc -non_shared -o XTI
app
XTI
appmain
.o
\
XTI
apputil
.o -lxti
See the
cc
(1)
reference page for more information.
To make a program thread safe, build the program with DECthreads
pthreads
routines. For more information, see
Guide to DECthreads.
The few differences between XTI and TLI are described in Section 3.5.2, which also describes how to link your programs with the correct library at compile time.
XTI and TLI header files contain data definitions, structures, constants, macros, and options used by the XTI and TLI library calls. An application program must include the appropriate header file to make use of structures or other information a particular XTI or TLI library call requires. Table 3-1 lists the XTI and TLI header files.
File Name | Description |
<tiuser.h>
|
Contains data definitions and structures for TLI applications. You must include this file for all TLI applications. |
<xti.h>
|
Contains data definitions and structures for XTI applications. You must include this file for all XTI applications. |
<fcntl.h>
|
Defines flags for modes of execution for the
t_open
function.
You must include this file for all XTI and TLI applications.
|
Note
Typically, header file names are enclosed in angle brackets (< >). To obtain the absolute path to the header file, prepend
/usr/include/
to the information enclosed in the angle brackets. For example, the absolute path for thetiuser.h
file is/usr/include/tiuser.h
.
Some of the calls apply to connection-oriented transport (COTS), some to connectionless transport (CLTS), some to connection-oriented transport when used with the orderly release feature (COTS_ORD), and some to all service modes. A small group of the calls are utility functions and do not apply to a particular service mode. Table 3-2 lists the name, purpose, and service mode of each XTI library call. Each call has an associated reference page by the same name.
Digital UNIX provides
XTI reference pages only; it does not provide TLI reference pages. For
information about TLI and for the TLI reference pages see the
UNIX System V Programmer's Guide: Networking Interfaces,
which is issued
by UNIX System Laboratories, Inc.
Digital UNIX provides reference pages for each of the functions. For
more information, see the
X/Open CAE Specification: Networking Services.
Name of Call | Purpose | Service Mode |
t_accept
|
Accepts a connection request | COTS, COTS_ORD |
t_alloc
|
Allocates memory for a library structure | All |
t_bind
|
Binds an address to a transport endpoint | All |
t_close
|
Closes a transport endpoint | All |
t_connect
|
Establishes a connection with another transport user | COTS, COTS_ORD |
t_error
|
Produces an error message | All |
t_free
|
Frees memory previously allocated for a library structure | All |
t_getinfo
|
Returns protocol-specific information | All |
t_getprotaddr |
Returns the protocol address | All |
t_getstate
|
Returns the current state for the transport endpoint | All |
t_listen
|
Listens for a connection request | COTS, COTS_ORD |
t_look
|
Returns the current event on the transport endpoint | All |
t_open
|
Establishes a transport endpoint | All |
t_optmgmt
|
Retrieves, verifies, or negotiates protocol options | All |
t_rcv
|
Receives data or expedited data over a connection | COTS, COTS_ORD |
t_rcvconnect
|
Receives the confirmation from a connection request | COTS, COTS_ORD |
t_rcvdis
|
Identifies the cause of a disconnect, and retrieves information sent with a disconnect | COTS, COTS_ORD |
t_rcvrel |
Acknowledges receipt of an orderly release indication | COTS_ORD |
t_rcvudata
|
Receives a data unit | CLTS |
t_rcvuderr
|
Receives information about an error associated with a data unit | CLTS |
t_snd
|
Sends data or expedited data over a connection | COTS, COTS_ORD |
t_snddis
|
Initiates a release on an established connection, or rejects a connection request | COTS, COTS_ORD |
t_sndrel |
Initiates an orderly release | COTS_ORD |
t_sndudata
|
Sends a data unit | CLTS |
t_strerror |
Produces an error message string | All |
|
||
t_sync
|
Synchronizes the data structures in the transport library | All |
t_unbind
|
Disables a transport endpoint | All |
Table notes:
XTI supports an orderly release mechanism,
t_sndrel
and
t_rcvrel
functions. (See
Table 3-2
for more information.)
However, if your applications need to be portable to the ISO transport layer,
we recommend that you do not use this mechanism.
Finally, the XTI header file defines the following constants to identify service modes:
These service modes are returned by the transport provider in the
servtype
field of the
info
structure when you create an endpoint
with the
t_open
function.
Each transport provider has a particular state associated with it, as viewed by the transport user. The state of a transport provider and its transition to the next allowable state is governed by outgoing and incoming events, which correspond to the successful return of specified user-level transport functions. Outgoing events correspond to functions that send a request or response to the transport provider, whereas incoming events correspond to functions that retrieve data or event information from the transport provider. This section describes the possible states of the transport provider, the outgoing and incoming events that can occur, and the allowable sequence of function calls.
XTI applications must manage asynchronous events. An asynchronous event is identified by a mnemonic which is defined as a constant in the XTI header file. Table 3-3 lists the name, purpose, and service mode for each type of asynchronous event in XTI.
Event Name | Purpose | Service Mode |
T_CONNECT |
The transport provider received a connection response.
This event usually occurs after the transport user issues the
t_connect
function.
|
COTS,
COTS_ORD |
T_DATA | The transport provider received normal data, which is all or part of a Transport Service Data Unit (TSDU). |
COTS, CLTS,
COTS_ORD |
T_DISCONNECT |
The transport provider received a disconnect request. This event usually
occurs after the transport user issues data transfer functions, the
t_accept
function, or the
t_snddis
function.
|
COTS,
COTS_ORD |
T_EXDATA |
The transport provider received
expedited
data.
|
COTS,
COTS_ORD |
T_GODATA | The flow control restrictions on the flow of normal data are lifted. The transport user can send normal data again. |
COTS, CLTS,
COTS_ORD |
T_GOEXDATA | The flow control restrictions on the flow of expedited data are lifted. The transport user can send expedited data again. |
COTS,
COTS_ORD |
T_LISTEN | The transport provider received a connection request from a remote user. This event occurs only when the file descriptor is bound to a valid address and no transport connection is established. |
COTS,
COTS_ORD |
T_ORDREL | The transport provider received a request for an orderly release. | COTS_ORD |
T_UDERR |
An error was found on a datagram that was previously sent. This event
usually occurs after the transport user issues the
t_rcvudata
or
t_unbind
functions.
|
CLTS |
XTI stores all events that occur at a transport endpoint.
If using a
synchronous mode of execution, the transport user returns from the
function it was executing with a value of -1 and then checks for a value of
TLOOK in
t_errno
and retrieves the event with the
t_look
function. In asynchronous mode, the transport user continues doing
productive work and periodically checks for new events.
Every event at a transport endpoint is consumed
by a specific XTI
function, or it remains outstanding. Exceptions are the T_GODATA
and T_GOEXDATA events, which are cleared by retrieving them with
t_look.
Thus, once the transport user receives a TLOOK error from a function,
subsequent calls to that function or a different function continue to
return the TLOOK error until the transport user consumes the event.
Table 3-4
summarizes the consuming functions for each asynchronous event.
Event | Cleared by t_look | Consuming Function(s) |
T_CONNECT | No |
t_connect ,
t_rcvconnect
|
T_DATA | No |
t_rcv, t_rcvudata
|
T_DISCONNECT | No |
t_rcvdis
|
T_EXDATA | No |
t_rcv
|
T_GODATA | Yes |
t_snd, t_sndudata
|
T_GOEXDATA | Yes |
t_snd
|
T_LISTEN | No |
t_listen
|
T_ORDREL | No |
t_rcvrel
|
T_UDERR | No |
t_rcvuderr
|
Table 3-5 lists the events that cause a specific XTI function to return the TLOOK error. This information may be useful when you structure the event checking mechanisms in your XTI applications.
Function | Events Causing TLOOK |
t_accept
|
T_DISCONNECT, T_LISTEN |
t_connect
|
T_DISCONNECT, T_LISTEN |
t_listen
|
T_DISCONNECT |
t_rcv
|
T_DISCONNECT, T_ORDREL |
t_rcvconnect
|
T_DISCONNECT |
t_rcvrel
|
T_DISCONNECT |
t_rcvudata
|
T_UDERR |
t_snd
|
T_DISCONNECT, T_ORDREL |
t_snddis
|
T_DISCONNECT |
t_sndrel
|
T_DISCONNECT |
t_sndudata
|
T_UDERR |
t_unbind
|
T_LISTEN, T_DATA |
Table notes:
t_connect
is issued for an
endpoint that was bound with a
qlen
> 0, and has a pending connection indication.
Each XTI function manages one transport endpoint at a time. It is not
possible to wait for several events from different sources, particularly
from several transport connections at a time. The Digital UNIX implementation of XTI
allows the transport user
to monitor input and output on a set of file descriptors with the
poll
function. See
poll
(2)
for more information.
XTI uses eight states to manage communication over a transport endpoint. Both the active and passive user have a unique state that reflects the function in process.
Table 3-6 describes the purpose of each XTI state. A service mode of COTS indicates the state occurs regardless of whether or not orderly service is implemented. A service mode of COTS_ORD indicates the state occurs only when orderly service is implemented.
State | Description | Service Mode |
T_UNINIT |
Uninitialized. Initial and final state of the interface.
To establish a transport endpoint,
the user must issue a
t_open .
|
COTS, CLTS, COTS_ORD |
T_UNBIND | Unbound. The user can bind an address to a transport endpoint or close a transport endpoint. | COTS, CLTS, COTS_ORD |
T_IDLE | Idle. The active user can establish a connection with a passive user (COTS), disable a transport endpoint (COTS, CLTS), or send and receive data units (CLTS). The passive user can listen for a connection request (COTS). | COTS, CLTS, COTS_ORD |
T_OUTCON | Outgoing connection pending. The active user can receive confirmations for connection requests. | COTS, COTS_ORD |
T_INCON | Incoming connection pending. The passive user can accept connection requests. | COTS, COTS_ORD |
T_DATAXFER | Data transfer. The active user can send data to and receive data from the passive user. The passive user can send data to and receive data from the active user. | COTS, COTS_ORD |
T_OUTREL | Outgoing orderly release. The user can respond to an orderly release indication. | COTS_ORD |
T_INREL | Incoming orderly release. The user can send an orderly release indication. | COTS_ORD |
If you are writing a connection-oriented application, note that your program can release a connection at any time during the connection-establishment state or data-transfer state.
The XTI library keeps track of outgoing and incoming events to manage the legal states of transport endpoints. The following sections describe these outgoing and incoming events.
Outgoing events are caused by XTI functions that send a request or response to the transport provider. An outgoing event occurs when a function returns successfully. Some functions produce different events, depending on the following values:
ocnt
|
A count of outstanding connection indications (those passed to the transport
user but not yet accepted or rejected). This count is only meaningful for
the current transport endpoint
( fd ).
|
fd
|
The file descriptor of the current transport endpoint. |
resfd
|
The file descriptor of the endpoint where a connection will be accepted. |
Table 3-7 describes the outgoing events available in XTI. A service mode of COTS indicates the event occurs for a connection-oriented service regardless of whether or not orderly service is implemented. A service mode of COTS_ORD indicates the event occurs only when orderly service is implemented.
Event | Description | Service Mode |
opened |
Successful return of
t_open
function.
|
COTS, CLTS, COTS_ORD |
bind |
Successful return of
t_bind
function.
|
COTS, CLTS, COTS_ORD |
optmgmt |
Successful return of
t_optmgmt
function.
|
COTS, CLTS, COTS_ORD |
unbind |
Successful return of
t_unbind
function.
|
COTS, CLTS, COTS_ORD |
closed |
Successful return of
t_close
function.
|
COTS, CLTS, COTS_ORD |
connect1 |
Successful return of
t_connect
function in synchronous execution mode.
|
COTS, COTS_ORD |
connect2 |
The
t_connect
function returned the TNODATA error
in asynchronous mode, or returned the TLOOK error because a disconnect
indication arrived on the transport endpoint.
|
COTS, COTS_ORD |
accept1 |
Successful return of
t_accept
function, where
ocnt
== 1
and
fd
==
resfd .
|
COTS, COTS_ORD |
accept2 |
Successful return of
t_accept
function, where
ocnt
== 1
and
fd
!=
resfd .
|
COTS, COTS_ORD |
accept3 |
Successful return of
t_accept
function, where
ocnt
> 1.
|
COTS |
snd |
Successful return of
t_snd
function.
|
COTS |
snddis1 |
Successful return of
t_snddis
function, where
ocnt
<= 1.
|
COTS, COTS_ORD |
snddis2 |
Successful return of
t_snddis
function, where
ocnt
> 1.
|
COTS, COTS_ORD |
sndrel |
Successful return of
t_sndrel
function.
|
COTS_ORD |
sndudata |
Successful return of
t_sndudata
function.
|
CLTS |
Incoming events are caused by XTI functions that retrieve data or events from
the transport provider. An incoming event occurs when a function returns successfully.
Some functions produce different events, depending on the value of the
ocnt
variable.
This variable is a count of outstanding connection indications (those passed to the transport
user but not yet accepted or rejected). This count is only meaningful for
the current transport endpoint
(fd
).
The pass_conn incoming event is not associated directly with the successful return of a function on a given endpoint. The pass_conn event occurs on the endpoint that is being passed a connection from the current endpoint. No function occurs on the endpoint where the pass_conn event occurs.
Table 3-8 describes the incoming events available in XTI. A service mode of COTS indicates the event occurs regardless of whether or not orderly service is implemented. A service mode of COTS_ORD indicates the event occurs only when orderly service is implemented.
Event | Description | Service Mode |
listen |
Successful return of the
t_listen
function
|
COTS, COTS_ORD |
rcvconnect |
Successful return of the
t_rcvconnect
function
|
COTS, COTS_ORD |
rcv |
Successful return of the
t_rcv
function
|
COTS, COTS_ORD |
rcvdis1 |
Successful return of the
t_rcvdis
function, where
ocnt
== 0
|
COTS, COTS_ORD |
rcvdis2 |
Successful return of the
t_rcvdis
function, where
ocnt
== 1
|
COTS, COTS_ORD |
rcvdis3 |
Successful return of the
t_rcvdis
function, where
ocnt
> 1
|
COTS, COTS_ORD |
rcvrel |
Successful return of the
t_rcvrel
function
|
COTS_ORD |
rcvudata |
Successful return of the
t_rcvudata
function
|
CLTS |
rcvuderr |
Successful return of the
t_rcvuderr
function
|
CLTS |
pass_conn | Successfully received a connection that was passed from another transport endpoint | COTS, COTS_ORD |
This section describes the relationship among XTI functions, outgoing and incoming events, and states. Since XTI has well-defined rules about state transitions, it is possible to know the next allowable state given the current state and most recently received event. This section provides detailed tables that map the current event and state to the next allowable state.
This section excludes the
t_getstate
,
t_getinfo
,
t_alloc
,
t_free
,
t_look
,
t_sync
,
and
t_error
functions from discussions of state transitions. These utility functions
do not affect the state of the transport interface, so they can be issued
from any state except the uninitialized (T_UNINIT) state.
To use Table 3-9, Table 3-10, and Table 3-11, find the row that matches the current incoming or outgoing event and the column that matches the current state. Go to the intersection of the row and column to find the next allowable state. A dash (--) at the intersection indicates an invalid combination of event and state. Some state transitions are marked by a number in parentheses that indicates an action that the transport user must take. The numbers and their meanings are listed at the end of the appropriate table.
Table 3-9 shows the state transitions for initialization and deinitialization functions, functions that are common to both the connection-oriented and connectionless modes of service. For example, if the current event and state are bind and T_UNBND, the next allowable state is T_IDLE. In addition, the transport user must set the count of outstanding connection indications to zero, as indicated by the numeral 1.
Event | T_UNINIT State | T_UNBND State | T_IDLE State |
opened | T_UNBND | -- | -- |
bind | -- |
T_IDLE |
-- |
unbind | -- | -- | T_UNBND |
closed | -- | T_UNINIT | T_UNINIT |
Table notes:
ocnt
,
to 0.
Table 3-10 shows the state transitions for data transfer functions in connectionless transport services.
Event | State T_IDLE |
sndudata | T_IDLE |
rcvudata | T_IDLE |
rcvuderr | T_IDLE |
Table 3-11
and
Table 3-12
show the transitions for connection, release, and data transfer
functions in connection-oriented transport services for incoming and outgoing events.
For example, if the current event and state are
accept2
and T_INCON, the next allowable state is T_IDLE, providing the transport user
decrements the count of outstanding connection indications and passes
a connection to another transport endpoint.
Event | T_IDLE State | T_OUTCON State | T_INCON State | T_DATAXFER State |
connect1 | T_DATAXFER | -- | -- | -- |
connect2 | T_OUTCON | -- | -- | -- |
rcvconnect | -- | T_DATAXFER | -- | -- |
listen |
T_INCON |
-- |
T_INCON |
-- |
accept1 | -- | -- |
T_DATAXFER |
-- |
accept2 | -- | -- |
T_IDLE |
-- |
accept3 | -- | -- |
T_INCON |
-- |
snd | -- | -- | -- | T_DATAXFER |
rcv | -- | -- | -- | T_DATAXFER |
snddis1 | -- | T_IDLE |
T_IDLE |
T_IDLE |
snddis2 | -- | -- |
T_INCON |
-- |
rcvdis1 | -- | T_IDLE | -- | T_IDLE |
rcvdis2 | -- | -- |
T_IDLE |
-- |
rcvdis3 | -- | -- |
T_INCON |
-- |
sndrel | -- | -- | -- | T_OUTREL |
rcvrel | -- | -- | -- | T_INREL |
pass_conn | T_DATAXFER | -- | -- | -- |
optmgmt | T_IDLE | T_OUTCON | T_INCON | T_DATAXFER |
closed | T_UNINIT | T_UNINIT | T_UNINIT | T_UNINIT |
Table notes:
t_accept
function.
Event | T_OUTREL State | T_INREL State | T_UNBND State |
connect1 | -- | -- | -- |
connect2 | -- | -- | -- |
rcvconnect | -- | -- | -- |
listen | -- | -- | -- |
accept1 | -- | -- | -- |
accept2 | -- | -- | -- |
accept3 | -- | -- | -- |
snd | -- | T_INREL | -- |
rcv | T_OUTREL | -- | -- |
snddis1 | T_IDLE | T_IDLE | -- |
snddis2 | -- | -- | -- |
rcvdis1 | T_IDLE | T_IDLE | -- |
rcvdis2 | -- | -- | -- |
rcvdis3 | -- | -- | -- |
sndrel | -- | T_IDLE | -- |
rcvrel | T_IDLE | -- | -- |
pass_conn | -- | -- | T_DATAXFER |
optmgmt | T_OUTREL | T_INREL | T_UNBND |
closed | T_UNINIT | T_UNINIT | -- |
In general, if you use multiple processes, you need to synchronize them carefully to avoid violating the state of the interface.
Although transport providers treat all transport users of a transport endpoint as a single user, the following situations are possible:
For a single process to manage several endpoints in synchronous execution mode, the process must manage the actions on each endpoint serially instead of in parallel. Optionally, you can write a server to manage several endpoints at once. For example, the process can listen for an incoming connection indication on one endpoint and accept the connection on a different endpoint, so as not to block incoming connections. Then, the application can fork a child process to service the requests from the new connection.
Multiple processes that share a single endpoint must coordinate actions to
avoid violating the state of the interface. To do this, each process
calls the
t_sync
function, which retrieves the current state of
the transport provider, before issuing other functions.
If all processes do not cooperate in this manner, another process
or an incoming event can change the state of the interface.
Similarly, while several endpoints can share the same protocol address,
only one can listen for incoming connections. Other endpoints sharing the
protocol address can be in data transfer state or in
the process of establishing
a connection without causing a conflict.
This means that an address can have only one server, but multiple endpoints can call
the address at the same time.
This section presents guidelines to help you sequence functions, manage states, and use XTI options. It then describes the steps required to write both connection-oriented and connectionless programs to XTI.
Figure 3-3 shows the typical sequence of functions and state transitions for an active user and passive user communicating with a connection-oriented transport service in nonblocking mode. The solid lines in the figure show the state transitions for the active user, while the dashed lines show the transitions for the passive user. Each line represents the call of a function, while each ellipse represents the resulting state. This example does not include the orderly release feature.
Figure 3-4 shows the typical sequence of functions and transitions in state for two users communicating with the connectionless transport service. Each line in the figure represents the call of a function, while each ellipse represents the resulting state. Both users are represented by solid lines.
All transport providers take the following actions with respect to states:
The uninitialized state (T_UNINIT) serves two purposes:
t_close
function, the transport provider is closed, and the resources associated with
the transport library are freed for use by another endpoint.
Follow these steps to write a connection-mode application:
To initialize an endpoint, complete the following steps:
Note that the steps described here for initializing an endpoint for connection-oriented service are identical for connectionless service.
Both connection-oriented and connectionless applications must open a transport endpoint using the
t_open
function. The syntax of the
t_open
function is as follows:
fd = t_open
(name,oflag,&info)
;
In the preceding statement:
fd
The
t_open
function returns a file descriptor
upon successful completion. Otherwise,
t_open
returns a value of
-1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
name
/dev/streams/xtiso
directory. If you use a different transport provider, see its
documentation for the correct device name.
Note
Using the special device with any mechanism other than XTI/TLI, for example, direct
open
,read
, orwrite
calls, is illegal and will generate undefined results.
oflag
t_open
.
In other words, the XTI specification forbids the use of O_RDONLY or
O_WRONLY to make the endpoint either read-only or write-only as expected.
info
info
parameter points to the
t_info
structure.
See
t_open
(3)
for more information.
If you are designing a protocol-independent program, you can determine
data buffer sizes by accessing the information that the
t_open
function
returns about the
t_info
structure. If the transport
user exceeds the allowed data size, you receive an error. Alternatively,
you can use the
t_alloc
function to allocate data buffers.
See
t_open
(3)
for more information.
The following is an example of the
t_open
function for the TCP transport provider:
if ( (newfd = t_open( "/dev/streams/xtiso/tcp" , O_RDWR , NULL) ) == -1 ) { (void) t_error("could not open tcp transport"); exit (1); }
Once you open an endpoint, you need to bind a protocol address
to the endpoint. By binding the address, you activate the endpoint.
In connection mode, you also direct the transport provider to begin
accepting connection indications or servicing connection requests on the
transport endpoint. To determine if the transport provider has accepted
a connection indication, you can issue the
t_listen
function. In connectionless mode,
once you bind the address, you can send or receive data units through
the transport endpoint.
To bind an address to an endpoint, issue the
t_bind
function with the following syntax:
t_bind
(fd,req,ret)
;
In the preceding statement:
fd
t_open
function.
req
ret
See
t_bind
(3)
for more information.
If the transport provider supports the automatic generation of addresses, you have the following choices in binding addresses:
req
to a null pointer if you do not wish to specify an address.
The transport provider will assign an address to the transport endpoint.
ret
to a null pointer if you do not need to determine the actual address that was bound
to the endpoint.
req
and
ret
to null pointers
if you want the transport provider to both assign the address and
not notify you of what it was.
req
is not available, the transport provider
will assign an appropriate address.
To determine if the transport provider generates addresses, do not specify
one in the
t_bind
function (set
req
to a null pointer). If the transport
provider supplies addresses, the function returns an assigned address in the
ret
field.
If the transport provider does not supply addresses, the function returns an error of TNOADDR.
If you accept a connection on an endpoint that is used for listening for connection indications, the bound address is busy for the duration of the connection. You cannot bind any other endpoint for listening on that same address while the initial listening endpoint is actively transferring data or in T_IDLE state.
You can use the
gethostbyname
routine, described in
Section 4.2.3.2,
to obtain host information when either TCP or UDP is the
underlying transport provider.
If you use a method to retrieve host information other than the
gethostbyname
routine, consider the following:
sockaddr_in
structure.
The
t_bind
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
XPG3 and XPG4 implement option management differently.
In XPG3, option management is handled exclusively by the
t_optmgmt
function. In XPG4, several functions contain an
opt
argument which is used to convey options between a transport user
and the transport provider.
For more information, see Section 3.6.6.
The connection establishment phase typically consists of the following actions:
These steps are described in the following sections.
The passive user issues the
t_listen
function to look for enqueued connection
indications. If the
t_listen
function finds a connection indication at the head
of the queue, it returns detailed information about the connection
indication and a local sequence number that identifies the indication.
The number of outstanding connection indications that can be queued is limited by
the value of the
qlen
parameter that was accepted by the transport
provider when the
t_bind
function was issued.
By default, the
t_listen
function executes synchronously by waiting for a connection
indication to arrive before returning control to the user. If you set
the O_NONBLOCK flag of the
t_open
function or the
fcntl
function for asynchronous execution,
the
t_listen
function checks for an existing connection indication and
returns an error of TNODATA if none is available.
To listen for connection requests, issue the
t_listen
function with the following syntax:
t_listen
(fd,call)
;
In the preceding statement:
fd
call
See
t_listen
(3)
for more information.
The
t_listen
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
A connection is initiated in either synchronous or asynchronous
mode. In synchronous mode, the active user issues the
t_connect
function, which waits for the passive user's response before returning
control to the active user. In asynchronous mode,
t_connect
initiates
a connection but returns control to the active user before a response to
the connection arrives. Then, the active user can determine the status
of the connection request by issuing the
t_rcvconnect
function. If the passive
user accepted the request, the
t_rcvconnect
function returns successfully and
the connection establishment phase is complete. If a response has not
been received yet, the
t_rcvconnect
function returns an error of TNODATA. The
active user should issue the
t_rcvconnect
function again later.
To initiate a connection, issue the
t_connect
function with the following syntax:
t_connect
(fd,sndcall,rcvcall)
;
In the preceding statement:
fd
sndcall
rcvcall
See
t_connect
(3)
for more information.
The
t_connect
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
When the passive user accepts a connection indication, it can issue the
t_accept
function on the same endpoint (the endpoint where it has
been listening with
t_listen
)
or a different endpoint.
If the passive user accepts on the same endpoint, the endpoint can no longer
receive and enqueue incoming connection indications. The protocol address that
is bound to the endpoint remains busy for the duration it is active.
No other transport endpoints can be bound to the same protocol
address as the listening endpoint. That is, no other endpoints can be bound
until the passive user issues the
t_unbind
function. Further, before
the connection can be accepted on the same endpoint, the passive user must
respond (with either the
t_accept
or
t_snddis
functions) to all
previous connection indications that it has received. Otherwise,
t_accept
returns an error of TBADF.
If the passive user accepts the connection on a different endpoint, the
listening endpoint can still receive and enqueue incoming connection requests.
The different endpoint must already be bound to a protocol address and be in
the T_IDLE state. If the protocol address is the same as for the endpoint
where the indication was received, the
qlen
parameter must be set to
zero (0).
For both types of endpoints,
t_accept
will fail and return an error of TLOOK if
there are connect or disconnect indications waiting to be received.
To accept a connection, issue the
t_accept
function with the following syntax:
t_accept
(fd,resfd,call)
;
In the preceding statement:
fd
resfd
call
See
t_accept
(3)
for more information.
The
t_accept
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
Once a connection is established between two endpoints, the active and passive users can transfer data in full-duplex fashion over the connection. This phase of connection-oriented service is known as the data transfer phase. The following sections describe how to send and receive data during the data transfer phase.
Transport users can send either normal or expedited data over a connection
with the
t_snd
function. Normally,
t_snd
sends successfully
and returns the number of bytes accepted if the transport provider can
immediately accept all the data. If the data cannot be accepted immediately,
the result of
t_snd
depends on whether it is executing synchronously
or asynchronously.
By default, the
t_snd
function executes
synchronously and waits if flow control conditions prevent the transport
provider from accepting the data. The function blocks until one of the following
conditions becomes true:
t_snd
function returns successfully.
t_snd
function returns with
an error of TLOOK. If you call the
t_look
function, it returns the
T_DISCONNECT event. Any data in transit is lost.
t_snd
function returns with an error
of TSYSERR. Any data in transit is lost.
If the O_NONBLOCK flag was set when the endpoint was created,
t_snd
executes asynchronously and fails immediately if flow control restrictions
exist. In some cases, only part of the data was accepted by the transport
provider, so
t_snd
returns a value that is less than the number
of bytes that you requested to be sent. At this point, you can do one
of the following:
t_snd
again with the remaining data.
t_look
function to see if the flow control restrictions are lifted,
then resend the data. The
t_look
function is described at the end of this chapter.
To send data or expedited data over a connection, issue the
t_snd
function with the following syntax:
t_snd
(fd,buf,nbytes,flags)
;
In the preceding statement:
fd
buf
nbytes
flags
T_EXPEDITED
Send the data as expedited data. The expedited data is subject to the interpretations of the transport provider. Some transport providers don't support expedited data.
T_MORE
Indicates that another
t_snd
function will follow with more data for
the current TSDU or ETSDU. The end of the TSDU or ETSDU is indicated by a
t_snd
function without T_MORE set.
Some transport providers do not
support the concept of a TSDU or ETSDU, so the T_MORE flag is not meaningful.
To find out if the transport provider
supports TSDUs and ETSDUs, check the
info
argument of the
t_open
or
t_getinfo
function. If the
tsdu
field of
info
is greater
than zero (0), the transport provider supports a record-oriented mode, and the
return value indicates the maximum size of a TSDU. If the
tsdu
field
is zero, the transport provider supports a stream-oriented mode of sending
data. The T_MORE flag has no bearing on how the data is
packaged for transfer at layers below the transport interface.
See
t_snd
(3)
for more information.
The
t_snd
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
Transport users can receive either normal or expedited data over a connection
with the
t_rcv
function. Typically, if data is available,
t_rcv
returns the data. If the connection has been disconnected,
t_rcv
returns immediately with an error. If data is not available, but the
connection still exists,
t_rcv
behaves differently depending on the
mode of execution:
t_rcv
executes synchronously and waits for one of the
following to arrive:
Instead of issuing
t_rcv
and waiting, you can issue
the
t_look
function and check for the T_DATA or T_EXDATA events.
t_rcv
executes
asynchronously and fails with an error of TNODATA if no data is available.
You should continue to poll for data by issuing the
t_rcv
or
t_look
functions.
To receive data, issue the
t_rcv
function with the following syntax:
t_rcv
(fd,buf,nbytes,flags)
;
In the preceding statement:
fd
buf
nbytes
flags
T_EXPEDITED
Indicates the data received is expedited data.
T_MORE
Indicates that there is more data for the TSDU
or ETSDU that must be received by using additional
t_rcv
functions. The end of the
TSDU or ETSDU is indicated by a
t_rcv
function with the T_MORE flag not set.
Some transport providers do not
support the concept of a TSDU or ETSDU, so the T_MORE flag is not meaningful.
To find out if the transport provider
supports TSDUs and ETSDUs, check the
info
argument of the
t_open
or
t_getinfo
function.
If you retrieve part of a TSDU and expedited data arrives, the receipt of the remainder of the TSDU is suspended until you process the ETSDU. For example, if you received data with T_MORE set and then received data with T_EXPEDITED and T_MORE set, this indicates a situation where expedited data arrived in the middle of your receipt of a TSDU. After you retrieve the full ETSDU, you can retrieve the remainder of the TSDU. It is the responsibility of the application programmer to remember that the receipt of normal data has been interrupted.
See
t_rcv
(3)
for more information.
The
t_rcv
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
XTI supports two ways to release connections: abortive release and orderly release. All transport providers support abortive release. Orderly release is not provided by all transport providers. For example, the OSI transport supports only abortive release, while TCP supports abortive release and optionally, orderly release.
An abortive release, which can be requested by the transport user or the transport provider, aborts a connection immediately. Abortive releases cannot be negotiated, and once the abortive release is requested, there is no guarantee that user data will be delivered.
Transport users can request an abortive release in either the connection establishment or data transfer phases. During connection establishment, a transport user can use the abortive release to reject a connection request. In data transfer phase, either user can release the connection at any time. If a transport provider requests an abortive release, both users are informed that the connection no longer exists.
To request an abortive release or to reject a connection indication, issue
the
t_snddis
function with the following syntax:
t_snddis
(fd,call)
;
In the preceding statement:
fd
call
See
t_snddis
(3)
for more information.
Transport users are notified about abortive
releases through the T_DISCONNECT event. If your program receives
a T_DISCONNECT
event, it must issue the
t_rcvdis
function to retrieve information about the
disconnect and to consume the T_DISCONNECT event.
The following is the syntax of the
t_rcvdis
function:
t_rcvdis
(fd,discon)
;
In the preceding statement:
fd
discon
See
t_rcvdis
(3)
for more information.
Both
t_snddis
and
t_rcvdis
return a value of 0
upon successful completion. Otherwise, they return a value of
-1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
An orderly release allows for release of a connection without loss of
data.
Orderly release is not provided by all transport providers.
If the transport provider returned a service type of T_COTS_ORD with the
t_open
or
t_getinfo
functions, orderly release is supported.
Transport users can request an orderly release during the data transfer
phase. The typical sequence of orderly release is as follows:
t_sndrel
function to request an orderly release of
the connection.
t_rcvrel
function to
indicate the request was received and consume the T_ORDREL event.
t_sndrel
function.
t_rcvrel
function.
To initiate an orderly release, use the
t_sndrel
function which has
the following syntax:
t_sndrel
(fd)
;
In the preceding statement:
fd
The transport user
cannot send more data over the connection
after it issues the
t_sndrel
function. The transport user can, however,
continue to
receive data until it receives an orderly release indication (the T_ORDREL
event).
See
t_sndrel
(3)
for more information.
To acknowledge the receipt of an orderly release indication, issue the
t_rcvrel
function with the following syntax:
t_rcvrel
(fd)
;
In the preceding statement:
fd
After a transport user receives an orderly release indication
(T_ORDREL), it cannot receive more data. (If the user attempts to do so,
the function blocks indefinitely.) The transport user can, however,
continue to send
data until it issues the
t_sndrel
function.
See
t_rcvrel
(3)
for more information.
Both
t_sndrel
and
t_rcvrel
return a value of 0
upon successful completion. Otherwise, they return a value of
-1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
When you are finished using an endpoint, you deinitialize it by
unbinding and closing the endpoint with the
t_unbind
and
t_close
functions.
Note that the steps described here for deinitializing an endpoint with
connection-oriented service are identical to those for connectionless service.
When you unbind the endpoint, you disable the endpoint so that the transport
provider no longer accepts requests for it. The syntax for
t_unbind
is as follows:
t_unbind
(fd)
;
In the preceding statement:
fd
See
t_unbind
(3)
for more information.
By closing the endpoint, you inform the transport provider that you are finished with it and you free any library resources associated with the endpoint.
You should call
t_close
when the endpoint is in the T_UNBND
state. However, this function does not check state information, so it
may be called to close a transport endpoint from any state.
If you close an endpoint that is not in the T_UNBND state, the library resources associated with the endpoint are freed automatically, and the file associated with the endpoint is closed. If there are no other descriptors in this or any other process that references the endpoint, the transport connection is broken.
To close the endpoint, issue the
t_close
function.
The syntax for
t_close
is as follows:
t_close
(fd)
;
In the preceding statement:
fd
See
t_close
(3)
for more information.
Both
t_unbind
and
t_close
return a value of 0
upon successful completion. Otherwise, they return a value of
-1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
This section describes the steps required to write a connectionless mode application:
Initializing an endpoint for connection-oriented and connectionless applications is the same. See Section 3.3.3.1 for information on how to initialize an endpoint for a CLTS application.
The data transfer phase of connectionless service consists of the following:
Note that connectionless service:
The
t_sndudata
function can execute synchronously or asynchronously.
When executing synchronously,
t_sndudata
returns control to the user
when the transport provider can accept another datagram. In some cases,
the function blocks for some time until this occurs. In asynchronous mode,
the transport provider refuses to send a new datagram if flow control
restrictions exist. The
t_sndudata
function returns an error of
TFLOW, and you must either try again later or issue the
t_look
function
to see when the flow control restriction is lifted, which is indicated
by the T_GODATA or T_GOEXDATA events.
If you attempt to send a data unit before you activate the endpoint
with the
t_bind
function, the transport provider discards the data.
To send a data unit, issue the
t_sndudata
function with the following syntax:
t_sndudata
(fd,unitdata)
;
In the preceding statement:
fd
unitdata
t_unitdata
structure.
See
t_sndudata
(3)
for more information.
The
t_sndudata
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
When you call the
t_rcvudata
function and data is available,
t_rcvudata
returns immediately indicating the number of octets received. If data
is not available,
t_rcvudata
behaves differently depending on the
mode of execution, as follows:
The
t_rcvudata
function blocks until either a datagram, error,
or signal is received. As an alternative to waiting for
t_rcvudata
to return, you can issue the
t_look
function periodically for the
T_GODATA event, and then issue
t_rcvudata
to receive the data.
The
t_rcvudata
function returns immediately with an error.
You then must either retry the function periodically or poll for incoming data
with the
t_look
function.
To receive data, issue the
t_rcvudata
function with the following syntax:
t_rcvudata
(fd,unitdata,flags)
;
In the preceding statement:
fd
unitdata
addr
Returns the address of the sender.
opt
Returns any protocol-specific options that apply to the data.
udata
Returns the data received.
flags
See
t_rcvudata
(3)
for more information.
The
t_rcvudata
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
If you issue the
t_look
function and receive the T_UDERR event, previously sent
data has generated an error. To clear the error and consume the T_UDERR
event, you should issue the
t_rcvuderr
function. This function also
returns information about the data that caused the error and the nature
of the error, if you want.
To receive an error indication with information about data, issue the
t_rcvuderr
function with the following syntax:
t_rcvuderr
(fd,uderr)
;
In the preceding statement:
fd
uderr
t_uderr
structure, which identifies the error.
See
t_rcvuderr
(3)
for more information.
The
t_rcvuderr
function returns a value of 0 upon successful completion.
Otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
Deinitializing an endpoint for connection-oriented and connectionless applications is the same. See Section 3.3.3.6 for information on how to deinitialize an endpoint for a connectionless application.
XTI provides a number of functions that can be issued during any phase of connection-oriented or connectionless service (except the uninitialized state) and do not affect the state of the interface. Table 3-13 lists and briefly describes these functions.
Function | Description |
t_getinfo
|
Returns information about the characteristics of the transport provider associated with the endpoint. |
t_getprotaddr |
Returns the protocol address. |
t_getstate
|
Returns the current state of the endpoint. |
t_strerror |
Produces an error message string. |
t_sync
|
Synchronizes the data structures managed by the transport library with information from the transport provider. |
t_alloc
|
Allocates storage for a specified data structure. |
t_free
|
Frees storage for a data structure that was previously allocated by
t_alloc .
|
t_error
|
Prints a message describing the last error returned by an XTI function. (Optional) |
t_look
|
Returns the current event associated with the endpoint. |
Table notes:
The
t_getinfo
and
t_getstate
functions can
be useful for retrieving important information. The
t_getinfo
function
returns the same information about the transport provider as
t_open
.
It offers the advantage that you can call it during any phase of
communication, whereas you can call
t_open
only during the initialization
phase. If a function returns the TOUTSTATE error to indicate that the endpoint
is not in the proper state, you can issue
t_getstate
to retrieve the
current state and take action appropriate for the state.
The
t_sync
function can do the following:
The
t_alloc
and
t_free
functions are
convenient for allocating and freeing memory because you specify the names of
the XTI structures rather than information about their size.
If you use
t_alloc
and
t_free
to manage
the memory for XTI structures,
and the structures change in future releases, you
will not need to change your program.
With
t_error
you can print a user-supplied message (explanation) plus
the contents of
t_errno
to standard output.
Finally,
t_look
is an important function for retrieving the current
outstanding event associated with the endpoint. Typically, if an XTI
function returns TLOOK as an error to indicate a significant asynchronous
event has occurred, the transport user follows by issuing the
t_look
function to retrieve the event. For more information about events,
see
Section 3.2.3.
This section provides the following:
XTI was designed to provide an interface that is independent of the specific transport protocol used. You can write applications that can modify their behavior according to any subset of the XTI functions and facilities supported by each of the underlying transport providers.
Providers do not have to provide all the features of all the XTI functions. Therefore, Application programmers should follow these guidelines when writing XTI applications:
If your application uses features that are not provided by all transport providers, it may not be able to use them with some transport providers or some XTI implementations.
For example, the orderly release facility (the
t_sndrel
and
t_rcvrel
functions) is not supported by all
connection-based transport protocols; in particular it is not
supported by ISO protocols. If your application runs in an
environment with multiple protocols, make sure it does not use the
orderly release facility.
As an alternative to using only the commonly supported features, write your application so that it modifies its behavior according to the subset of XTI functions supported by each transport provider.
Some transport providers, such as TCP, do not support
the concept of a TSDU, so they ignore the T_MORE flag when used with the
t_snd
,
t_sndudata
,
t_rcv
,
and
t_rcvudata
functions.
t_open
and
t_getinfo
functions.
Make sure your application retrieves these limits before transferring data and adheres to the limits throughout the communication process.
Although the
t_optmgmt
function allows an application to access the default
protocol options from the transport provider and pass them as an argument
to the connection-establishment function, make sure your application
avoids examining the options or relying on the existence of certain ones.
t_rcvdis
function or the error
code associated with the
t_rcvuderr
function.
These codes depend on the underlying protocol so, to achieve protocol independence, make sure your application does not attempt to interpret the codes.
t_open
function.
If you perform other operations, the results can vary from system to system.
The following sections explain how to port applications from different transport-level programming interfaces to XTI. Specifically, they discuss how to port from the two most common transport-level programming interfaces: Transport Layer Interface (TLI), which many UNIX System V applications use, and the 4.3BSD socket interface, which many Berkeley UNIX applications use.
The information presented in the following sections presumes that you are experienced at programming with TLI or sockets and that you understand fundamental XTI concepts and syntax.
This section discusses issues to consider before you recompile your TLI programs and explains how to recompile them. As a long-term solution, Digital recommends that you use the XTI interface instead of the TLI interface. As more applications and transport providers use XTI, you might find it advantageous to do so as well.
XTI and TLI support the same functions, states, and modes of service. Note that Digital UNIX provides shared library support by default when you link an XTI or TLI application with the XTI or TLI library. For more information on shared library support, see Section 3.2.2.
Before you recompile your TLI program, you should consider your program's
current implementation of the following event management:
The System V UNIX operating system provides the
poll
function as a tool for managing events. The Digital UNIX implementation of XTI supports the
poll
function, so
if your application uses it, you can recompile. If your program
uses a unique mechanism for managing events, you should
port that mechanism to Digital UNIX or change to the polling mechanism provided
with Digital UNIX.
Because the Digital UNIX implementation of TLI is compatible at the source level with AT&T TLI, you can recompile your TLI program with the Digital UNIX TLI library using the following steps:
#include <tli/tiuser.h>
cc -o
name name.c
-ltli
If you decide to change your TLI application to an XTI application, be aware of the following minor differences between TLI and XTI.
t_error
is a function of type
int
that returns an integer
value (0 for success and -1 for failure), while in TLI, it is a procedure
of type
void
.
t_look
does not support the T_ERROR event (as in TLI);
it returns -1 and the
t_errno
instead.
oflag
parameter of the
t_open
function, the O_NDELAY
value in TLI is known as the O_NONBLOCK value in XTI.
t_open
function,
XTI uses the bitwise inclusive OR of O_RDWR and O_NONBLOCK as the value
of the
oflag
parameter; TLI uses the bitwise inclusive OR of
O_NDELAY and either O_RDONLY, O_WRONLY, or O_RDWR. The O_RDONLY and O_WRONLY
values are not available in XTI; O_RDWR is the only valid value for access
to an endpoint.
t_look
function explicitly before the function or set a signal for the TLOOK event,
which are less convenient. The TBADQLEN error, returned when there are no
queued connection requests, prevents an application from
waiting forever after issuing the
t_listen
function.
See the XTI reference pages for more information on error messages.
To make a TLI application a true XTI application, do the following:
#include <xti.h>
cc -o
name name.c
-lxti
This section explains the differences between the socket interface and XTI. It assumes that your applications use the standard 4.3BSD socket interface and does not account for any extensions or changes you have made to the socket interface. See Appendix B for examples of both sockets and XTI servers and clients.
Because it was designed eventually to replace the socket interface, XTI shares many common functions with the socket interface. However, you should be aware of any differences between it and your current socket interface when rewriting an application for use with XTI.
XTI provides 25 functions. Of the 13 socket functions that map onto corresponding XTI functions, 5 have subtle differences. Table 3-14 lists each XTI function, its corresponding socket function (if one exists), and whether the two functions share common semantics. Generally, socket calls pass parameters by value, while most XTI functions pass pointers to structures containing a combination of input and output parameters.
XTI Function | Socket Function | Shared Semantics |
t_accept
|
accept
|
No |
t_alloc
|
-- | -- |
t_bind
|
bind
|
No |
t_close
|
close
|
Yes |
t_connect
|
connect
|
Yes |
t_error
|
-- | -- |
t_free
|
-- | -- |
t_getinfo
|
-- | -- |
t_getstate
|
-- | -- |
t_listen
|
listen ,
accept
|
Yes |
t_look
|
select
|
No |
t_open
|
socket
|
Yes |
t_optmgmt
|
setsockopt ,
getsockopt
|
No |
t_rcv
|
recv
|
Yes |
t_rcvconnect
|
-- | -- |
t_rcvdis
|
-- | -- |
t_rcvrel
|
-- | -- |
t_rcvudata
|
recvfrom
|
Yes |
t_rcvuderr
|
-- | -- |
t_snd
|
send
|
Yes |
t_snddis
|
shutdown
|
No |
t_sndrel
|
-- | -- |
t_sndudata
|
sendto
|
Yes |
t_sync
|
-- | -- |
t_unbind
|
-- | -- |
Table notes:
t_listen
function specifies the queue length parameter as
well as waiting for the incoming connection. In sockets,
the
listen
function only specifies the queue length parameter.
The XTI functions that do not share all semantics with their socket counterparts have the following differences:
t_accept
t_accept
function takes the user-specified
resfd
argument and establishes a connection with the remote endpoint. In contrast,
the
accept
call from sockets asks the system to select the file
descriptor to which the connection will be established.
Additionally, the
t_accept
function is issued after a connection indication is
received; therefore, it does not block. Conversely, the
accept
call is issued in anticipation of a connect request and therefore
may block until the connect request occurs.
t_bind
t_look
t_look
function returns the current event, which can be one
of nine possible events: T_LISTEN, T_CONNECT, T_DATA, T_EXDATA, T_DISCONNECT,
T_UDERR, T_OREREL, T_GODATA, T_GOEXDATA. The
poll
function can be used
to monitor incoming events on a transport endpoint. The
select
call can be
used to see if a single descriptor is ready for read or write, or if
an exceptional condition is pending.
t_snddis
t_snddis
function initiates an abortive release on an established
connection or rejects a connection request. After an XTI program issues the
t_snddis
functions it can continue to listen for requests with the
t_listen
function or re-establish a connection with the
t_connect
function.
In sockets, once you shut down a connection with the
shutdown
and
close
calls,
the system automatically frees all local resources that are allocated for
this connection. Therefore, in order to continue to listen for connections
or establish a connection, the program needs to reissue the
socket
and
bind
calls.
XTI and sockets both use a series of states to control the appropriate sequence of calls, but each uses a different set of states. XTI states and socket states do not share similar semantics. For example, XTI states are mutually exclusive; socket states are not.
Few error messages are common among sockets and XTI. Table 3-15 lists the socket error messages that have comparable XTI error messages.
Socket Error | XTI Error | Description |
EBADF | TBADF | You specified an invalid file descriptor. |
EOPNOTSUPP | TNOTSUPPORT | You issued a function the underlying transport provider does not support. |
EADDRINUSE | TADDRBUSY | You specified an address that is already in use. |
EACCES | TACCES | You do not have permission to use the specified address. |
Note
XTI and TLI are implemented using STREAMS. You should use the
poll
function instead of theselect
call on any STREAMS file descriptors.
This section provides information on the differences between the XPG3 and XPG4 implementation of XTI.
In earlier versions of Digital UNIX, the XTI implementation conformed to X/Open's XPG3 specification. The current implementation conforms to SPEC1170's XTI (part of Networking Services' specification) as well as X/Open's XPG4 specification for XTI.
There are some changes in the specification of which you, as a programmer, should be aware. This section outlines these differences and the related programming issues.
Note that the implementation of Digital UNIX converges both XPG3 and XPG4 versions of XTI in a single subset. This section also provides details about the usage of the appropriate level of functionality.
In this manual, the terms SPEC1170 or SPEC1170 XTI are used to refer to the implementation of XTI available in this version of Digital UNIX. The terms XPG3 XTI refer to the implementation of XTI that conforms to X/Open's XPG3 specification. Note that the latter can be available in the current versions of Digital UNIX due to binary compatibility or source migration features.
Most of the changes between the two specifications are upwardly compatible, with
the exception of the
t_optmgmt
function.
The following is a quick summary of the basic changes in the XTI from XPG3 to SPEC1170:
The changes to the
t_optmgmt
function are extensive and incompatible with the XPG3 specification.
In general, an application that uses the XPG3 implementation of the
t_optmgmt
function cannot use the
t_optmgmt
function on a system running the XPG4 specification, without
making some modifications to the source.
If you have an application that was developed for XPG3 XTI, you have the following choices to support it under Digital UNIX:
Which option you choose will depend on your situation. The following sections describe these conditions in details.
This choice is appropriate if the sources and features of your application are not going to change. It is useful to provide continued coverage by ensuring that older releases of your products are still functional.
This situation arises from minor changes due to correcting minor
problems. Therefore, there are no changes to the structure or features
or the application. In this case, you might want to compile the sources
in the same manner as XPG3 development environment. In that case,
compile your source code with the
-DXPG3
compiler switch. This ensures that the headers automatically
define the older features for you.
If you need to use the new features supported by SPEC1170 XTI, you will have to make changes in your source code. You cannot combine the features from the XPG3 and SPEC1170 XTI. Therefore, if you have large applications consisting of multiple files, you will need to recompile all files with the new features, rather than just the few you might have changed.
You need to compile your source code with the
-DXOPEN_SOURCE
compiler switch. Additionally, you must ensure that the names of the
transport protocols (as provided through the streams device special files as in
/dev/streams/xtiso/tcp
)
are updated to reflect the naming convention used
in SPEC1170 XTI. For example, the names
for TCP and UDP are
/dev/streams/xtiso/tcp+
and
/dev/streams/xtiso/udp+
.
Check the reference manual
for the names for the other protocols.
Application binaries developed with XPG3 XTI will run on systems running the current version of Digital UNIX. However, there are certain conditions of which you should be aware.
Under unusual circumstances, the errors in XPG3 programs may have been masked due to the way in which the programs or libraries were compiled and linked. It is feasible that the new implementation is able to flag such conditions as errors. Since the error manifested is a programming error in the application, you will have to correct it. The common programming errors that may cause these errors are pointer overruns and uninitialized variables.
Another issue to consider is the availability of SPEC1170 features through STREAMS special files. This is significant if your application accepts command line input for the specifying transport protocol or imports the protocol names from some configuration files. Since the system configured with XTI will have the file names for SPEC1170-compliant protocols as well, it is important to warn users and administrators that those special names should not be used with applications running with binary-compatibility mode. The results of such an action are undefined.
If you are planning to run an old applications without recompiling them, check them for binary compatibility to avoid these problems.
Systems running the current version of Digital UNIX and configured to run XTI support both XPG3 and SPEC1170-compliant functionality. You cannot run the XPG3 and SPEC1170 functionality separately. Therefore, you only need to ensure that XTI subsystem is configured.
You can use the XPG3 and SPEC1170 versions of XTI on the same network. If you are using compatible versions of your application, then the operation should be transparent to users.
It is possible to of convert your application in simple steps, so that you have some pieces that are XPG3 XTI compatible and some pieces that are SPEC1170 compatible. The only thing you have to ensure is that application-level protocol remains the same. Apart from that there will be no issue for interoperability of these components. Therefore, if you have client and server components of an application, you can choose to upgrade the server component for SPEC1170 compliance, while the client component is still operational in binary compatibility mode. Later on, once the server functionality is updated satisfactorily, you can choose to update the client software.
This section provides information on using XTI options in XPG4 and XPG3.
This section provides the following information on using XTI options:
The following functions contain an
opt
argument of the type
struct netbuf
as an input or output parameter. This argument is
used to convey options between the transport user and the transport provider:
t_accept
t_connect
t_listen
t_optmgmt
t_rcvconnect
t_rcvudata
t_rcvuderr
t_sndudata
There is no general definition about the possible contents of options. There are general XTI options and those that are specific for each transport provider. Some options allow you to tailor your communication needs; for instance, by asking for high throughput or low delay. Others allow the fine-tuning of the protocol behavior so that communication with unusual characteristics can be handled more effectively. Other options are for debugging purposes.
All options have default values. Their values have meaning to and are defined by the protocol level in which they apply. However, their values can be negotiated by a transport user. This includes the simple case where the transport user can enforce its use. Often, the transport provider or even the remote transport user can have the right to negotiate a value of lesser quality than the proposed one, that is, a delay can become longer, or a throughput may become lower.
It is useful to differentiate between options that are association-related and those that are not. (Association-related means a pair of communication transport users.) Association-related options are intimately related to the particular transport connection or datagram transmission. If the calling user specifies such an option, some ancillary information is transferred across the network in most cases. The interpretation and further processing of this information is protocol-dependent. For instance, in an ISO connection-oriented communication, the calling user can specify quality-of-service parameters on connection establishment. These are first processed and possibly lowered by the local transport provider, then sent to the remote transport provider that may degrade them again, and finally conveyed to the called user that makes the final selection and transmits the selected values back to the caller.
Options that are not association-related do not contain information
destined for the remote transport user. Some have purely local
relevance; for example, an option that enables debugging. Others
influence the transmission; for instance, the option that sets the IP
time-to-live
field or TCP_NODELAY. (See the
xti_internet
(7)
reference page.) Local options are negotiated solely between the
transport user and the local transport provider. The distinction
between these two categories of options is visible in XTI through the
following relationship: on output, the
t_listen
and
t_rcvudata
functions return association-related options only. The
t_rcvconnect
and
t_rcvuderr
functions may return options of both categories. On input, options
of both categories may be specified with the
t_accept
and
t_sndudata
functions. The
t_connect
and
t_optmgmt
functions can process and return both categories of options.
The transport provider has a default value for each option it supports. These defaults are sufficient for the majority of communication relations. Therefore, a transport user should only request options actually needed to perform the task and leave all others at their default value.
This section describes the general framework for the use of options.
This framework is obligatory for transport providers. The
t_optmgmt
reference page provides information on general XTI options. The
xti_internet
reference page provides information on
the specific options that are legal with the TCP and UDP transport providers.
Options are conveyed through an
opt
argument of
struct netbuf
.
Each option in the buffer specified is of the form
struct t_opthdr
possibly followed by an option value.
A transport provider embodies a stack of protocols. The
level
field of
struct t_opthdr
identifies the XTI level or a protocol of
the transport provider as TCP or ISO 8073:1986. The
name
field identifies the option within the level and the
len
field contains
the total length; that is the length of the option header
t_ophdr
plus the length of the option value. The
status
field is used by
the XTI level or the transport provider to indicate success or failure
of a negotiation.
Several options can be concatenated; however, The transport user has
to ensure that each option starts at a long-word boundary. The macro
OPT_NEXTHDR(pbuf,buflen,poptons)
can be used for that purpose. The parameter
pbuf
denotes a pointer to an option buffer
opt.buf
and
buflen
is its length. The parameter
poption
points to the current options in the option buffer.
OPT_NEXTHDR
returns a pointer to the position of the next option
or returns a null pointer if the option buffer is exhausted. The macro
is helpful for writing and reading the option list.
This section describes the general rules governing the passing and retrieving of options and the error conditions that can occur. Unless explicitly restricted, these rules apply to all functions that allow the exchange of options.
When multiple options are specified in an option buffer on input,
different rules apply to the levels that may be specified, depending on
the function call. Multiple options specified on input to
t_optmgmt
must address the same option level. Options specified on input to
t_connect
,
t_accept
,
and
t_sndudata
can address different levels.
Only legal options can be negotiated; illegal options can cause failure. An option is illegal if the following applies:
t_opthdr.len
parameter exceeds the remaining size of the option buffer
(counted from the beginning of the option).
t_optmgmt
(3)
and
xti_internet
(7)
reference pages.
If and illegal option is passed to XTI, the following will happen:
t_optmgmt
function fails with a TBADOPT error.
t_accept
or
t_connect
functions fail with a TBADOPT
error or the connection establishment aborts, depending on the
implementation and the time the illegal option is detected. If the
connection aborts, a T_DISCONNECT event occurs and a synchronous call to
t_connect
fails with a TLOOK error. It depends on timing and
implementation conditions whether a
t_accept
function can still succeed or fail with a TLOOK error in that case.
t_sndudata
function either fails with a TBADOPT error
or it successfully returns; but a T_UDERR event occurs to indicate that
the datagram was not sent.
If the transport user passes multiple options in one call and one of them
is illegal, the call fails as described previously. It is, however, possible
that some or even all of the submitted legal options were successfully
negotiated. The transport user can check the current status by a call
to the
t_optmgmt
function with the T_CURRENT flag set. See the
t_optmgmt
(3)
and
xti_internet
(7)
reference pages.
Specifying an option level unknown to or not supported by the protocol
selected by the option level does not cause failure. The option is
discarded in calls to the
t_connect
,
t_accept
,
or
t_sndudata
functions. The
t_opmgmt
function returns T_NOTSULPORT in the
level
field of the option.
A transport user initiates an option negotiation when calling the
t_connect
,
t_sndudata
,
or
t_optmgmt
functions with the T_NEGOTIATE flag set.
The negotiation rules for these functions depend on whether an option
request is an absolute requirement. This is explicitly defined for each
option. See the
t_optmgmt
(3)
and
xti_internet
(7)
reference pages. In the case of an ISO transport provider, for example,
the option that requests use of expedited data is not an absolute
requirement. On the other hand, the option that requests protection
could be an absolute requirement.
Note
The term absolute requirement originates from the quality-of-service parameters in the ISO 8072:1986 specification. Its use is extended here to all options.
If the proposed option value is an absolute requirement, there are three possible outcomes:
status
field in
t_opthdr
is set to T_SUCCESS.
t_optmgmt
function successfully returns; but the returned option has its
status
field set to T_FAILURE.
t_connect
function fails with a TLOOK error.
t_sndudata
function fails with a TLOOK error or successfully returns; but a T_UDERR
event occurs to indicate that the datagram was not sent.
If multiple options are submitted in one call and one of them is rejected, XTI behaves as just described. Although the connection establishment or the datagram transmission fails, options successfully negotiated before some option was rejected retain their negotiated values. There is no roll-back mechanism. See the Option Management of a Transport Endpoint section for more information.
The
t_optmgmt
function attempts to negotiate each option. The
status
fields of the returned options indicate success (T_SUCCESS)
or failure (T_FAILURE).
t_optmgmt
function reports T_NOTSULPORT in the
status
field. The
t_connect
and
t_sndudata
functions ignore this option.
If the proposed option value is not an absolute requirement, the following outcomes are possible:
When the result of the negotiation is retrieved, the
status
field in
t_opthdr
is set to T_SUCCESS if the negotiated value equals the
proposed one; otherwise, it is set to T_PARTSUCCESS.
t_optmgmt
reports T_NOTSULPORT in the
status
field. The
t_connect
and
t_sndudata
functions ignore this option.
Unsupported options do not cause functions to fail or a connection to abort, since different vendors possibly implement different subsets of options. Furthermore, future enhancements of XTI might encompass additional options that are unknown to earlier implementations of transport providers. The decision whether or not the missing support of an option is acceptable for the communication is left to the transport user.
The transport provider does not check for multiple occurrences of the same options, possibly with different option values. It simply processes the options in the option buffer sequentially. However, the user should not make any assumption about the order of processing.
Not all options are independent of one another. A requested option value might conflict with the value of another option that was specified in the same call or is currently effective. See the Option Management of a Transport Endpoint section for more information. These conflicts may not be detected at once, but they might later lead to unpredictable results. If detected at negotiation time, these conflicts are resolved within the rules stated above. The outcomes may thus be quite different and depend on whether absolute or nonabsolute requests are involved in the conflict.
Conflicts are usually detected at the time a connection is established or
a datagram is sent. If options are negotiated with the
t_optmgmt
function, conflicts are usually not detected at this time, since
independent processing of the requested options must allow for temporal
inconsistencies.
When called, the
t_connect
,
and
t_sndudata
functions initiate
a negotiation of all association-related options according to the rules
of this section. Options not explicitly specified in the function
calls themselves are taken from an internal option buffer that contains
the values of a previous negotiation. See the
Option Management of a Transport Endpoint section
for more information.
In connection-oriented communication, some protocols give the peer
transport users the opportunity to negotiate characteristics of the
transport connection to be established. These characteristics are
association-related options. With the connect indication, the called
user receives (through the
t_listen
function) a proposal about the
option values that should be effective for this connection. The called
user can accept this proposal or weaken it by choosing values of lower
quality; for example, longer delays than proposed. The called user can,
of course, refuse the connection establishment altogether.
The called user responds to a negotiation proposal using the
t_accept
function. If the called transport user tries to negotiate
an option of higher quality than proposed, the outcome depends on the
protocol to which that option applies. Some protocols may reject the
option, some protocols take other appropriate action described in
protocol-specific reference pages. If an option is rejected, the following
error occurs:
The connection fails; a T_DISCONNECT event occurs. In that case,
whether a
t_accept
function can still succeed or fail with a TLOOK
error depends on timing and implementation conditions.
If multiple options are submitted with the
t_accept
function and
one of them is rejected, the connection fails as described previously.
Options that could be successfully negotiated before the erroneous option
was processed retain their negotiated value. There is no rollback
mechanism. See the
Option Management of a Transport Endpoint section
for more information.
The response options can either be specified with the
t_accept
call or can be preset for the responding endpoint (not the listening
endpoint)
resfd
in a
t_optmgmt
call (action T_NEGOTIATE) prior to the
t_accept
call. (See the
Option Management of a Transport Endpoint section
for more information.)
Note that the response to a negotiation
proposal is activated when the
t_accept
function is called. A
t_optmgmt
function call with erroneous option values as described
previously will succeed; the connection aborts at the time the
t_accept
function is called.
The connection also fails if the selected option values lead to contradictions.
The
t_accept
function does not check for multiple specification of
an option. (See
the Initiating an Option Negotiation section.)
Unsupported options are ignored.
This section describes how a transport user can retrieve information about options.
A transport user must be able to:
To this end, the following function take an output argument
opt
of the
struct netbuf
:
t_connect
t_listen
t_optmgmt
t_rcvconnect
t_rcvudata
t_rcvuderr
The transport user has to supply a buffer to which the options will be
written; the
opt.buf
parameter must point to this buffer and the
opt.maxlen
parameter must contain the buffer's size. The transport
user can set the
opt.maxlen
parameter to zero to indicate that no options are to be retrieved.
Which options are returned depend on the function call involved:
t_connect
in synchronous mode and
t_rcvconnect
The functions return the values of all association-related options that
were received with the connection response and the negotiated values of
those nonassociation-related options that had been specified on input.
However, options specified on input in the
t_connect
call that are not supported or refer to an unknown option level are
discarded and not returned on output.
The
status
field of each option returned with the
t_connect
or
t_rcvconnect
function indicates if the proposed value
(T_SUCCESS) or a degraded value (T_PARTSUCCESS) has been negotiated. The
status
field of received ancillary information (for example,
IP options) that is not subject to negotiation is always set to T_SUCCESS.
t_listen
The received association-related options are related to the incoming
connection (identified by the sequence number), not to the listening
endpoint. (However, the option values currently in effect for the
listening endpoint can affect the values retrieved by the
t_listen
function, since the transport provider might also be involved in the
negotiation process.) Therefore, if the same options are specified
in a call to the
t_optmgmt
function with action T_CURRENT, they will usually not return the same values.
The number of received options may vary for subsequent connect
indications, since many association-related options are only transmitted on
explicit demand by the calling user; for example, IP options or ISO
8072:1986 throughput. It is even possible that no options at all are
returned.
The
status
field is irrelevant.
t_rcvudata
The received association-related options are related to the incoming
datagram, not to the transport endpoint
fd
.
Therefore, if the same options are specified in a call to the
t_optmgmt
function with action T_CURRENT, the
t_optmgmt
function will usually not return the same values.
The number of options received may vary from call to call.
The
status
field is irrelevant.
t_rcvuderr
The returned options are related to the options input of the previous
t_sndudata
call that produced the error. Which options are
returned
and which values they have depend on the specific error
condition. The
status
field is irrelevant.
t_optmgmt
This call can process and return both categories of options. It acts on
options related to the specified transport endpoint, not on options
related to a connect indication or an incoming datagram. For more
information, see the
t_optmgmt
(3)
reference page.
Only privileged users can request privileged options, or option values. The meaning of privilege is hereby implementation-defined.
Read-only options serve for information purposes only. The transport user may be allowed to read the option value but not to change it. For instance, to select the value of a protocol timer or the maximum length of a protocol data unit may be too subtle to leave to the transport user, though the knowledge about this value might be of some interest. An option might be read-only for all users or solely for nonprivileged users. A privileged option might be inaccessible or read-only for nonprivileged users.
An option might be negotiable in some XTI states and read-only in other XTI states. For instance, the ISO quality-of-service options are negotiable in the T_IDLE and T_INCON states, and read-only in all other states (except T_UNINIT).
If a transport user requests negotiation of a read-only option, or a nonprivileged user requests illegal access to a privileged option, the following outcomes are possible:
t_optmgmt
function successfully returns, but the returned
option has its
status
field set to T_NOTSULPORT if a privileged
option was requested illegally, and to T_READONLY if modification of a
read-only option was requested.
t_accept
or
t_connect
functions fail with TACCES or the connection
establishment aborts and a T_DISCONNECT event occurs. If the connection
aborts, a synchronous call to
t_connect
fails with TLOOK. If a
privileged option is illegally requested, the option is quietly ignored.
A nonprivileged user is not able to select an option that is privileged
or unsupported. Timing and implementation conditions determine
whether a
t_accept
call still succeeds or fails with TLOOK.
t_sndudata
function may return TLOOK or successfully return, but a T_UDERR event
occurs to indicate that the datagram was not sent. If a privileged
option is illegally requested, the option is quietly ignored. A
If multiple options are submitted to the
t_connect
,
t_accept
,
or
t_sndudata
functions and a read-only option is rejected, the
connection or the datagram transmission fails as described. Options that
could be successfully negotiated before the erroneous option was processed
retain their negotiated values. There is no rollback mechanism. See the
Option Management of a Transport Endpoint section
for more information.
This section describes how option management works during the lifetime of a transport endpoint.
Each transport endpoint is (logically) associated with an internal option buffer. When a transport endpoint is created, this buffer is filled with a system default value for each supported option. Depending on the option, the default may be OPTION ENABLED, OPTION DISABLED, or denote a time span, and so on. These default settings are appropriate for most uses. Whenever an option value is modified in the course of an option negotiation, the modified value is written to this buffer and overwrites the previous one. At any time, the buffer contains all option values that are currently effective for this transport endpoint.
The current value of an option can be retrieved at any time by calling the
t_optmgmt
function with the T_CURRENT flag set. Calling the
t_optmgmt
function with the T_DEFAULT flag set yields the system
default for the specified option.
A transport user can negotiate new option values by calling the
t_optmgmt
function with the T_NEGOTIATE flag set.
The negotiation follows the rules described in the
Elements of Negotiation section.
Some options may be modified only in specific XTI states and are read-only in other XTI states. Many association-related options, for instance, may not be changed in the T_DATAXFER state, and an attempt to do so fails; see the Privileged and Read-Only Options section. The legal states for each option are specified with its definition.
As usual, association-related options take effect at the time a
connection is established or a datagram is transmitted. This is the
case if they contain information that is transmitted across the network
or determine specific transmission characteristics. If such an option
is modified by a call to the
t_optmgmt
function, the transport
provider checks whether the option is supported and negotiates a value
according to its current knowledge. This value is written to the
internal option buffer.
The final negotiation takes place if the connection is established or the datagram is transmitted. This can result in a degradation of the option value or even in a negotiation failure. The negotiated values are written to the internal option buffer.
Some options can be change in the T_DATAXFER state; for example, those specifying buffer sizes. Such changes might affect the transmission characteristics and lead to unexpected side effects; for example, data loss if a buffer size was shortened.
The transport user can explicitly specify both categories of options on
input when calling the
t_connect
,
t_accept
,
or
t_sndudata
functions. The options are at first locally negotiated
option by option and the resulting values written to the internal option
buffer. The modified option buffer is then used if a further
negotiation step across the network is required; for example, in
connection-oriented ISO communication. The newly negotiated values are
then written to the internal option buffer.
At any stage, a negotiation failure can cause the transmission to abort. If a transmission aborts, the option buffer preserves the content it had at the time the failure occurred. Options that could be negotiated before the error occurred are written back to the option buffer, whether the XTI call fails or succeeds.
It is up to the transport user to decide which option it explicitly
specifies on input when calling the
t_connect
,
t_accept
,
or
t_sndudata
functions. The transport user need not pass options at
all by setting the
len
field of the function's input
opt
argument to zero (0). The current content of the internal option buffer
is then used for negotiation without prior modification.
The negotiation procedure for options at the time of a
t_connect
,
t_accept
,
or
t_sndudata
call always obeys the rules in
the Initiating an Option Negotiation section
whether the options were
explicitly specified during the call or implicitly taken from the
internal option buffer.
The transport user should not make assumptions about the order in which options are processed during negotiation.
A value in the option buffer is only modified as a result of a successful negotiation of this option. It is, in particular, not changed by a connection release. There is no history mechanism that would restore the buffer state existing prior to the connection establishment of the datagram transmission. The transport user must be aware that a connection establishment or a datagram transmission may change the internal option buffer, even if each option was originally initialized to its default value.
Some options may not always have a fully specified value. An ISO transport provider, for instance, that supports several protocol classes might not have a preselected preferred class before a connection establishment is initiated. At the time of the connection request, the transport provider may conclude from the destination address, quality-of-service parameters, and other locally available information which preferred class it should use. A transport user asking for the default value of the preferred class option in the T_IDLE state would get the value T_UNSPEC. This value indicates that the transport provider did not yet select a value. The transport user could negotiate another value as the preferred class; for example, T_CLASS2. The transport provider would then be forced to initiate a connect request with class 2 as the preferred class.
An XTI implementation may also return the T_UNSPEC value if it currently cannot access the option value. This can happen in the T_UNBND state in systems where the protocol stacks reside on separate controller cards and not in the host. The implementation may never return T_UNSPEC if the option is not supported at all.
If T_UNSPEC is a legal value for a specific option, it can be used on input, as well. It is used to indicate that it is left to the provider to choose an appropriate value. This is especially useful in complex options as ISO throughput, where the option value has an internal structure. The transport user can leave some fields unspecified by selecting this value. If the user proposes T_UNSPEC, the transport provider is free to select an appropriate value. This might be the default value, some other explicit value, or T_UNSPEC.
For each option, it is specified whether T_UNSPEC is a legal value for negotiation purposes.
The
t_open
and
t_getinfo
functions return values
representing characteristics of the transport provider in the
info
argument. The value of
info->options
is used by the
t_alloc
function to allocate storage for an option buffer to be used in an XTI
call. The value is sufficient for all uses.
In general,
info->options
also includes the size of privileged
options; even if these are not read-only for nonprivileged users.
Alternatively, an implementation can choose to return different values in
info->options
for privileged and nonprivileged users.
The values in
info->etsdu
,
info->connect
,
and
info->discon
possibly diminish as soon as the T_DATAXFER state is entered. Calling the
t_optmgmt
function does not influence these values. For more information, see the
t_optmgmt
(3)
reference page.
An application programmer who writes XTI programs has the following portability issues across the following:
Options are intrinsically coupled with a definite protocol or protocol profile. Therefore, explicit use of options degrades portability across protocol profiles.
Different vendors might offer transport providers different option
support. This is due to different implementation and product policies.
The lists of options on the
t_optmgmt
(3)
reference page and in the
protocol-specific reference pages are maximal sets, but do not
necessarily reflect common implementation practice. Vendors implement
subsets that suit their needs. Therefore, making careless use of options
endangers portability across different system platforms.
Every implementation of a protocol profile accessible by XTI can be used with the default values of options. Applications can thus be written that do not care about options at all.
An application program that processes options retrieved from an XTI function should discard options it does not know to lessen its dependence from different system platforms and future XTI releases with possibly increased option support.
The Digital UNIX XPG3 implementation of
XTI provides an optional function,
t_optmgmt
,
for retrieving, verifying,
and negotiating protocol options with transport providers.
After you create an endpoint with
t_open
and bind an address to it, you can
verify or negotiate options with the transport provider. To do so, issue
the
t_optmgmt
function, with the following syntax:
t_optmgmt
(fd,req,ret)
;
In the preceding statement:
fd
t_open
function.
req
t_optmgmt
structure that sends protocol options to the
transport provider and requests actions of the transport provider.
ret
t_optmgmt
structure that returns the valid protocol options
and the actions taken by the transport provider.
Both the
req
and
ret
arguments point to a
t_optmgmt
structure.
Note
Although other transport providers may support the
t_optmgmt
function, the Digital UNIX TCP transport provider does not. See the transport provider documentation for information about option management.
See
t_optmgmt
(3)
for more information.
The
t_optmgmt
function returns a value of 0 upon successful completion;
otherwise, it returns a value of -1, and
t_errno
is set to one of the values described in
Section 3.7.
(For multithreaded applications,
t_errno
is thread specific.)
XTI returns library errors and system errors. When an XTI function encounters an error, it returns a value of -1, and can do one of the following:
t_errno
to get the specific error.
(For multithreaded applications,
t_errno
is thread specific.)
t_error
function to print the text of the
message associated with the error stored in
t_errno.
t_getstate
function. Some errors change the state of the endpoint.
Note
Since a successful call to an XTI function does not clear the contents of
t_errno,
checkt_errno
only after an error occurs.
The
<xti.h>
header file defines the
t_errno
variable as a macro as follows:
#define t_errno(*_t_errno())
For more information on errors, see the individual XTI reference pages.
Use the
xtiso
kernel configuration option to configure XTI transport providers.
You can configure the
xtiso
option into your system at installation time
or you can add it to your
system using the
doconfig
command. See the
Installation Guide.
You can use the
doconfig
command
in one of the following ways:
doconfig
command without options if you have not customized
your kernel. Without options the
doconfig
command creates a
new kernel configuration file for your system.
doconfig -c
command if you have customized your
kernel and you do not want to recustomize it. The
doconfig -c
command allows you to add information to the
existing kernel configuration file.
To use the
doconfig
command without any options, do the following:
/usr/sbin/doconfig
command at the superuser prompt (#).
Enter a name for the kernel configuration file. [HOST1]:
[RETURN]
y
when the system asks whether you want to
replace the system configuration file. For example:
A configuration file with the name 'HOST1' already exists.
Do you want to replace it? (y/n) [n]:
y
Saving /sys/conf/HOST1 as /sys/conf/HOST1.bck
*** KERNEL CONFIGURATION AND BUILD PROCEDURE ***
X/Open Transport Interface (XTISO, TIMOD, TIRDWR)
option
from the Kernel Option Selection menu. Confirm your choice
at the prompt.
For example:
*** KERNEL OPTION SELECTION ***
Selection Kernel Option -------------------------------------------------------------- 1 System V Devices 2 NTP V3 Kernel Phase Lock Loop (NTP_TIME) 3 Kernel Breakpoint Debugger (KDEBUG) 4 Packetfilter driver (PACKETFILTER) 5 Point-to-Point Protocol (PPP) 6 STREAMS pckt module (PCKT) 7 X/Open Transport Interface (XTISO, TIMOD, TIRDWR) 8 File on File File System (FFM) 9 ISO 9660 Compact Disc File System (CDFS) 10 Audit Subsystem 11 ACL Subsystem 12 Logical Storage Manager (LSM) 13 Advanced File System (ADVFS) 14 All of the above 15 None of the above 16 Help --------------------------------------------------------------
Enter the selection number for each kernel option you want. For example, 1 3 [15]: 7
Enter the selection number for each kernel option you want.
For example, 1 3 :
7
You selected the following kernel options:
X/Open Transport Interface (XTISO, TIMOD, TIRDWR)
Is that correct? (y/n) [y]:
y
Configuration file complete.
n
when the
doconfig
command asks whether you want to
edit the configuration file.
The
doconfig
command then creates device special files, indicates
where a log of the files it created is located,
and builds the new kernel. After the new kernel is built, you
must move it from the directory where
doconfig
places it to
the root directory (
\/
)
and reboot your system.
When you reboot, the
strsetup -i
command runs automatically, creating the device special files for any new
STREAMS modules.
strsetup -c
command to verify that the device is configured properly.
The following example shows the output from the
strsetup -c
command:
#
/usr/sbin/strsetup -c
STREAMS Configuration Information...Fri Nov 3 14:23:36 1995
Name Type Major Module ID ---- ---- ----- --------- clone 32 0 dlb device 52 5010 kinfo device 53 5020 log device 54 44 nuls device 55 5001 echo device 56 5000 sad device 57 45 pipe device 58 5304 xtisoUDP device 59 5010 xtisoTCP device 60 5010 xtisoUDP+ device 61 5010 xtisoTCP+ device 62 5010 ptm device 63 7609 pts device 6 7608 bba device 64 24880 lat device 5 5 pppif module 6002 pppasync module 6000 pppcomp module 6001 bufcall module 0 null module 5002 pass module 5003 errm module 5003 ptem module 5003 spass module 5007 rspass module 5008 pipemod module 5303 timod module 5006 tirdwr module 0 ldtty module 7701
Configured devices = 15, modules = 14
To use the
doconfig -c
command to add the XTISO option to the
kernel configuration file, do the following:
doconfig -c
HOSTNAME
command from the superuser prompt (#).
HOSTNAME
is the name of your system in all uppercase letters.
For example, for a system called
host1
you would enter:
#
doconfig -c HOST1
y
at the prompt to edit the kernel configuration file.
The
doconfig
command allows you to edit the
configuration file with the
ed
editor. For information about
using the
ed
editor, see
ed
(1).
The following
ed
editing session shows how
to add the XTISO option
to the kernel configuration file for
host1
.
The number of the line after which you append the
new line can differ between kernel configuration files:
*** KERNEL CONFIGURATION AND BUILD PROCEDURE ***
Saving /sys/conf/HOST1 as /sys/conf/HOST1.bck
Do you want to edit the configuration file? (y/n) [n]:
y
Using ed to edit the configuration file. Press return when ready,
or type 'quit' to skip the editing session:
2153
48a
options XTISO
\.
1,$w
2185
q
*** PERFORMING KERNEL BUILD ***
doconfig
places it to
the root directory (
\/)
and reboot your system.
When you reboot, the
strsetup -i
command is run automatically, creating the device special files for any new
STREAMS modules.
strsetup -c
command to verify that the device is configured properly.
The following example shows the output from the
strsetup -c
command:
#
/usr/sbin/strsetup -c
STREAMS Configuration Information...Fri Nov 3 14:23:36 1995
Name Type Major Module ID ---- ---- ----- --------- clone 32 0 dlb device 52 5010 kinfo device 53 5020 log device 54 44 nuls device 55 5001 echo device 56 5000 sad device 57 45 pipe device 58 5304 xtisoUDP device 59 5010 xtisoTCP device 60 5010 xtisoUDP+ device 61 5010 xtisoTCP+ device 62 5010 ptm device 63 7609 pts device 6 7608 bba device 64 24880 lat device 5 5 pppif module 6002 pppasync module 6000 pppcomp module 6001 bufcall module 0 null module 5002 pass module 5003 errm module 5003 ptem module 5003 spass module 5007 rspass module 5008 pipemod module 5303 timod module 5006 tirdwr module 0 ldtty module 7701
Configured devices = 15, modules = 14
For detailed information on reconfiguring your kernel or the
doconfig
command see the
System Administration
manual.