t_bind(3xti_spx)


t_bind -- bind a socket to a given transport endpoint

Synopsis

#include "spx_app.h" 

int t_bind ( int spxFd, struct t_bind *req, struct t_bind *ret )

Parameters

(IN) spxFd
Passes the file descriptor of the local transport endpoint.

(IN) req
Passes a pointer to a t_bind structure. The t_bind structure contains the socket number to bind to. The socket value in the structure is initialized either to a static socket number (an assigned number) or to zero (to obtain a dynamic socket number). The application can set req to NULL to obtain a dynamic socket (qlen is assumed to be zero).

(IN) ret
Passes a pointer to a t_bind structure. The local endpoint address is returned in the structure to which ret is pointing. If the application does not care to which address it was bound, it can set ret to NULL.

(OUT) ret
Returns the local endpoint's address: network address, node address, and socket number.

Return values

0
Successful

-1
Unsuccessful
If t_bind returns an error, t_errno may be set to one of the following.

TBADF
The specified file descriptor does not refer to a transport endpoint.

TOUTSTATE
This transport endpoint is in a state that invalidates a t_bind request.

TBADADDR
Either the address passed down was not the same size of an ipxAddr_t, or the size of the address was not zero (NULL bind pointer).

TNOADDR
There are no unused dynamic socket numbers. The SPX user should try again later.

TACCES
The socket number requested was in use.

TBUFOVFLW
The number of bytes allowed for the return argument is not sufficient to store the value of that argument.

TSYSERR
A system error has occurred during the execution of this function. Check errno for possible further information.

Remarks

The t_bind call associates a protocol address with a given transport endpoint. This call binds the endpoint to an SPX/SPXII socket. This call also directs the transport provider to begin accepting incoming connection requests.

This function works as specified in ``Programming with the X/Open Transport Interface (XTI)'' with the additions explained below.

The t_bind structure has the following format:

   struct t_bind { 
      netbuf     addr; 
      unsigned   qlen; 
   }; 
The qlen field is used to indicate the total number of outstanding connection requests allowed on this endpoint. For additional information, see "Outstanding Connection Requests" on page 181.

The netbuf structure has the following format:

   struct netbuf { 
      unsigned int    maxlen; 
      unsigned int    len; 
      char            *buf; 
   }; 
For a t_bind call, a pointer to an ipxAddr_t structure must be passed in the req.addr.buf field to bind to a static socket. If binding to a dynamic socket, a NULL pointer can be passed.

The ipxAddr_t structure has the following format:

   typedef struct ipxAddress{ 
    uint8    net[4]; 
    uint8    node[6]; 
    uint8    sock[2]; 
   } ipxAddr_t; 
The t_bind call allows an endpoint to bind to a socket number, which can be either dynamic or static. SPX keeps track of which socket number is bound to which transport endpoint. The net and node fields do not need to be filled in the ipxAddr_t structure, but the sock field must be initialized to either a static or dynamic socket value. Static Socket Numbers Services written to run over SPX/SPXII generally have well-known or static socket numbers associated with them. (Again, contact Novell to obtain an assignment for a static socket number for your application.) By having static socket numbers, SPX/SPXII users can be sure that their server and client application types match.

To bind to a static socket number, complete the following steps.

  1. Allocate a t_bind structure for req and ret. They can be the same structure.

  2. Set the socket value in the ipxAddr_t structure before making the t_bind call. The example code uses two #defines to specify the socket number and to ensure that the socket number is passed in hi-lo format.

  3. Initialize the structure's fields. The req.addr.buf field must point to the ipxAddr_t structure allocated in Step 1.

  4. Make the t_bind call by passing the spxFd value returned in the t_open call and by passing the address of the t_bind structure allocated in Step 1.
The SPXII driver looks at the socket field in the ipxAddr_t structure for the SPX user's desired socket number. The socket number must be passed in hi-lo byte order.

If the socket number desired is not currently being used by another IPX/SPX user, the SPXII driver returns the local network address, local node address, and the allocated or requested socket number in the corresponding fields of the ipxAddr_t structure of the ret.addr.buf field.

Only one IPX/SPX endpoint can bind to a given socket number at a time. If the user tries to bind to a socket that has already been bound to, an error results and the bind fails.

Another method to coordinate servers and clients is to use the Service Advertising Protocol (SAP). For programming information, see Chapter 8, "SAP Library," on page 233. Dynamic Socket Number Two methods can be used to have the SPXII driver allocate and assign a dynamic socket number.

