XTI socket server sample program

As with all TCP/IP applications, dynamic dataset allocations are used unless explicitly overridden. For example, the TCPIP.DATA file can be specified using the SYSTCPD DD JCL statement. For more information, see C Socket application programming interface.

The following example shows an XTI socket server program.

/*** IBMCOPYR ********************************************************/
/*                                                                   */
/* Component Name: XTISC.C (alias EZAEC0YM)                          */
/*                                                                   */
/* Copyright:    Licensed Materials - Property of IBM                */
/*                                                                   */
/*               "Restricted Materials of IBM"                       */
/*                                                                   */
/*               5647-A01                                            */
/*                                                                   */
/*               (C) Copyright IBM Corp. 1977, 1998                  */
/*                                                                   */
/*               US Government Users Restricted Rights -             */
/*               Use, duplication or disclosure restricted by        */
/*               GSA ADP Schedule Contract with IBM Corp.            */
/*                                                                   */
/* Status:       CSV2R6                                              */
/*                                                                   */
/*                                                                   */
/*   SMP/E Distribution Name: EZAEC0YM                               */
/*                                                                   */
/*                                                                   */
/*** IBMCOPYR ********************************************************/

static char ibmcopyr[]=
   "XTISC    - Licensed Materials - Property of IBM. "
   "This module is \"Restricted Materials of IBM\" "
   "5647-A01 (C) Copyright IBM Corp. 1994. "
   "See IBM Copyright Instructions.";

/*********************************************************************/
/* XTIS Sample : Server                                              */
/*                                                                   */
/* Function:                                                         */
/*                                                                   */
/*  1. Establishes an XTI endpoint  (Asynchronous mode)              */
/*  2. Listens for a connection request from an XTI client           */
/*  3. Accepts the connection request                                */
/*  4. Receives a block of data from the client                      */
/*  5. Echos the data back to the client                             */
/*  6. Waits for the disconnect request from the XTI client          */
/*  7. Server stops                                                  */
/*                                                                   */
/* Command line:                                                     */
/*                                                                   */
/*  XTIS     H                                                       */
/*                                                                   */
/*********************************************************************/

#include "xti.h"
#include "xti1006.h"
#include "stdio.h"

/*
*  bind request structure for t_bind()
*/

struct t_bind req,ret;

/*
*  for server to listen for calls with
*/

struct t_call call;

/*
*  descriptor to t_listen() on
*/

int fd;

/*
*  descriptor to t_accept() on
*/

int resfd;

int tot_received;

/*
*  data buffer
*/

char buf[25];

int looking;

/*
*  flags returned from t_rcv()
*/

int rflags,sflags;

/*
*  transport provider for t_open()
*/

char tprov[1][8] =
     { "RFC1006" } ;

/*
*  args that are optional
*/

int args;

int tot_sent;
int pnum = 102;
char *port = "102";
char *hostnm;
char *stsel = "server";
unsigned int rqlen = 0;
struct xti1006tsap tsap, tsapret;
void cleanup(int);
void form_addr_1006(struct xti1006tsap *,int, char *, char*, int, int);

/*
*  MAIN line program starts here !!!
*/

