Solstice X.25 9.2 Developer's Guide

3.1 Making a Single Call

This section shows the process for making a single, straightforward call. The call being made is a standard X.25 call. It does not have to deal with Expedited Data or Resets. The disconnect is initiated locally. The steps for making a standard X.25 call are:

  1. Open a stream on the /dev/x25 device:

    if ((x25_fd = open("/dev/x25", O_RDWR)) < 0) {
     	perror("Opening Stream");
     	exit(1);
     	}
  2. Open a connection to the open stream.

    1. Allocate a Connect Request structure.

    2. Supply any quality of service and facilities parameters that are required.

    3. Set the called (and optionally calling) addresses.

    4. Pass the Connect Request down to the X.25 Driver.

    5. Wait for the connect confirmation or rejection

      #define FALSE 0
       #define TRUE 1
       #define CUDFLEN 4
       #define DBUFSIZ 128
       #include <memory.h>
       #include <netx25/x25_proto.h>
       struct xaddrf called = { 0, 0, { 14, { 0x23, 0x42, 0x31, 
       0x56, 0x56, 0x56, 0x56 }}, 0 };
        /* no flags
         * DTE = "23423156565656", null NSAP
         */
       struct xcallf conreq;
       struct strbuf ctlblk, datblk;
       struct xdataf data; 
      
       main ()
       {
          .
          /* Convert link to internal format */
          called.link_id = 0;
          conreq.xl_type = XL_CTL;
          conreq.xl_command = N_CI;
          conreq.CONS_call = FALSE;
          /* This is not a CONS call */
          conreq.negotiate_qos = FALSE;
          /* Just use default */
          memset(&conreq.qos, 0, sizeof(struct qosformat));
          memcpy(&conreq.calledaddr, &called, sizeof(struct xaddrf));
          memset(&conreq.callingaddr, 0, sizeof(struct xaddrf));
        }

      In the example, the entire QOS field is zeroed, allowing for future additions to the structure. Setting the calling address to null, as shown, leaves the network to fill in this value. For more information on QOS and Facilities, see "2.7 Facilities and QOS Parameters".

  3. Send the message on the stream using the putmsg system call, passing any call user data in the data part of the message:

    char cudf[CUDFLEN] = { 1, 0, 0, 0 };
     ctlblk.len = sizeof(struct xcallf);
     ctlblk.buf = (char *) &conreq;
     datblk.len = CUDFLEN;
     datblk.buf = cudf;
     if (putmsg(x25_fd, &ctlblk, &datblk, 0) < 0 ) {
     	perror("Call putmsg");
     	exit(1);
     	}
  4. Transfer the data.

    In the data transfer phase, access is given to:

    • the Q-bit, to support X.29-like services

    • the M-bit, to signal packet fragmentation

    • the D-bit, to request confirmation of data delivery

    • Expedited data, to support X.29 and OSI CONS.

      Normal and Q-bit data is sent and received using the N_Data message and may be acknowledged using the N_DAck message. Expedited data uses the N_EData message, and is acknowledged using an N_EAck message.

      Once a connection has been successfully opened on a stream, sending a data packet is straightforward:

      char datbuf[DBUFSIZ];
       /* Copy data into datbuf[] here*/
       data.xl_type = XL_DAT;
       data.xl_command = N_Data;
       data.More = data.setQbit = data.setDbit = FALSE;
       ctlblk.len = sizeof(struct xdataf);
       ctlblk.buf = (char *) &data;
       datblk.len = DBUFSIZ;
       datblk.buf = datbuf;
       retval = putmsg(x25_fd, &ctlblk, &datblk, 0); 

      Normally, the call to putmsg blocks if there are flow control conditions in the connection which lead to either a full queue at the stream head, or a lack of streams resources. To avoid blocking due to a full queue, open the stream with the option O_NDELAY flagged. In this case, putmsg returns immediately, and the failure is signalled by a return value (retval) of EAGAIN.

      This procedure allows the application to carry out other processing (for example, receiving data) before trying again. The best method to use depends on the nature of the application.

  5. Close the connection.

    In this example, closure is initiated locally. The application sends a Disconnect Request (N_DI) message on the stream. Unless this is being used to reject an incoming call the X.25 driver signals that it has observed the message. It does this by sending a Disconnect Confirm upstream when it receives the Clear Confirm. In this way, the upper components can be certain that no messages will follow the Disconnect.

    In the case of rejection, the connection identifier supplied on the Connect Indication must be returned in the disconnect message. The disconnect (reject) is not acknowledged in this case.

    As in the case of a remote disconnection, once the response has been received the stream becomes idle, and remains in this state until the application sends out another control message. This may be to close the stream, or to initiate a new Listen or Connect request on it. The application should, however, not send any of these messages until it receives the Disconnect Response.

    As described in "6.4.7 N_DI--Clear Request/Indication ", a disconnect collision may occur. If this happens, no Clear Confirm is sent.

    /* Coded and sent disconnect request, process response */
     struct xdiscf  *dis_ind;
     struct xdcnff  *dis_cnf;
     struct extraformat *xqos = (struct extraformat *)0;
     if ( hdrptr->xl_type == XL_CTL ) {
     	switch( hdrptr->xl_command ) {
     /* Disconnect Collision */
     		case N_DI:
     			dis_ind = (struct xdiscf*)hdrptr; 
     			xqos = &dis_ind->indicatedqos.xtras;
     			break;
     /* Disconnect Confirmation */
     		case N_DC:
     			dis_cnf = (struct xdcnff*)hdrptr; 
     			xqos = &dis_cnf->indicatedqos.xtras;
     			break;
     		default:
     			return;
     		}
     	if ( xqos ) {
     /*
       * Print any charging information returned
       */
     		if ( xqos->chg_cd_len ) { 
     /* Print out Call Duration from chg_cd_field */
     			}
     		if ( xqos->chg_mu_len ) { 
     /* Print out Monetary Unit from chg_mu_field */
     			}
     		if ( xqos->chg_sc_len ) { 
     /* Print out Segment Count from chg_sc_field */
     			}
     		}  /* end if (xqos) */
     	}  /* end if (hdrptr->xl_type==XL_CTL) */