Network Interface Guide

Endpoint Initiation

Before a client and server can connect, each must first open a local connection to the transport provider (the transport endpoint) through t_open(3NSL), and establish its identity (or address) through t_bind(3NSL).

Many protocols perform a subset of the services defined in XTI/TLI. Each transport provider has characteristics that determine the services it provides and limit the services. Data defining the transport characteristics are returned by t_open(3NSL) in a t_info structure. Table 3-6 shows the fields in a t_info structure.

Table 3-6 t_info Structure




Maximum size of a transport address  


Maximum bytes of protocol-specific options that can be passed between the transport user and transport provider  


Maximum message size that can be transmitted in either connection mode or connectionless mode  


Maximum expedited data message size that can be sent over a transport connection  


Maximum number of bytes of user data that can be passed between users during connection establishment  


Maximum bytes of user data that can be passed between users during the abortive release of a connection  


The type of service supported by the transport provider  

The three service types defined by XTI/TLI are:

  1. T_COTS -- The transport provider supports connection mode service but does not provide the orderly release facility. Connection termination is abortive, and any data not already delivered is lost.

  2. T_COTS_ORD -- The transport provider supports connection mode service with the orderly release facility.

  3. T_CLTS -- The transport provider supports connectionless mode service.

Only one such service can be associated with the transport provider identified by t_open(3NSL).

t_open(3NSL) returns the default provider characteristics of a transport endpoint. Some characteristics can change after an endpoint has been opened. This happens with negotiated options (option negotiation is described later in this section). t_getinfo(3NSL) returns the current characteristics of a transport endpoint.

After a user establishes an endpoint with the chosen transport provider, the client and server must establish their identities. t_bind(3NSL) does this by binding a transport address to the transport endpoint. For servers, this routine informs the transport provider that the endpoint is used to listen for incoming connect requests.

t_optmgmt(3NSL) can be used during the local management phase. It lets a user negotiate the values of protocol options with the transport provider. Each transport protocol defines its own set of negotiable protocol options, such as quality-of-service parameters. Because the options are protocol-specific, only applications written for a specific protocol use this function.


The local management requirements of the example client and server are used to discuss details of these facilities. Example 3-3 shows the definitions needed by the client program, followed by its necessary local management steps.

Example 3-3 Client Implementation of Open and Bind

