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.
#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 */ * return code from each subroutine call and take appropriate */ /* action. */ /* Return 0 if successful */ /* 1 if error occurs */ /*****************************************************************************/
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); }