t_listen(3xti_spx)


t_listen -- enable an SPX/SPXII application server to receive connection requests from SPX/SPXII clients

Synopsis

#include"spx_app.h" 

int t_listen ( int spxFd, struct t_call *rcvcall )

Parameters

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

(IN) rcvcall
Passes a pointer to a t_call structure. The fields in the structure must be initialized to the proper size of the incoming data. See "Remarks" for information about the fields and the appropriate values for the fields.

(OUT) rcvcall
Receives the address of the remote endpoint, its connection ID, its allocation number, and--if spxFd is an SPXII file descriptor--an SPX2_OPTIONS structure. See "Remarks" for more information.

Return values

0
Successful

-1
Unsuccessful
See t_listen(3xti) and ``Programming with the X/Open Transport Interface (XTI)'' for other possible errors.

Remarks

The t_listen call enables an SPX/SPXII application server to receive connection requests from SPX/SPXII clients. A successful t_listen call returns the client's address, connection ID, and allocation number. The application server sends a response back to the client: either a t_accept to accept the connection or a t_snddis to reject the connection.

This function works as specified in t_listen(3xti) and ``Programming with the X/Open Transport Interface (XTI)'' with the following additions.

The t_call structure has the following format:

   struct t_call { 
      struct netbuf  addr; 
      struct netbuf  opt; 
      struct netbuf  udata; 
      int            sequence; 
   }; 
The t_alloc call will allocate memory for all needed structures. It will initialize the buf pointers and maxlen fields for all netbuf structures. The len field of the netbuf structure must be initialized by the application for buffers sent to SPX/SPXII.

The netbuf structure has the following format:

   struct netbuf { 
      unsigned int    maxlen; 
      unsigned int    len; 
      char            *buf; 
   }; 
Use of t_alloc to allocate structures will help ensure the compatibility of user programs with future releases of SPXII.

On return, the addr.buf field will point to an ipxAddr_t structure with the following format:

   typedef struct ipxAddress{ 
      uint8    net[4]; 
      uint8    node[6]; 
      uint8    sock[2]; 
   } ipxAddr_t; 
A value is placed in the rcvcall.sequence field by SPX/SPXII. If the application wants to accept the connection request, the sequence field must be the same for the t_accept call. If the application wants to reject the connection request it can use the t_snddis call with the same sequence field from the t_listen call.

If t_listen returns successfully, rcvcall.addr points to an ipxAddr_t structure that contains the net, node, and sock of the remote transport endpoint requesting the connection. The net, node, and sock are in hi-lo byte order. The rcvcall->opt.buf points to the option structure (SPX2_OPTIONS or SPX_OPTS) returned by SPX. It will contain information about the connection.

The SPX_OPTS structure has the following format:

   typedef struct spxopt_s { 
      unsigned char  spx_connectionID[2]; 
      unsigned char  spx_allocationNumber[2]; 
   } SPX_OPTS; 
See page 207 for the SPX2_OPTIONS structure format.

Both endpoints must support orderly release before an application can use the orderly release calls. Although older versions of SPX did not support orderly release, the spxIISessionFlags can be used to determine whether both endpoints support orderly release. The spxIISessionFlags in the opt (SPX2_OPTIONS) structure should be saved if the application wants to use orderly release.

For further information, see t_sndrel on page 230 and t_optmgmt on page 205.

The t_listen call retrieves any connection requests residing on the stream head. The t_listen call can function synchronously or asynchronously.

SPX/SPXII ensures that each connection indication is unique by dropping any duplicate connection requests. A duplicate request is a request that comes from the same network, node, socket, and source connection ID as a previous request.

When a t_connect call has been received from a client, the SPX/SPXII server can either accept or reject the connection request.

SPX/SPXII sends a terminate connection indication if the application issues a t_snddis after a t_listen return.

Examples

   { 
      int            spxFd; 
      int            len; 
      uint32         spxIISessionFlags; 
      struct t_call  *rcvcall; 
      SPX2_OPTIONS   *retOpts; 
      ipxAddr_t      *ipxAddr; 
      ... 
      
      if((rcvcall = (struct t_call *)t_alloc(spxFd, T_CALL, T_ALL))==NULL) { 
        t_error( "t_alloc of T_CALL failed"); 
        exit(-1); 
      } 
   

rcvcall->addr.len = rcvcall->addr.maxlen; rcvcall->opt.len = rcvcall->opt.maxlen; rcvcall->udata.len = 0; len = rcvcall->opt.maxlen; /* ** Since this is a synchronous call, the call will block until a ** connection request comes in. When the call returns, the ** rcvcall->addr will contain the remote address. ** The rcvcall->opt.buf will be a pointer to the option structure ** (SPX_OPTS or SPX2_OPTIONS). See t_optmgmt for the structure ** formats. If this call were in asynchronous mode, the t_listen ** call will return fail if no connection requests have arrived, ** or success if one has arrived. */

/* ** Listen for a connect request */ if ((t_listen(spxFd, rcvcall)) < 0) { t_error( "t_listen failed"); if (t_errno == TLOOK) { lookVal = t_look(spxFd); printLookVal(lookVal); } exit(-1); }

ipxAddr = (ipxAddr_t *)rcvcall->addr.buf; fprintf(stderr,"\tConnect Request from:\n\t net 0x%02X%02X%02X%02X\n", ipxAddr->net[0],ipxAddr->net[1], ipxAddr->net[2],ipxAddr->net[3]); 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]); fprintf(stderr,"\t socket 0x%02X%02X\n", ipxAddr->sock[0], ipxAddr->sock[1]);

retOpts = (SPX2_OPTIONS *)rcvcall->opt.buf; /* Save spxII session flags, which are needed for orderly release */ spxIISessionFlags = retOpts->spxIISessionFlags; fprintf(stderr,"Clients Window size:----------- %06d\n", retOpts->spxIIRemoteWindowSize); fprintf(stderr,"Clients connection ID Number:-- %06d\n", GETINT16(retOpts->spxIIConnectionID)); fprintf(stderr,"SPXII Session Flags: ---------- 0x%04X\n", spxIISessionFlags); ... /* Accept this connect request on the same fd, only one connection */ rcvcall->udata.len = 0; rcvcall->opt.len = len;

if ((t_accept(spxFd, spxFd, rcvcall)) < 0) { t_error("t_accept failed"); if (t_errno == TLOOK) { lookVal = t_look(spxFd); printLookVal(lookVal); } exit(-1); } t_free((char *)rcvcall, T_CALL); }

State

When t_listen returns with a connect indication, the state will be T_INCON.

References

t_accept(3xti_spx), t_bind(3xti_spx), t_connect(3xti_spx), t_listen(3xti), t_optmgmt(3xti_spx), t_snddis(3xti_spx), t_sndrel(3xti_spx)
30 January 1998
© 1998 The Santa Cruz Operation, Inc. All rights reserved.