#include"spx_app.h"int t_listen ( int spxFd, struct t_call *rcvcall )
spxFd
rcvcall
rcvcall
spxFd
is an SPXII file descriptor--an SPX2_OPTIONS structure. See "Remarks" for more information.
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.
When a t_connect call has been received from a client, the SPX/SPXII server can either accept or reject the connection request.
{ 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); }