main(argc,argv)
int argc;
char *argv[];
{

  /*
  *  Check arguments. No arguments should be passed to the server
  */

  if (argc > 2) {
    fprintf(stderr,"Usage : XTIS <port>\n");
    exit(1);
  }

  if(argc == 2)
  {
    pnum = (unsigned short) atoi(argv[1]);
    port = argv[1];
  }
  /*
  *  assume normal data
  */

  sflags = 0;

  /*
  *  establish endpoint to t_listen() on
  */

  if ((fd = t_open(tprov[0],O_NONBLOCK,NULL)) < 0)
  {
    t_error("Error on t_open");
    exit(t_errno);
  }

  /*
  *  establish endpoint to t_accept() on
  */

  if ((resfd = t_open(tprov[0],O_NONBLOCK,NULL)) < 0)
  {
    t_error("Error on t_open");
    cleanup(fd);
    exit(t_errno);
  }

  /*
  *  compose req structure for t_bind() calls
  */

  /*
  *  length of tsap
  */

  req.addr.len = sizeof(tsap);

  /*
  *  allocate the buffer to contain the
  *  port and tsel to bind server to
  */

  req.addr.buf = (char *)malloc(sizeof(tsap));

  /*
  *  fill address buffer with the address information
  */

  form_addr_1006((struct xti1006tsap *)req.addr.buf, \
                  pnum,                              \
                  NULL,                              \
                  stsel,                             \
                  fd,                                \
                  resfd);

  /*
  *  length of tsap
  */

  ret.addr.maxlen = sizeof(tsapret);
  ret.addr.buf = (char *)malloc(sizeof(tsapret));

  /*
  *  listening endpoint needs qlen > 0,
  *  ability to queue 10 requests
  */

  req.qlen = 10;
  ret.qlen = rqlen;

  /*
  *  now that we're done composing the req,
  *  do the bind of fd to addr in req
  */

  if (t_bind(fd,&req,&ret) != 0)
  {
    t_error("Error on t_bind");
    cleanup(fd);
    cleanup(resfd);
    exit(t_errno);
  }

  /*
  *  accepting endpoint with same addr needs qlen == 0
  */

  req.qlen = 0;

  /*
  *  now that we're done composing the req,
  *  do the bind of resfd to addr in req
  */

  if (t_bind(resfd,&req,&ret) != 0)
  {
    t_error("Error on t_bind");
    cleanup(fd);
    cleanup(resfd);
    exit(t_errno);
  }

  /*
  *  initialize call receipt structure for t_listen()
  */

  call.opt.maxlen = 0;
  call.addr.len = 0;
  call.opt.len = 0;
  call.udata.len = 0;
  call.opt.buf = NULL;

  call.addr.maxlen = sizeof(tsapret); /* listen for return*/
  call.addr.buf = (char *)malloc(sizeof(tsapret));

  call.udata.maxlen = 0;
  call.udata.buf = NULL;

  /*
  *  wait for connect req & get seq num in the call variable
  */

  looking = 1;
  while (looking)
    if (t_listen(fd,&call) == 0)
      looking = 0;
    else
      if (t_errno != TNODATA)
      {
        t_error("Error on t_accept");
        cleanup(fd);
        cleanup(resfd);
        exit(t_errno);
      }

  /*
  *  accept the connection on the accepting endpoint
  */

  if (t_accept(fd,resfd,&call) != 0)
  {
    t_error("Error on t_accept");
    cleanup(fd);
    cleanup(resfd);
    exit(t_errno);
  }

  /*
  *  receive data from the client
  */

  looking = 1;
  while (looking)
    if (t_rcv(resfd,buf,sizeof(buf),&rflags) > 0)
      looking = 0;
    else
      if (t_errno != TNODATA)
      {
        t_error("Error on t_rcv");
        cleanup(fd);
        cleanup(resfd);
        exit(t_errno);
      }

  /*
  *  sent data back to the client
  */

  strcpy(buf,"DATA FROM SERVER");

  looking = 1;
  while (looking)
    if (t_snd(resfd,buf,sizeof(buf),sflags) > 0)
      looking = 0;

  /*
  *  wait for disconnect from the client
  */

  looking = 1;
  while (looking)
    if (t_look(resfd) == T_DISCONNECT)
      looking = 0;

  /*
  *  receive the disconnect request
  */

  looking = 1;
  while (looking)
    if (t_rcvdis(resfd,NULL) == 0)
      looking = 0;

  /*
  *  unbind the endpoints
  */

  if (t_unbind(resfd) != 0)
  {
    t_error("Error on t_unbind for resfd");
    cleanup(fd);
    cleanup(resfd);
    exit(t_errno);
  }

  if (t_unbind(fd) != 0)
  {
    t_error("Error on t_unbind for fd");
    cleanup(fd);
    cleanup(resfd);
    exit(t_errno);
  }

  /*
  *  if fd is an endpoint, try to close it
  */

  cleanup(fd);

  /*
  *  if resfd is an endpoint, try to close it
  */

  cleanup(resfd);

  printf("Server ended successfully\n");
  exit(0);

}

/*********************************************************************/

void form_addr_1006(addrbuf1006,portnum,hostnmstr,tselstr1006,fd1,fd2)

/*
*  formats the provided address information
*  into the buffer for RFC1006
*/

/*
*  address buffer to be filled in
*/

struct xti1006tsap *addrbuf1006;

int   portnum;

/*
*  hostnmstr represented as a string
*/

char            *hostnmstr;

/*
*  tsel represented as a string
*/

char            *tselstr1006;

/*
*  one possible endpoint to close if
*  an error occurs in forming address
*/

int   fd1;

/*
*  other possible endpoint to close
*/

int   fd2;

{


  /*
  *  check validity of hostname
  *  there's no way program can
  *  continue without valid addr
  */

  if (strlen(hostnmstr) > 64)
  {
     fprintf(stderr,"hostname %s too long\n",hostnmstr);
     /*
     *  don't want TADDRBUSY when you try to reuse the address
     */
     cleanup(fd1);
     cleanup(fd2);
     exit(TBADADDR);
  }

  addrbuf1006->xti1006_hostnm_len = strlen(hostnmstr);
  strcpy(addrbuf1006->xti1006_hostnm,hostnmstr);

  /*
  *  check validity of hostname
  *  there's no way program can
  *  continue without valid addr
  */

  if (strlen(tselstr1006) > 64)
  {
     fprintf(stderr,"tsel %s too long\n",tselstr1006);
     /*
     *  don't want TADDRBUSY when you try to reuse the address
     */
     cleanup(fd1);
     cleanup(fd2);
     exit(TBADADDR);
  }

  addrbuf1006->xti1006_tsel_len = strlen(tselstr1006);
  strcpy(addrbuf1006->xti1006_tsel,tselstr1006);

  if (tselstr1006 == "Nulltsap")
  {
     addrbuf1006->xti1006_tsel_len = 0;
     strcpy(addrbuf1006->xti1006_tsel,NULL);
  }
  else
  {
     addrbuf1006->xti1006_tsel_len = strlen(tselstr1006);
     strcpy(addrbuf1006->xti1006_tsel,tselstr1006);
  } /* endif */

  if (portnum != -1)
     addrbuf1006->xti1006_tset = portnum;

}
/*********************************************************************/

void cleanup(fd)

int fd;

{
  if (fd >= 0)
    if (t_close(fd) != 0)
    {
       fprintf(stderr,"unable to t_close() endpoint while");
       fprintf(stderr," cleaning up from error\n");
     }
}
Figure 1. Sample server code for XTI