#include <stdio.h>
#include <tiuser.h>
#include <fcntl.h>
#define SRV_ADDR 1 									/* server's address */

   int fd;
   int nbytes;
   int flags = 0;
   char buf[1024];
   struct t_call *sndcall;
   extern int t_errno;

   if ((fd = t_open("/dev/exmp", O_RDWR, (struct t_info *),NULL))
         == -1) {
      t_error("t_open failed");
   if (t_bind(fd, (struct t_bind *) NULL, (struct t_bind *) NULL)
         == -1) {
      t_error("t_bind failed");

The first argument of t_open(3NSL) is the path of a file system object that identifies the transport protocol. /dev/exmp is the example name of a special file that identifies a generic, connection-based transport protocol. The second argument, O_RDWR, specifies to open for both reading and writing. The third argument points to a t_info structure in which to return the service characteristics of the transport.

This data is useful to write protocol-independent software (see "Guidelines to Protocol Independence"). In this example, a NULL pointer is passed. For Example 3-3, the transport provider must have the following characteristics:

If the user needs a service other than T_COTS_ORD, another transport provider can be opened. An example of the T_CLTS service invocation is shown in the section "Read/Write Interface".

t_open(3NSL) returns the transport endpoint file handle that is used by all subsequent XTI/TLI function calls. The identifier is a file descriptor from opening the transport protocol file. See open(2).

The client then calls t_bind(3NSL) to assign an address to the endpoint. The first argument of t_bind(3NSL) is the transport endpoint handle. The second argument points to a t_bind structure that describes the address to bind to the endpoint. The third argument points to a t_bind structure that describes the address that the provider has bound.

The address of a client is rarely important because no other process tries to access it. That is why the second and third arguments to t_bind(3NSL) are NULL. The second NULL argument directs the transport provider to choose an address for the user.

If t_open(3NSL) or t_bind(3NSL) fails, the program calls t_error(3NSL) to display an appropriate error message by stderr. The global integer t_error(3NSL) is assigned an error value. A set of error values is defined in tiuser.h.

t_error(3NSL) is analogous to perror(3C). If the transport function error is a system error, t_errno(3NSL) is set to TSYSERR, and errno is set to the appropriate value.


The server example must also establish a transport endpoint at which to listen for connection requests. Example 3-4 shows the definitions and local management steps.

Example 3-4 Server Implementation of Open and Bind

#include <tiuser.h>
#include <stropts.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>

#define DISCONNECT -1
#define SRV_ADDR 1								/* server's address */
int conn_fd;			/* connection established here */
extern int t_errno;

   int listen_fd;							/* listening transport endpoint */
   struct t_bind *bind;
   struct t_call *call;

   if ((listen_fd = t_open("/dev/exmp", O_RDWR,
      (struct t_info *) NULL)) == -1) {
      t_error("t_open failed for listen_fd");
   if ((bind = (struct t_bind *)t_alloc( listen_fd, T_BIND, T_ALL))
         == (struct t_bind *) NULL) {
      t_error("t_alloc of t_bind structure failed");
   bind->qlen = 1;
    * Because it assumes the format of the provider's address,
    * this program is transport-dependent
    bind->addr.len = sizeof(int);
   *(int *) bind->addr.buf = SRV_ADDR;
   if (t_bind (listen_fd, bind, bind) < 0 ) {
      t_error("t_bind failed for listen_fd");

   #if (!defined(_XOPEN_SOURCE) ||(_XOPEN_SOURCE_EXTENDED -0 != 1))
    * Was the correct address bound? 
    * When using XTI, this test is unnecessary 

   if (bind->addr.len != sizeof(int) ||
      *(int *)bind->addr.buf != SRV_ADDR) {
      fprintf(stderr, "t_bind bound wrong address\n");

Like the client, the server first calls t_open(3NSL) to establish a transport endpoint with the desired transport provider. The endpoint, listen_fd, is used to listen for connect requests.

Next, the server binds its address to the endpoint. This address is used by each client to access the server. The second argument points to a t_bind structure that specifies the address to bind to the endpoint. The t_bind structure has the following format:

struct t_bind {
 	struct netbuf addr;
 	unsigned qlen;

Where addr describes the address to be bound, and qlen specifies the maximum number of outstanding connect requests. All XTI structure and constant definitions made visible for use by applications programs through xti.h. All TLI structure and constant definitions are in tiuser.h.

The address is specified in the netbuf structure with the following format:

struct netbuf {
 	unsigned int maxlen;
 	unsigned int len;
 	char *buf;

Where maxlen specifies the maximum length of the buffer in bytes, len specifies the bytes of data in the buffer, and buf points to the buffer that contains the data.

In the t_bind structure, the data identifies a transport address. qlen specifies the maximum number of connect requests that can be queued. If the value of qlen is positive, the endpoint can be used to listen for connect requests. t_bind(3NSL) directs the transport provider to queue connect requests for the bound address immediately. The server must dequeue each connect request and accept or reject it. For a server that fully processes a single connect request and responds to it before receiving the next request, a value of 1 is appropriate for qlen. Servers that dequeue several connect requests before responding to any should specify a longer queue. The server in this example processes connect requests one at a time, so qlen is set to 1.

t_alloc(3NSL) is called to allocate the t_bind structure. t_alloc(3NSL) has three arguments: a file descriptor of a transport endpoint; the identifier of the structure to allocate; and a flag that specifies which, if any, netbuf buffers to allocate. T_ALL specifies to allocate all netbuf buffers, and causes the addr buffer to be allocated in this example. Buffer size is determined automatically and stored in the maxlen field.

Each transport provider manages its address space differently. Some transport providers allow a single transport address to be bound to several transport endpoints, while others require a unique address per endpoint. XTI and TLI differ in some significant ways in providing the address binding.

In TLI, based on its rules, a provider determines if it can bind the requested address. If not, it chooses another valid address from its address space and binds it to the transport endpoint. The application program must check the bound address to ensure that it is the one previously advertised to clients. In XTI, if the provider determines it cannot bind to the requested address, it fails the t_bind(3NSL) request with an error.

If t_bind(3NSL) succeeds, the provider begins queueing connect requests, entering the next phase of communication.