Outstanding Connection Requests An outstanding connection request is a connection request that has arrived and has been delivered to the UNIX application, but to which the application has not responded with a connection request acknowledge (t_accept) or connection request reject (t_snddis).

The qlen field in the t_bind structure indicates to SPXII the total number of outstanding connection requests allowed on this transport endpoint.

SPXII allows up to a specified number of outstanding connection requests per transport endpoint. This is currently set to 5. Even if the UNIX application requests more than 5, only 5 are given.

Although you are allowed to have more than one outstanding connection request, we recommend that you have only one.

If a value greater than 1 is specified in the qlen field during a t_bind, a connection request can arrive from a remote transport endpoint, making the t_listen unblock.

If another connection request arrives between the time the t_listen unblocks and the t_accept is issued, the t_accept fails, saying that an event has occurred. You will not be able to t_accept the connection requests until all pending connection requests have been retrieved from the stream head using t_listen. A t_bind with qlen equal to 1 should be issued to avoid this outcome.

Example 1 shows how to bind to a dynamic socket, while Example 2 shows how to bind to a specific or static socket number.

Example 1

    /* Bind to dynamic socket. I don't want know what address I am 
    ** bound to. 
    */ 
   { 
      ... 
      if ((t_bind(spxFd, NULL, NULL)) < 0) { 
         t_error("t_bind failed"); 
         exit(-1); 
      } 
      ... 
   } 

Example 2

   /* This example shows how to bind to the specific socket 0x4500. 
   ** The SPXII driver fills in the net, node fields of the IPX address, 
   ** and returns the full address. 
   */ 
   

/* ** Bind to static socket 0x4500; then print full address after t_bind. */

#define SOCKET_TO_BIND_HIGH 0x45 #define SOCKET_TO_BIND_LOW 0x00 { int spxFd; struct t_bind *bind_req; struct t_bind *bind_ret; ipxAddr_t *ipxAddr; ...

/* ** Allocate structures for t_bind request */

if ((bind_req = (struct t_bind *)t_alloc(spxFd, T_BIND, T_ALL)) == NULL ) { t_error("t_alloc of T_BIND request structure failed"); exit(-1); }

/* ** Allocate structures for t_bind return values */

if ((bind_ret = (struct t_bind *)t_alloc(spxFd, T_BIND, T_ALL)) == NULL ) { t_error( "t_alloc of T_BIND return structure failed"); exit(-1); }

/* ** qlen 0 for clients, 1-5 for servers. qlen is the # of ** outstanding connect indications allowed. */

bind_req->qlen = 0; bind_req->addr.len = sizeof(ipxAddr_t); ipxAddr = (ipxAddr_t *)bind_req->addr.buf; ipxAddr->sock[0] = SOCKET_TO_BIND_HIGH; ipxAddr->sock[1] = SOCKET_TO_BIND_LOW;

if (t_bind(spxFd, bind_req, bind_ret) < 0) { t_error( "t_bind failed"); exit(-1); }

/* ** Print t_bind returned values */

fprintf(stderr,"\nt_bind returned:\n");

/* qlen */ fprintf(stderr,"\t%4d for qlen from %s\n", bind_ret->qlen, spxDev);

/* number of address bytes returned */ fprintf(stderr,"\t%4d bytes of address from %s\n", bind_ret->addr.len, spxDev); ipxAddr = (ipxAddr_t *)bind_ret->addr.buf;

/* network */ fprintf(stderr,"\tBound to address:\n\t net 0x%02X%02X%02X%02X\n", ipxAddr->net[0],ipxAddr->net[1],ipxAddr->net[2],ipxAddr->net[3]);

/* node */ fprintf(stderr,"\t node 0x%02X%02X%02X%02X%02X%02X\n", ipxAddr->node[0],ipxAddr->node[1],ipxAddr->node[2], ipxAddr->node[3],ipxAddr->node[4],ipxAddr->node[5]);

/* socket */ fprintf(stderr,"\t socket 0x%02X%02X\n", ipxAddr->sock[0], ipxAddr->sock[1]);

/* ** free structures used for t_bind */

t_free((char *)bind_req, T_BIND); t_free((char *)bind_ret, T_BIND); ... }

State

After a successful bind, the state is T_IDLE.

After an unsuccessful bind, the state is T_UNBND unless t_error was TOUTSTATE.

References

t_bind(3xti), t_open(3xti_spx), t_optmgmt(3xti_spx), t_unbind(3xti)
30 January 1998
© 1998 The Santa Cruz Operation, Inc. All rights reserved.