[ Previous | Next | Contents | Search ]
AIXLink/X.25 1.1 for AIX: Guide and Reference

X.25 Example Program svcxmit: Make a Call Using an SVC

This example program uses a switched virtual circuit (SVC) to make a call and transmit data, as follows. Example program svcrcv is designed to receive the data sent by this program.

Program Description

To use the X.25 program:

  1. Initialize the API for the port specified by LINK_NAME (x25_init).
  2. If initialization failed, the program displays a message. Exit from the program.
  3. Get a counter (x25_ctr_get).
  4. Make a call from this address specified by the CALLING_ADDR flag to the address specified by the CALLED_ADDR flag, enabling D-bit acknowledgment (x25_call).
  5. Wait for a call-clear or call-connected message (x25_ctr_wait).
  6. Receive the message (x25_receive).
  7. If the message is call-connected:
    1. Send data (x25_send), without the D-bit set.
    2. Send data (x25_send), with the D-bit set.
    3. Wait for (x25_ctr_wait) and receive (x25_receive) acknowledgment of the data sent with the D-bit set.
    4. Clear the call (x25_call_clear).
  8. If the call was cleared by the remote DTE (the other user), the program displays a message.
  9. Remove the counter (x25_ctr_remove).
  10. Terminate the API (x25_term).

Example Program svcxmit

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <NLchar.h>
#include <x25sdefs.h>
#define LINK_NAME    "x25s0"            /* Name of X.25 port.           */
#define CALLING_ADDR "54321"            /* Calling Network User Address */
#define CALLED_ADDR  "1234502"          /* Called  Network User Address */
 
#define SAMPLE_NAME "IBMSAMP"         /* A name in the X.25 routing list.*/
 
#define INFO        "Hello World"
#define INFO2       "Goodbye Everyone"
/*****************************************************************************/
/* Function     main                                                         */
/* Description  This program is designed to demonstrate usage of the X.25    */
/*              API. It makes a call, transmits some data, and then clears   */
/*              the call.                                                    */
/*              Example program svcrcv is designed to receive the data sent */
/*              by this program.                                             */
/*              Note that, in a production program, you should check the     */


