Network Interface Guide

Server

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;

main()
{
   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");
      exit(1);
   }
   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");
      exit(2);
   }
   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");
      exit(3);
   }

   #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");
      exit(4);
    }
    #endif

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.