int main(
  int argc,
  char *argv[])
{
  int conn_id;        /* Connection identifier,                              */
                      /*  to identify the call once it is made.               */
  int ctr_id;         /* Counter identifier to be associated with the call.  */
  int rc;             /* Used for return codes.                               */
  int ctr_num = 1;    /* The number of counters in counter array.             */  
 /*****************************************************************************/
 /* The following structures are defined in the x25sdefs.h file.              */
 /*****************************************************************************/
struct cb_msg_struct cb_msg;
struct cb_link_name_struct cb_link_name;
struct ctr_array_struct ctr_array[1];    
struct cb_call_struct cb_call;    
struct cb_clear_struct cb_clear;   
struct cb_data_struct cb_data; 
  /***************************************************************************/
  /* Initialize the API for access to a link.                                */
  /***************************************************************************/
  cb_link_name.flags = X25FLG_LINK_NAME;
  cb_link_name.link_name = LINK_NAME;
  rc = x25_init<(&cb_link_name);                                                  
  if (rc < 0)
  {
    (void)printf("%s: x25_init failed : x25_errno = %d errno = %d\n",
                argv[0],x25_errno,errno);
    return(1);
  }
  else
  {  
    /************************************************************************/
    /* Get a counter to be used to notify us of incoming messages.          */
    /************************************************************************/
     ctr_id = x25_ctr_get();
    /************************************************************************/
    /* Set the flags in the cb_call structure to indicate which fields      *
    /* have been filled in. The fields which this program sets              */
    /* are the calling and called addresses, and the link on which to call. */
    /* The D-bit field must also be set, as there will be a data packet     */
    /* sent later which sets the D-bit.                                     */
    /************************************************************************/
    cb_call.flags = X25FLG_LINK_NAME;      /* Set flag for using linkname.  */
    cb_call.link_name = LINK_NAME;
 
    cb_call.flags |= X25FLG_CALLING_ADDR;  /* Set flag for calling address. */
    cb_call.calling_addr = CALLING_ADDR;
 
    cb_call.flags |= X25FLG_CALLED_ADDR;   /* Set flag for called address.  */
    cb_call.called_addr = CALLED_ADDR; 
    cb_call.flags |= X25FLG_D_BIT;         /* Set flag for D-bit.         */
    /* Now that cb_call structure has been set up, make the call.          */
    /* The return code is the connection identifier, which will be used to  */
    /* refer to this call later.                                            */

    conn_id = x25_call(&cb_call,ctr_id);                                       
    if (conn_id == -1)
    {
      (void)printf("%s: x25_call failed : x25_errno = %d errno = %d\n",
                  argv[0],x25_errno,errno);
      return(1);
    }
    else
      (void)printf("%s: Placed outgoing call\n",argv[0]); 
    /************************************************************************/
    /* After making the call, prepare for either a call-connected or a      */
    /* clear-indication message to arrive:                                  */
    /* wait for the counter value to change indicating an incoming message. */
    /* (If there were more than one counter in the array, you would have to */
    /* test the counter identifier to see which one had been incremented.   */
    /* In this case there is only one, so we do not have to do this.)       */
    /************************************************************************/
    ctr_array[0].flags = X25FLG_CTR_ID;
    ctr_array[0].flags |= X25FLG_CTR_VALUE;
    ctr_array[0].ctr_id = ctr_id;
    ctr_array[0].ctr_value = 0;
 
    (void)x25_ctr_wait(ctr_num,ctr_array); 
    /* Receive the call-clear or call-connected packet.                     */
    (void)x25_receive(&conn_id,&cb_msg);                                          
    /************************************************************************/
    /* If the incoming message shows that the call has been connected,      */
    /* send some data<.                                                      */
    /************************************************************************/
    if (cb_msg.msg_type == X25_CALL_CONNECTED)
    {
      cb_data.flags = X25FLG_DATA;
      cb_data.data_len = strlen(INFO);
      cb_data.data = INFO;
      (void)x25_send(conn_id,&cb_data);
      (void)printf("%s: Data sent\n",argv[0]); 
      /**********************************************************************/
      /* Send some more data but this time with the D bit set. This         */
      /* requires the receiver to send an acknowledgement to this data,     */
      /* so we have to wait for the acknowledgment to arrive.               */
      /**********************************************************************/
      cb_data.flags = X25FLG_DATA;
      cb_data.flags |= X25FLG_D_BIT;
      cb_data.data_len = strlen(INFO2);
      cb_data.data = INFO2;
      (void)x25_send(conn_id,&cb_data);
      (void)printf("%s: Data sent\n",argv[0]);
      /* Wait for and receive acknowledgement                               */
      (void)x25_ctr_wait(ctr_num,ctr_array);  
      (void)x25_receive(&conn_id,&cb_msg);   
 
      if (cb_msg.msg_type == X25_DATA_ACK)
        (void)printf("%s: Data has been acknowledged.\n",argv[0]);
      else
        (void)printf("%s: Unexpected packet received.\n",argv[0]);     
      /**********************************************************************/
      /* Clear the call now that transmission is completed.                 */
      /**********************************************************************/
      cb_clear.flags = X25FLG_CAUSE;
      cb_clear.flags |= X25FLG_DIAGNOSTIC;
      cb_clear.cause = 0;            /* The CCITT code for DTE-originated   */
      cb_clear.diagnostic = 0;       /* No further information              */
 
      (void)printf("%s: Clearing the call.",argv[0]);
      
      /* The x25_call_clear function can return information from the clear  */
      /* confirmation packet. However, this isn't required here, so set the */
      /* third parameter to NULL.                                           */
      
      (void)x25_call_clear(conn_id,&cb_clear,(struct cb_msg_struct *)NULL);
    }    
    /************************************************************************/
    /* If the message received was a clear-indication,                      */
    /* print out a message before terminating the program.                  */
    /************************************************************************/
    else if (cb_msg.msg_type == X25_CLEAR_INDICATION)
    {
      (void)printf("%s: Call cleared. Cause = 0x%02x Diagnostic = 0x%02x\n",
        argv[0], cb_msg.msg_point.cb_clear->cause,
        cb_msg.msg_point.cb_clear->diagnostic);
    } 
    /************************************************************************/
    /* Finally, tidy up by removing the counter and terminating the API.    */
    /************************************************************************/
    (void)x25_ctr_remove(ctr_id);
    (void)x25_term(&cb_link_name);
  }
  return(0);
}

[ Previous | Next | Contents | Search ]