2105 lines
91 KiB
HTML
2105 lines
91 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html
|
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html lang="en-us" xml:lang="en-us">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<meta name="security" content="public" />
|
|
<meta name="Robots" content="index,follow" />
|
|
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
|
|
<meta name="DC.Type" content="reference" />
|
|
<meta name="DC.Title" content="Example: Using the user-defined communications programs for file transfer" />
|
|
<meta name="abstract" content="This example shows how X.25-oriented applications use the user-defined communications support to connect to remote systems." />
|
|
<meta name="description" content="This example shows how X.25-oriented applications use the user-defined communications support to connect to remote systems." />
|
|
<meta name="DC.Relation" scheme="URI" content="apiexmp.htm" />
|
|
<meta name="DC.Relation" scheme="URI" content="../apis/qolsetf.htm" />
|
|
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
|
|
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
|
|
<meta name="DC.Format" content="XHTML" />
|
|
<meta name="DC.Identifier" content="apiexustran" />
|
|
<meta name="DC.Language" content="en-us" />
|
|
<!-- All rights reserved. Licensed Materials Property of IBM -->
|
|
<!-- US Government Users Restricted Rights -->
|
|
<!-- Use, duplication or disclosure restricted by -->
|
|
<!-- GSA ADP Schedule Contract with IBM Corp. -->
|
|
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
|
|
<link rel="stylesheet" type="text/css" href="./ic.css" />
|
|
<title>Example: Using the user-defined communications programs for file transfer</title>
|
|
</head>
|
|
<body id="apiexustran"><a name="apiexustran"><!-- --></a>
|
|
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
|
|
<h1 class="topictitle1">Example: Using the user-defined communications programs for file transfer</h1>
|
|
<div><p>This example shows how X.25-oriented applications use the user-defined
|
|
communications support to connect to remote systems.</p>
|
|
<div class="section"><p>Two user-defined application programs written in the ILE C programming
|
|
language are used to illustrate a simple file transfer between two systems
|
|
over an X.25 packet-switching data network (PSDN). Although an X.25 example
|
|
is shown, many of the same concepts can be applied to applications running
|
|
over token-ring and Ethernet local area networks (LANs). For the purposes
|
|
of the examples, the APIs are referred to by their call names. The includes <em>header</em>, <em>hexconv</em>,
|
|
and <em>typedefs</em> are not in QSYSINC. These includes are only documented
|
|
in the examples.</p>
|
|
<p>For this example, the following network configuration
|
|
will be used.</p>
|
|
<br /><img src="RBAFX652.gif" alt="Example
X.25 network" /><br /><div class="note"><span class="notetitle">Note:</span> Read the <a href="codedisclaimer.htm">Code license and disclaimer information</a> for
|
|
important legal information.</div>
|
|
</div>
|
|
<div class="section"><h4 class="sectiontitle">X.25 overview</h4><p>In this example X.25 network, the
|
|
source application on System A is responsible for establishing a switched
|
|
virtual circuit, or connection to the target application running on System
|
|
B. This is done by using the remote network address (System B's address) of
|
|
X'0000652'. When the target application on System B is initialized, it waits
|
|
for notification of an incoming call packet before proceeding. Once the virtual
|
|
circuit is established, the source application reads records from a file into
|
|
its output buffer and sends them to the target application using normal X.25
|
|
data transfer procedures. While receiving the file data, the target application
|
|
writes the data to a local file on System B. When the file transfer completes,
|
|
the source application closes the connection by issuing an X.25 clear request
|
|
packet and ends. When receiving the clear indication packet, the target application
|
|
also ends.</p>
|
|
</div>
|
|
<div class="section"><h4 class="sectiontitle">User-defined communications support overview</h4><p>Both
|
|
the source and target applications call the Query Line Description (QOLQLIND)
|
|
API to obtain information about the local X.25 line being used. This information
|
|
is stored in a local control block for use in establishing the peer connection
|
|
during X.25 connection processing. Both applications also call the Enable
|
|
Link (QOLELINK) API to enable the link for future communications. The iSeries™ server
|
|
line name, communications handle, and remote DTE address are passed to both
|
|
programs as arguments to the C function main(). For simplicity, the user space
|
|
names and data queue name on the call to the QOLELINK API are coded directly
|
|
in the applications.</p>
|
|
<div class="note"><span class="notetitle">Note:</span> Keyed data queue support is used by both applications.
|
|
The key length is 3 and the keys used are source (SRC) and target (TGT) for
|
|
the source and target applications, respectively.</div>
|
|
<p id="apiexustran__Header_38"><a name="apiexustran__Header_38"><!-- --></a><strong>Activating
|
|
filters</strong></p>
|
|
<p>Once the links have been enabled and both applications have
|
|
read their respective enable-complete entries from their data queues, the
|
|
target application program calls the Set Filter (QOLSETF) API to activate
|
|
a filter. The filter activated then identifies the protocol of the local X.25
|
|
service user. This filter is used by the user-defined communications support
|
|
on System B to route incoming calls. The actual filter type activated is X'00'
|
|
(for X.25 PID) and its associated value is X'21'. For more information concerning
|
|
filters, see Set Filter (QOLSETF) API. After activating the X'21' filter,
|
|
the target application waits for the source application to request a connection.</p>
|
|
<p id="apiexustran__Header_39"><a name="apiexustran__Header_39"><!-- --></a><strong>Establishing a connection</strong></p>
|
|
<p>The source application
|
|
calls the Send Data (QOLSEND) API with a X'B000' operation in its output data
|
|
buffer to establish a switched virtual circuit (SVC) to the target application.
|
|
Included in the first byte of the call user data is the protocol ID of the
|
|
target application, or X'21'. When the user-defined communications support
|
|
on System B sees the incoming call packet with the first byte of user data
|
|
equal to a previously activated filter, the call is routed to the process
|
|
responsible for activating that filter. In this case, the target application
|
|
will receive notification of an incoming call since it previously activated
|
|
filter X'21'.</p>
|
|
<p>While waiting for the incoming call, the target application
|
|
calls the Receive Data (QOLRECV) API to receive a X'B201' operation with incoming
|
|
call data. After doing so, the target application accepts the X.25 connection
|
|
by calling the QOLSEND API with a X'B400' operation in its output data buffer.
|
|
See for more information.</p>
|
|
<p id="apiexustran__Header_40"><a name="apiexustran__Header_40"><!-- --></a><strong>Sending data</strong></p>
|
|
<p>Once
|
|
the peer connection is established between the source and target applications
|
|
running on System A and System B respectively, the file transfer takes place.
|
|
The source application reads records from a local file and calls the QOLSEND
|
|
API with X'0000' operations in its output data buffer to transfer the file
|
|
data to System B. This process continues until the entire contents of the
|
|
source file has been sent to System B.</p>
|
|
<p id="apiexustran__Header_41"><a name="apiexustran__Header_41"><!-- --></a><strong>Receiving data</strong></p>
|
|
<p>After
|
|
accepting the X.25 connection, the target application waits until its data
|
|
queue receives incoming-data entries. When the first entry is read from the
|
|
queue, the QOLRECV API is called to determine which operation was received.
|
|
Barring failure, the target application should receive a X'0001' operation
|
|
as a result of the QOLRECV API call. The data contained in the input data
|
|
buffer is the file data received from System A. While receiving the file data,
|
|
the target application writes the data to a local file. This process continues
|
|
until the entire contents of the file is received from System A. The target
|
|
application then assumes the file transfer is complete when an operation other
|
|
than a X'0001' operation is received after a successful call to the QOLRECV
|
|
API. Most likely, the first non-X'0001' operation received will be X'B301'
|
|
operation, signalling that the user-defined communications support running
|
|
on System B received an SVC clear indication.</p>
|
|
<p id="apiexustran__Header_42"><a name="apiexustran__Header_42"><!-- --></a><strong>Clearing
|
|
the connection and disabling links</strong></p>
|
|
<p>Once the entire contents of the
|
|
file has been read and sent to System B, the source application calls the
|
|
QOLSEND API with a X'B100' operation in its output data buffer to clear the
|
|
X.25 connection. Afterwards, the source application closes its local file,
|
|
disables its local link by calling the QOLDLINK API, and ends.</p>
|
|
<p>When
|
|
the source application program sends a X'B100' operation, it causes the target
|
|
application to receive a X'B301' operation. After receiving this operation,
|
|
the target application program calls the QOLSEND API with a X'B100' operation
|
|
to locally close the connection between itself and the user-defined communications
|
|
support. Afterwards, the target application closes its local file, disables
|
|
its local link by calling the QOLDLINK API, and ends.</p>
|
|
<p id="apiexustran__Header_43"><a name="apiexustran__Header_43"><!-- --></a><strong>Using
|
|
timers and the data queue support</strong></p>
|
|
<p>Both the source and target application
|
|
programs use the user-defined communications support timer service to manage
|
|
the reception of certain operations. This is done by setting a timer before
|
|
checking the data queue for an entry. For example, the target application
|
|
sets a timer to manage the reception of file data from the source application.
|
|
If the timer expires, the user-defined communications support places a timer-expired
|
|
entry on the application's data queue. The target application then assumes
|
|
when receiving this entry that the source application ended abnormally. The
|
|
target application can then take the appropriate action to end itself.</p>
|
|
</div>
|
|
<div class="section"><h4 class="sectiontitle">ILE C compiler listings</h4><p>Below are the listings for
|
|
the source and target applications described in the previous paragraphs. Note
|
|
the reference numbers (for example, <span class="uicontrol">(1)</span>) in the listings.
|
|
Detailed explanations of each reference number block are found in <a href="#apiexustran__SPTCSOUR">Source application program listing references</a> and <a href="#apiexustran__SPTCTARG">Target application program listing references</a>.</p>
|
|
<p>The target application compiler
|
|
listing can be found in <a href="#apiexustran__HDRTARGET">Target application
|
|
on System B listing</a>.</p>
|
|
<p id="apiexustran__Header_45"><a name="apiexustran__Header_45"><!-- --></a><strong>Source application on
|
|
System A listing</strong></p>
|
|
<p>In this example, the source application is the
|
|
initiator of all meaningful work. In summary, the source program listed on
|
|
the following pages does the following:</p>
|
|
<ul><li>Calls the QOLQLIND API to get local X.25 line information</li>
|
|
<li>Opens the local file</li>
|
|
<li>Calls the QOLELINK API to establish a link for communications</li>
|
|
<li>Calls the QOLSEND API with X'B000' operation to establish a peer (SVC)
|
|
connection</li>
|
|
<li>Sends the local file to the target system using X'0000' operations </li>
|
|
<li>Calls the QOLSEND API with X'B100' operation to clear the peer (SVC) connection</li>
|
|
<li>Calls the QOLDLINK API to disable the link</li>
|
|
<li>Calls the QOLTIMER API to manage the reception of data queue entries</li>
|
|
</ul>
|
|
<p>To create the program using ILE C, use the Create Bound C (CRTBNDC)
|
|
command.</p>
|
|
<pre> Program name . . . . . . . . . :
|
|
<span class="uicontrol">(SOURCE)</span>
|
|
Library name . . . . . . . . : UDCS_APPLS
|
|
Source file . . . . . . . . . . : QCSRC
|
|
Library name . . . . . . . . : UDCS_APPLS
|
|
Source member name . . . . . . : SOURCE
|
|
Text Description . . . . . . . : Source Application Example
|
|
Output . . . . . . . . . . . . : *NONE
|
|
Compiler options . . . . . . . : *SOURCE *NOXREF *SHOWUSR
|
|
: *SHOWSYS *NOSHOWSKP *NOEXPMAC
|
|
: *NOAGR *NOPPONLY *NODEBUG
|
|
: *GEN *NOSECLVL *PRINT *LOGMSG
|
|
: *USRINCPATH
|
|
Checkout Options . . . . . . . : *NOAGR
|
|
Optimization . . . . . . . . . : *NONE
|
|
Inline Options:
|
|
Inliner . . . . . . . . . . . : *OFF
|
|
Mode . . . . . . . . . . . . : *NOAUTO
|
|
Threshold . . . . . . . . . . : 250
|
|
Limit . . . . . . . . . . . . : 2000
|
|
Debugging View . . . . . . . . : *NONE
|
|
Define Names . . . . . . . . . : *NONE
|
|
Language Level . . . . . . . . : *SOURCE
|
|
Source Margins:
|
|
Left margin . . . . . . . . . : 1
|
|
Right margin . . . . . . . . : 32754
|
|
Sequence columns:
|
|
Left column . . . . . . . . . : *NONE
|
|
Right column . . . . . . . . :
|
|
Message flagging level . . . . : 0
|
|
Compiler messages:
|
|
Message limit . . . . . . . . : *NOMAX
|
|
Message limit severity . . . : 30
|
|
Replace Program Object . . . . : *YES
|
|
User Profile . . . . . . . . . : *USER
|
|
Authority . . . . . . . . . . . : *LIBCRTAUT
|
|
Target Release . . . . . . . . : *CURRENT
|
|
System includes . . . . . . . . : *YES
|
|
|
|
/*******************************************************************/
|
|
/** Program Name: Source Application Program Example **/
|
|
/** **/
|
|
/** **/
|
|
/** Function: **/
|
|
/** This is the source application program example that uses **/
|
|
/** X.25 services provided by the user-defined communications **/
|
|
/** support to transfer a simple file to the target application **/
|
|
/** program running on system B. This program performs the **/
|
|
/** following: **/
|
|
/** 01. Open the source file name INFILE. **/
|
|
/** 02. Call QOLQLIND API to obtain local line information. **/
|
|
/** 03. Enable a link. **/
|
|
/** 04. Send a 'B000'X operation (call request). **/
|
|
/** 05. Receive a 'B001'X operation (call confirmation). **/
|
|
/** 06. Read record(s) from the file opened in step 1). and **/
|
|
/** send '0001'X operation(s) to transfer the file to **/
|
|
/** the target application program. **/
|
|
/** 07. Send a 'B100'X operation (clear call request). **/
|
|
/** 08. Receive a 'B101'X operation. **/
|
|
/** 09. Disable the link enabled in step 3). **/
|
|
/** **/
|
|
/** A data queue will be actively used to manage the operation **/
|
|
/** of this program. Data queue support will be used to monitor **/
|
|
/** for the completion of the enable and disable routines, as **/
|
|
/** well as timer expirations and incoming data. Timers are **/
|
|
/** used to ensure that there will never be an infinite wait on **/
|
|
/** the data queue. If a timer expires, the link enabled will **/
|
|
/** be disabled and the program will stop. **/
|
|
/** **/
|
|
/** Inputs: **/
|
|
/** The program expects the following input parameters **/
|
|
/** Line Name: This is the name of the line description **/
|
|
/** that will be used to call the QOLELINK API. **/
|
|
/** The line must be an X.25 line with at least **/
|
|
/** one SVC of type *SVCBOTH or *SVCOUT. **/
|
|
/** **/
|
|
/** CommHandle: This is the logical name that will be used **/
|
|
/** to identify the link enabled. **/
|
|
/** **/
|
|
/** Remote DTE Address: The is the Local Network Address **/
|
|
/** of System B. **/
|
|
/** **/
|
|
/** **/
|
|
/** Outputs: **/
|
|
/** Current status of the file transfer will be provided when **/
|
|
/** running this program. If an error should occur, then a **/
|
|
/** message will be displayed indicating where the error occurred **/
|
|
/** and the program will end. If the program completes **/
|
|
/** successfully, a "successful completion" message will be **/
|
|
/** posted. **/
|
|
/** **/
|
|
/** Language: ILE C **/
|
|
/** **/
|
|
/** APIs used: QOLELINK, QUSPTRUS, QOLRECV, QOLSEND, QOLDLINK, **/
|
|
/** QOLTIMER, QRCVDTAQ **/
|
|
/** **/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
#include "header"
|
|
#include "typedef"
|
|
#include "hexconv"
|
|
<span class="uicontrol">(1)</span>
|
|
|
|
/************ Typedef Declarations *******************/
|
|
<span class="uicontrol">(2)</span>
|
|
|
|
void senddata(sendparms *a, char *b, desc *c, char *d, char *e, int f);
|
|
void sndformat1(sendparms *a,char *b, char *c, char *d, qlindparms *f);
|
|
void sndformat2 (sendparms *a, char *b, char *c);
|
|
void setfilters (hdrparms *a);
|
|
void byte (char *a, int b, char *c, int d);
|
|
void printespec (espec *a);
|
|
void settimer(unsigned short *a,char *b,qentry *c,usrspace *d,char *e);
|
|
void dequeue (int a, char *b, qentry *c, usrspace *d);
|
|
void x25lind (qlindparms *a, char *b);
|
|
int getline (char *a, int b, FILE *c);
|
|
void disablelink (disableparms *a, char *b, usrspace *c);
|
|
void handler (disableparms a, usrspace *b);
|
|
|
|
void _GetExcData(_INTRPT_Hndlr_Parms_T *parms);
|
|
/**********************************************************/
|
|
/*************** Start Main Program *******************/
|
|
/**********************************************************/
|
|
main (int argc, char *argv[])
|
|
{
|
|
/************ Variable Declarations *******************/
|
|
usrspace inbuff, /* Input Data Buffer */
|
|
indesc, /* Input Buffer Descriptor */
|
|
outbuff, /* Output Data Buffer */
|
|
outdesc, /* Output Buffer Descriptor */
|
|
qname; /* Data Queue */
|
|
int length, /* Data Queue key length */
|
|
linesiz, /* Length of line that is read in */
|
|
i= 0; /* counter */
|
|
unsigned short expctid; /* Message ID that is expected */
|
|
char commhandle[10], /* Command Line Parameter */
|
|
*buffer, /* Pointer to buffer */
|
|
rmtdte[18], /* Remote DTE read in */
|
|
line[132], /* Line to read in */
|
|
key[256]; /* Data Queue key identifier */
|
|
desc *descriptor; /* Pointer to buffer descriptor */
|
|
/** definitions for the API functions **/
|
|
enableparms enable;
|
|
disableparms disable;
|
|
sendparms send;
|
|
recvparms recv;
|
|
setfparms setf;
|
|
timerparms timer;
|
|
qlindparms qlind;
|
|
qentry dataq;
|
|
hdrparms *header;
|
|
|
|
<span class="uicontrol">(3)</span>
|
|
|
|
/***--- Open the file to send to remote side ----**/
|
|
if ((fptr = fopen("UDCS_APPLS/INFILE(INFILE)", "r")) == NULL)
|
|
{
|
|
printf("Unable to open source input file in UDCS_APPLS LIB.\n");
|
|
printf("The Program was terminated.\n\n");
|
|
return;
|
|
}
|
|
/***--- Open the display file as our input screen. ----**/
|
|
if ((screen = fopen("ERRORSPEC", "ab+ type=record")) == NULL)
|
|
{
|
|
printf("Unable to open display file.\n");
|
|
printf("The Program was terminated.\n\n");
|
|
return;
|
|
}
|
|
/** set the exception handler **/
|
|
|
|
signal(SIGALL,SIG_DFL);
|
|
/** Clear the command line Parameters **/
|
|
strncpy(enable.linename, " ", 10); /* Clear linename */
|
|
strncpy(commhandle, " ", 10); /* Clear Commhandle*/
|
|
strncpy(rmtdte, " ", 17); /* Clear Remote DTE*/
|
|
/** Receive command line Parameters **/
|
|
strncpy(enable.linename, argv[1], strlen(argv[1]));
|
|
strncpy(commhandle, argv[2], strlen(argv[2]));
|
|
strncpy(rmtdte, argv[3], strlen(argv[3]));
|
|
rmtdte[strlen(argv[3])] = '\0';
|
|
/** Initialize the user spaces **/
|
|
strncpy(inbuff.library, "UDCS_APPLS", 10); /* Input Buffer */
|
|
strncpy(inbuff.name, "SOURCEIBUF", 10);
|
|
strncpy(indesc.library, "UDCS_APPLS", 10); /* Input B Desc */
|
|
strncpy(indesc.name, "SOURCEBDSC", 10);
|
|
strncpy(outbuff.library, "UDCS_APPLS", 10); /* Output Buffer*/
|
|
strncpy(outbuff.name, "SOURCEOBUF", 10);
|
|
strncpy(outdesc.library, "UDCS_APPLS", 10); /* Output B Desc */
|
|
strncpy(outdesc.name, "SOURCEODSC", 10);
|
|
strncpy(qname.library, "UDCS_APPLS", 10); /* Data queue */
|
|
strncpy(qname.name, "X25DTAQ ", 10);
|
|
/***** retrieve the line description information ******/
|
|
x25lind (&qlind, enable.linename);
|
|
if ((qlind.retcode != 0) || (qlind.reason != 0))
|
|
{
|
|
printf("Query line description failed.\n");
|
|
printf("Return code = %d\n", qlind.retcode);
|
|
printf("Reason code = %d\n\n", qlind.reason);
|
|
return;
|
|
}
|
|
/***** Hard Code the QOLELINK Input Parameters ******/
|
|
enable.maxdtax25 = 512;
|
|
enable.keylength = 3;
|
|
strncpy (enable.keyvalue, "SND", 3);
|
|
|
|
<span class="uicontrol">(4)</span>
|
|
|
|
/**************************************************/
|
|
/************ Enable the line *******************/
|
|
/**************************************************/
|
|
QOLELINK (&(enable.retcode), &(enable.reason), &(enable.tdusize),\
|
|
&(enable.numunits), &(enable.maxdtalan), &(enable.maxdtax25),\
|
|
(char *)&inbuff, (char *)&indesc, (char *)&outbuff,\
|
|
(char *)&outdesc, &(enable.keylength), enable.keyvalue,\
|
|
(char *)&qname, enable.linename, commhandle);
|
|
if ((enable.retcode != 0) || (enable.reason != 0))
|
|
{
|
|
printf("Line %.10s with Commhandle %.10s was NOT ENABLED.\n",\
|
|
enable.linename, commhandle);
|
|
printf("Return code = %d\n", enable.retcode);
|
|
printf("Reason code = %d\n\n", enable.reason);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(5)</span>
|
|
|
|
/*-------- Set a timer for Enable Link ---------**/
|
|
expctid = 0xF0F0;
|
|
settimer(&expctid, "Enable", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F0)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(6)</span>
|
|
|
|
/******************************************************************/
|
|
/************** Set up a Call Request Packet *******************/
|
|
/******************************************************************/
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS(&outbuff, &buffer);
|
|
QUSPTRUS(&outdesc, &descriptor);
|
|
send.ucep = 26; /* set the UCEP number */
|
|
send.operation = 0xB000; /* send a call request */
|
|
send.numdtaelmnts = 1; /* send one data unit */
|
|
/**----------- Send the packet ---------**/
|
|
sndformat1 (&send, buffer, rmtdte, commhandle, &qlind);
|
|
if ((send.retcode != 0) || (send.reason != 0))
|
|
{
|
|
printf("Call request packet not sent\n");
|
|
printf("Return code = %d\n", send.retcode);
|
|
printf("Reason code = %d\n", send.reason);
|
|
printf("new pcep %d\n", send.newpcep);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(7)</span>
|
|
|
|
/*****************************************************************/
|
|
/*********** Receive the Call CONFIRMATION packet ********/
|
|
/*****************************************************************/
|
|
/*-------- Set a timer to receive a message ---------**/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Rcv Call", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
QOLRECV (&(recv.retcode), &(recv.reason), &(recv.ucep),\
|
|
&(recv.pcep), &(recv.operation), &(recv.numdtaunits),\
|
|
&(recv.dataavail), &(recv.errorspecific), commhandle);
|
|
if ((recv.retcode != 0) || (recv.reason != 0))
|
|
{
|
|
printf("Recv Call reqst resp failed\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/* Interpret the Received Operation */
|
|
if (recv.operation != 0xB001)
|
|
{
|
|
printf("Recvd opr %x instead of opr B001\n", recv.operation);
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
printf("We have an X.25 SVC connection\n\n");
|
|
|
|
<span class="uicontrol">(8)</span>
|
|
|
|
/*****************************************************************/
|
|
/*************** Send the file to the target application *******/
|
|
/*****************************************************************/
|
|
send.pcep = send.newpcep; /* set the PCEP number */
|
|
/*************** Send the Mbr LGRF in file DOC ****************/
|
|
linesiz = getline(line, 92, fptr); /* Get first record **/
|
|
while (linesiz != 0)
|
|
{
|
|
/*************** Send a Packet of Data ***************/
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS(&outbuff, &buffer);
|
|
QUSPTRUS(&outdesc, &descriptor);
|
|
send.operation = 0x0000;
|
|
send.numdtaelmnts = 1;
|
|
/**----- Send the packet -------------**/
|
|
senddata (&send, buffer, descriptor, commhandle, line, linesiz);
|
|
if ((send.retcode != 0) || (send.reason != 0))
|
|
{
|
|
printf("Data NOT sent for commhandle %.9s\n", commhandle);
|
|
printf("Return code = %d\n", send.retcode);
|
|
printf("Reason code = %d\n", send.reason);
|
|
printf("new pcep %d\n", send.newpcep);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
i = i + 1;
|
|
printf("Data %d Sent for commhandle %.9s.\n\n", i, commhandle);
|
|
linesiz = getline(line, 92, fptr); /** Get next record **/
|
|
} /*** End While loop ***/
|
|
/***************************************************************/
|
|
/*************** Set up a Clear Request Packet **************/
|
|
/***************************************************************/
|
|
<span class="uicontrol">(9)</span>
|
|
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS(&outbuff, &buffer);
|
|
QUSPTRUS(&outdesc, &descriptor);
|
|
send.operation = 0xB100; /** send clear request **/
|
|
send.numdtaelmnts = 1; /** send one data unit **/
|
|
/**----------- Send the packet ---------**/
|
|
sndformat2 (&send, buffer, commhandle);
|
|
if ((send.retcode != 0) || (send.reason != 0))
|
|
{
|
|
printf("Clear request packet not sent\n");
|
|
printf("Return code = %d\n", send.retcode);
|
|
printf("Reason code = %d\n", send.reason);
|
|
printf("new pcep %d\n", send.newpcep);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(10)</span>
|
|
/***************************************************************/
|
|
/*********** Receive the Clear Request Response packet *****/
|
|
/***************************************************************/
|
|
/*-------- Set a timer to receive a message ---------**/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Rv Clr Rqt", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/*********** Call QOLRECV to Receive the Clear Response *****/
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS (&inbuff, &buffer);
|
|
QUSPTRUS (&indesc, &descriptor);
|
|
QOLRECV (&(recv.retcode), &(recv.reason), &(recv.ucep),\
|
|
&(recv.pcep), &(recv.operation), &(recv.numdtaunits),\
|
|
&(recv.dataavail), &(recv.errorspecific), commhandle);
|
|
if ((recv.retcode != 0) || (recv.reason != 0))
|
|
{
|
|
printf("Recv clear response failed\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/* Interpret the Received Operation */
|
|
if (recv.operation != 0xB101)
|
|
{
|
|
printf("Recvd opr %x instead of opr B101\n", recv.operation);
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/***********************************************/
|
|
/*** Disable the link and end the program ****/
|
|
/***********************************************/
|
|
disablelink (&disable, commhandle, &qname);
|
|
printf("****** SOURCE completed successfully ******\n\n");
|
|
} /* End Main */
|
|
/*****************************************************************/
|
|
/************** Start Subroutine Section **********************/
|
|
/*****************************************************************/
|
|
/*************************************************************/
|
|
/*************** Send a Packet of Data ******************/
|
|
<span class="uicontrol">(11)</span>
|
|
|
|
void senddata (sendparms *send,
|
|
char *buffer,
|
|
desc *descriptor,
|
|
char *commhandle,
|
|
char *line,
|
|
int linesiz)
|
|
{
|
|
descriptor->length = linesiz;
|
|
descriptor->more = 0;
|
|
descriptor->qualified = 0;
|
|
descriptor->interrupt = 0;
|
|
descriptor->dbit = 0;
|
|
strncpy (buffer, line, linesiz);
|
|
QOLSEND (&(send->retcode), &(send->reason),
|
|
&(send->errorspecific),\
|
|
&(send->newpcep), &(send->ucep), &(send->pcep), \
|
|
commhandle, &(send->operation), &(send->numdtaelmnts));
|
|
} /* End senddata Subroutine */
|
|
/*********************************************************/
|
|
/************ Routine to fill X.25 Format I ***********/
|
|
void sndformat1 (sendparms *send,
|
|
char *buffer,
|
|
char *rmtdte,
|
|
char *commhandle,
|
|
qlindparms *qlind)
|
|
{
|
|
format1 *output = (format1 *) buffer;
|
|
register int counter;
|
|
register querydata *qd;
|
|
qd = (querydata *)&(qlind->userbuffer);
|
|
output->type = 2; /* SVC used */
|
|
output->logchanid = 0x0;
|
|
output->sendpacksize = qd->x25data.defsend;
|
|
output->sendwindsize = qd->x25data.windowsend;
|
|
output->recvpacksize = qd->x25data.defrecv;
|
|
output->recvwindsize = qd->x25data.windowrecv;
|
|
output->dtelength = strlen(rmtdte);
|
|
byte(output->dte, 16, rmtdte, strlen(rmtdte));
|
|
output->dbit = 0;
|
|
output->cug = 0;
|
|
output->cugid = 0;
|
|
output->reverse = 0;
|
|
output->fast = 0;
|
|
output->faclength = 0;
|
|
byte(output->facilities, 109, "", 0);
|
|
output->calllength = 1;
|
|
byte(output->callud, 128, "21", 2); /* Contains Remote PID */
|
|
output->misc[0] = 0; /* change to 0x80 for reset support */
|
|
output->misc[1] = 0;
|
|
output->misc[2] = 0;
|
|
output->misc[3] = 0;
|
|
output->maxasmsize = 16383;
|
|
output->autoflow = 32;
|
|
QOLSEND (&(send->retcode), &(send->reason),
|
|
&(send->errorspecific),\
|
|
&(send->newpcep), &(send->ucep), &(send->pcep),\
|
|
commhandle, &(send->operation), &(send->numdtaelmnts));
|
|
} /* End sndformat1 Subroutine */
|
|
/**********************************************************/
|
|
/************ Routine to fill X.25 Format II ***********/
|
|
void sndformat2 (sendparms *send,
|
|
char *buffer,
|
|
char *commhandle)
|
|
{
|
|
format2 *output = (format2 *) buffer;
|
|
output->type = 1;
|
|
output->cause = 'FF';
|
|
output->diagnostic = 'FF';
|
|
output->faclength = 0;
|
|
byte(output->facilities, 109, "", 0);
|
|
output->length = 0;
|
|
byte(output->userdata, 128, "", 0);
|
|
QOLSEND (&(send->retcode), &(send->reason),
|
|
&(send->errorspecific),\
|
|
&(send->newpcep), &(send->ucep), &(send->pcep),\
|
|
commhandle, &(send->operation), &(send->numdtaelmnts));
|
|
} /* End sndformat2 Subroutine */
|
|
|
|
<span class="uicontrol">(12)</span>
|
|
|
|
/********************************************/
|
|
/******** Routine to disable ***********/
|
|
void disablelink (disableparms *disable,
|
|
char *commhandle,
|
|
usrspace *qname)
|
|
{
|
|
unsigned short expctid;
|
|
qentry dataq;
|
|
disable->vary = 1; /* Hard coded to be varied off */
|
|
QOLDLINK (&(disable->retcode), &(disable->reason),\
|
|
commhandle, &(disable->vary));
|
|
if ((disable->retcode != 0) && (disable->reason != 00))
|
|
{
|
|
printf ("Link %.10s did not disabled.\n", commhandle);
|
|
printf ("return code = %d\n", disable->retcode);
|
|
printf ("reason code = %d\n\n", disable->reason);
|
|
}
|
|
/**------- Set a timer to receive disable complete msg --------**/
|
|
expctid = 0xF0F1;
|
|
settimer(&expctid, "Disable", &dataq, qname, commhandle);
|
|
if (expctid != 0xF0F1)
|
|
{
|
|
printf("Disable link did not complete successfully");
|
|
return;
|
|
}
|
|
printf ("%.10s link disabled \n", commhandle);
|
|
/** close the files **/
|
|
fclose(fptr);
|
|
fclose(screen);
|
|
} /* End disablelink Subroutine */
|
|
/**************************************************************/
|
|
/** Routine to convert string to Hexadecimal format ******/
|
|
void byte (char *dest,
|
|
int dlength,
|
|
char *source,
|
|
int slength)
|
|
{
|
|
register int counter;
|
|
char holder[2];
|
|
for (counter=0;counter<dlength;counter++)
|
|
dest[counter]=0;
|
|
for (counter=slength-1;counter>=0;counter--)
|
|
if (isxdigit(source[counter]))
|
|
{
|
|
holder[0]=source[counter];
|
|
holder[1]='\0';
|
|
if (counter % 2 == 0)
|
|
dest[counter/2] += (char) hextoint(holder)*16;
|
|
else dest[counter/2] += (char) hextoint(holder);
|
|
}
|
|
} /* End byte Subroutine */
|
|
/**************************************************************/
|
|
/** Routine to display the ErrorSpecific output ******/
|
|
void printespec(espec *errorspecific)
|
|
{
|
|
especout outparms;
|
|
|
|
sprintf(outparms.hwecode, "%.8X", errorspecific->hwecode);
|
|
sprintf(outparms.timestamp, "%.8X%.8X", errorspecific->timestamphi,\
|
|
errorspecific->timestamplo);
|
|
sprintf(outparms.elogid, "%.8X", errorspecific->elogid);
|
|
if (errorspecific->flags & 0x40)
|
|
outparms.fail = 'Y';
|
|
else outparms.fail = 'N';
|
|
if (errorspecific->flags & 0x20)
|
|
outparms.zerocodes = 'Y';
|
|
else outparms.zerocodes = 'N';
|
|
if (errorspecific->flags & 0x10)
|
|
outparms.qsysopr = 'Y';
|
|
else outparms.qsysopr = 'N';
|
|
sprintf(outparms.cause,"%.2X", errorspecific->cause);
|
|
sprintf(outparms.diagnostic, "%.2X", errorspecific->diagnostic);
|
|
sprintf(outparms.erroffset, "%.6d", errorspecific->erroroffset);
|
|
fwrite(&outparms, 1, sizeof(especout), screen);
|
|
fread("", 0, 0, screen);
|
|
} /* End printespec Subroutine */
|
|
<span class="uicontrol">(13)</span>
|
|
|
|
/************* Set a timer and dequeue next entry ******/
|
|
void settimer (unsigned short *expctid,
|
|
char *process,
|
|
qentry *dataq,
|
|
usrspace *qname,
|
|
char *commhandle)
|
|
{
|
|
timerparms timer;
|
|
disableparms disable;
|
|
int length;
|
|
char key[6];
|
|
timer.interval = 20000; /* Set timer for 20 seconds */
|
|
timer.establishcount = 1;
|
|
timer.keylength = 3; /* Set key value */
|
|
strncpy(timer.keyvalue, "SRC", 3);
|
|
timer.operation = 1; /* Set a timer */
|
|
QOLTIMER (&(timer.retcode), &(timer.reason), timer.handleout,\
|
|
timer.handlein, (char *)qname, &(timer.operation),\
|
|
&(timer.interval), &(timer.establishcount),\
|
|
&(timer.keylength), timer.keyvalue, timer.userdata);
|
|
if ((timer.retcode != 0) || (timer.reason != 0))
|
|
{
|
|
printf("%s timer failed while being set.\n", process);
|
|
printf("Return code = %d\n", timer.retcode);
|
|
printf("Reason code = %d\n\n", timer.reason);
|
|
}
|
|
/**------- Dequeue an entry --------**/
|
|
strncpy(key, "SRC",3);
|
|
length = 3;
|
|
dequeue (length, key, dataq, qname);
|
|
/*** Cancel timer ***/
|
|
if (dataq->msgid != 0xF0F4)
|
|
{
|
|
strncpy(timer.handlein, timer.handleout, 8);
|
|
timer.operation = 2; /* Set one timer */
|
|
QOLTIMER (&(timer.retcode), &(timer.reason), timer.handleout,\
|
|
timer.handlein, (char *)qname, &(timer.operation),\
|
|
&(timer.interval), &(timer.establishcount),\
|
|
&(timer.keylength), timer.keyvalue, timer.userdata);
|
|
if ((timer.retcode != 0) || (timer.reason != 0))
|
|
{
|
|
printf("%s timer failed while being canceled\n", process);
|
|
printf("Return code = %d\n", timer.retcode);
|
|
printf("Reason code = %d\n\n", timer.reason);
|
|
}
|
|
}
|
|
if (dataq->msgid != *expctid)
|
|
{
|
|
printf ("A %.4X message ID was received instead of %.4X\n",\
|
|
dataq->msgid, *expctid);
|
|
printf ("%s completion message was not received\n", process);
|
|
*expctid = dataq->msgid;
|
|
}
|
|
} /* End settimer Subroutine */
|
|
/***************************************************************/
|
|
/******* Dequeues the Incoming Message and processes it ******/
|
|
void dequeue (int length,
|
|
char *key,
|
|
qentry *dataq,
|
|
usrspace *qname)
|
|
{
|
|
char fldlen[3],
|
|
waittime[3],
|
|
keylen[2],
|
|
senderid[2],
|
|
*pointer,
|
|
order[2];
|
|
register int counter;
|
|
waittime[0] = 0;
|
|
waittime[1] = 0;
|
|
waittime[2] = 0x1D; /* Hard code a delay of infinite */
|
|
keylen[0] = 0;
|
|
keylen[1] = 0x3F; /* Hard code a keylength of 3 */
|
|
senderid[0] = 0;
|
|
senderid[1] = 0x0F;
|
|
strncpy(order, "EQ", 2);
|
|
fflush(stdin);
|
|
pointer = (char *)dataq;
|
|
for (counter = 0; counter < 336; counter++)
|
|
pointer[counter] = 0;
|
|
strncpy (dataq->type, " ", 7);
|
|
while ((strncmp(dataq->type, "*USRDFN", 7) != 0) || (fldlen == 0))
|
|
QRCVDTAQ(qname->name, qname->library, fldlen, dataq, waittime,\
|
|
order, keylen, key, senderid,"");
|
|
} /* End dequeue Subroutine */
|
|
<span class="uicontrol">(14)</span>
|
|
|
|
/************************************************************/
|
|
/** x25lind: Retrieve X.25 line description information **/
|
|
void x25lind (qlindparms *qlind, char *linename)
|
|
{
|
|
register int counter;
|
|
for(counter=0;counter<256;counter++)
|
|
qlind->userbuffer[counter]=0;
|
|
qlind->format = 0x01;
|
|
QOLQLIND (&(qlind->retcode), &(qlind->reason), &(qlind->nbytes),\
|
|
qlind->userbuffer, linename, &(qlind->format));
|
|
} /* End x25lind Subroutine */
|
|
/*******************************************************/
|
|
/** Getline: Read a record into line and return length **/
|
|
int getline (char *line, int max, FILE *fptr)
|
|
{
|
|
if (fgets(line, max, fptr) == NULL)
|
|
return 0;
|
|
else
|
|
return strlen(line);
|
|
} /* End getline Subroutine */
|
|
/***************************************************/</pre>
|
|
</div>
|
|
<div class="section" id="apiexustran__SPTCSOUR"><a name="apiexustran__SPTCSOUR"><!-- --></a><h4 class="sectiontitle">Source application program listing references</h4><p>The
|
|
following reference numbers and explanations correspond to the reference numbers
|
|
in the source application's program listing.</p>
|
|
|
|
<div class="tablenoborder"><table cellpadding="4" cellspacing="0" summary="" frame="border" border="1" rules="all"><tbody><tr><th valign="top" class="firstcol" id="d0e187">(1)</th>
|
|
<td valign="top" headers="d0e187 ">Some general C structure declarations used by both the source and target
|
|
application programs.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e192">(2)</th>
|
|
<td valign="top" headers="d0e192 ">Function prototypes of the internal functions used in this program.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e197">(3)</th>
|
|
<td valign="top" headers="d0e197 ">Call the C library routines fopen() and signal() to open the source
|
|
file and set up a signal handler to process <span class="keyword">i5/OS™</span> exceptions,
|
|
respectively. An example of an exception would be accessing a data area with
|
|
a NULL pointer. If an exception situation is encountered, SIG_DFL, the default
|
|
handler, will be called in order for the program to end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e206">(4)</th>
|
|
<td valign="top" headers="d0e206 ">Call the QOLQLIND API to retrieve local configuration information from
|
|
the iSeries server
|
|
line description about that will be used for communications. Next, call the
|
|
QOLELINK API to enable the line description using the line name and communications
|
|
handle passed as input parameters to this program.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e214">(5)</th>
|
|
<td valign="top" headers="d0e214 ">Call the QOLTIMER API to time the completion of the enable link operation.
|
|
If the timer expires before the enable-complete entry is posted on the this
|
|
program's data queue, then this program will end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e219">(6)</th>
|
|
<td valign="top" headers="d0e219 ">Call the QOLSEND API with a X'B000' operation to establish a connection
|
|
to the target application program.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e224">(7)</th>
|
|
<td valign="top" headers="d0e224 ">Monitor the source program's data queue for the call confirmation.
|
|
The source program will be notified of the call confirmation by call the QOLRECV
|
|
API and receiving a X'B001' operation in the program's input buffer.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e229">(8)</th>
|
|
<td valign="top" headers="d0e229 ">This is the main send loop for the source program. The data from the
|
|
source file is placed one line at a time in the output buffer and then the
|
|
QOLSEND API is called to send one data unit of the file to System B. This
|
|
process repeats until the contents of the entire file have been transmitted
|
|
to the target application.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e234">(9)</th>
|
|
<td valign="top" headers="d0e234 ">Call the QOLSEND API with a X'B100' operation to clear the peer connection.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e239">(10)</th>
|
|
<td valign="top" headers="d0e239 ">The source program will check its data queue for a response to the
|
|
clear packet sent to the target system. Once the response is received, the
|
|
program will clean up, call the QOLDLINK API to disable the link previously
|
|
enabled, and end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e244">(11)</th>
|
|
<td valign="top" headers="d0e244 ">The following C functions illustrate the various user-defined communications
|
|
support APIs.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e249">(12)</th>
|
|
<td valign="top" headers="d0e249 ">This procedure illustrates a call to the QOLDLINK API. Note the vary
|
|
option is set to vary off the associated iSeries server *USRDFN network device.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e257">(13)</th>
|
|
<td valign="top" headers="d0e257 ">The settimer() calls the QOLTIMER API requesting timers for 20000 milliseconds,
|
|
or twenty seconds. After setting a timer, the settimer() will call the dequeue()
|
|
to remove an entry from the program's data queue.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e262">(14)</th>
|
|
<td valign="top" headers="d0e262 ">The x25lind() illustrates calling the QOLQLIND API.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<p id="apiexustran__HDRTARGET"><a name="apiexustran__HDRTARGET"><!-- --></a><strong>Target application on System B listing</strong></p>
|
|
<p>The
|
|
target application waits for the source application to initiate the file transfer.
|
|
The following list summarizes the actions of the target application:</p>
|
|
<ul><li>Calls the QOLQLIND API to get local X.25 line information</li>
|
|
<li>Opens the local file</li>
|
|
<li>Calls the QOLELINK API to establish a link for communications</li>
|
|
<li>Calls the QOLSETF API to activate an X.25 protocol ID filter</li>
|
|
<li>Calls the QOLRECV API to receive the X'B201' operation (incoming call)</li>
|
|
<li>Calls the QOLSEND API with a X'B400' operation to accept the SVC connection</li>
|
|
<li>Receives the file from the target system using X'0001' operations</li>
|
|
<li>Calls the QOLRECV API to receive the X'B301' (connection failure notification)</li>
|
|
<li>Call the QOLSEND API with 'B100' operation to locally close the SVC connection</li>
|
|
<li>Calls the QOLDLINK API to disable the link</li>
|
|
<li>Calls the QOLTIMER API to manage the reception of data queue entries</li>
|
|
</ul>
|
|
<p>To create the program using ILE C, use the Create Bound C (CRTBNDC)
|
|
command.</p>
|
|
<p>Explanations of the reference numbers in the listing can be
|
|
found in <a href="#apiexustran__SPTCTARG">Target application program listing references</a>.</p>
|
|
<pre> Program name . . . . . . . . . :
|
|
<span class="uicontrol">(TARGET)</span>
|
|
Library name . . . . . . . . : UDCS_APPLS
|
|
Source file . . . . . . . . . . : QCSRC
|
|
Library name . . . . . . . . : UDCS_APPLS
|
|
Source member name . . . . . . : TARGET
|
|
Text Description . . . . . . . : Target Application Example
|
|
Output . . . . . . . . . . . . : *NONE
|
|
Compiler options . . . . . . . : *SOURCE *NOXREF *NOSHOWUSR
|
|
: *NOSHOWSYS *NOSHOWSKP *NOEXPMAC
|
|
: *NOAGR *NOPPONLY *NODEBUG
|
|
: *GEN *NOSECLVL *PRINT *LOGMSG
|
|
: *USRINCPATH
|
|
Checkout Options . . . . . . . : *NOAGR
|
|
Optimization . . . . . . . . . : *NONE
|
|
Inline Options:
|
|
Inliner . . . . . . . . . . . : *OFF
|
|
Mode . . . . . . . . . . . . : *NOAUTO
|
|
Threshold . . . . . . . . . . : 250
|
|
Limit . . . . . . . . . . . . : 2000
|
|
Debugging View . . . . . . . . : *NONE
|
|
Define Names . . . . . . . . . : *NONE
|
|
Language Level . . . . . . . . : *SOURCE
|
|
Source Margins:
|
|
Left margin . . . . . . . . . : 1
|
|
Right margin . . . . . . . . : 32754
|
|
Sequence columns:
|
|
Left column . . . . . . . . . : *NONE
|
|
Right column . . . . . . . . :
|
|
Message flagging level . . . . : 0
|
|
Compiler messages:
|
|
Message limit . . . . . . . . : *NOMAX
|
|
Message limit severity . . . : 30
|
|
Replace Program Object . . . . : *YES
|
|
User Profile . . . . . . . . . : *USER
|
|
Authority . . . . . . . . . . . : *LIBCRTAUT
|
|
Target Release . . . . . . . . : *CURRENT
|
|
System includes . . . . . . . . : *YES
|
|
|
|
/*******************************************************************/
|
|
/** **/
|
|
/** Program Name: Target Application Program Example **/
|
|
/** **/
|
|
/** **/
|
|
/** Function: **/
|
|
/** This is the target application program example that uses **/
|
|
/** X.25 services provided by the user-defined communications **/
|
|
/** support to receive a simple file from the source application **/
|
|
/** program running on System A. This program performs the **/
|
|
/** following: **/
|
|
/** 01. Open the target file named OUTFILE. **/
|
|
/** 02. Call QOLQLIND to obtain local line information. **/
|
|
/** 03. Enable a link. **/
|
|
/** 04. Set a Filter on the enabled link. **/
|
|
/** 05. Receive a 'B101'X operation (incoming call). **/
|
|
/** 06. Send a 'B400'X operation (accept call). **/
|
|
/** 07. Receive '0001'X operation(s) (incoming data) from **/
|
|
/** the source application program and write it to the **/
|
|
/** file opened in step 1). **/
|
|
/** 08. Receive a 'B301'X operation (clear call indication). **/
|
|
/** 09. Send a 'B100'X operation to respond locally to the **/
|
|
/** clearing of the connection. **/
|
|
/** 10. Disable the link enabled in step 3). **/
|
|
/** **/
|
|
/** A data queue will be actively used to manage the operation **/
|
|
/** of this program. Data queue support will be used to monitor **/
|
|
/** for the completion of the enable and disable routines, as **/
|
|
/** well as timer expirations and incoming data. Timers are **/
|
|
/** used to ensure that there will never be an infinite wait on **/
|
|
/** the data queue. If a timer expires, the link enabled will **/
|
|
/** be disabled and the program will stop. **/
|
|
/** **/
|
|
/** **/
|
|
/** Inputs: **/
|
|
/** The program expects the following input parameters: **/
|
|
/** Line Name: This is the name of the line description **/
|
|
/** that will be used to call the QOLELINK API. **/
|
|
/** The line must be an X.25 line with at least **/
|
|
/** one SVC of type *SVCBOTH or *SVCIN. **/
|
|
/** **/
|
|
/** CommHandle: This is the logical name that will be used **/
|
|
/** to identify the link enabled. **/
|
|
/** **/
|
|
/** Remote DTE Address: The is the Local Network Address **/
|
|
/** of system A. **/
|
|
/** **/
|
|
/** **/
|
|
/** Outputs: **/
|
|
/** Current status of the file transfer will be provided when **/
|
|
/** running this program. If an error should occur, then a **/
|
|
/** message will be displayed indicating where the error occurred **/
|
|
/** and the program will end. If the program completes **/
|
|
/** successfully, a "successful completion" message will be **/
|
|
/** posted. **/
|
|
/** **/
|
|
/** Language: ILE C **/
|
|
/** **/
|
|
/** APIs used: QOLELINK, QUSPTRUS, QOLRECV, QOLSEND, QOLDLINK, **/
|
|
/** QRCVDTAQ, QOLTIMER **/
|
|
/** **/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
#include "header"
|
|
#include "typedef"
|
|
#include "hexconv"
|
|
void senddata(sendparms *a, char *b, desc *c, char *d, char *e, int f);
|
|
void sndformat1(sendparms *a,char *b, char *c, char *d, qlindparms *e);
|
|
void sndformat2 (sendparms *a, char *b, char *c);
|
|
void setfilters (hdrparms *a);
|
|
void byte (char *a, int b, char *c, int d);
|
|
void printespec (espec *a);
|
|
void settimer(unsigned short *a,char *b,qentry *c,usrspace *d,char *e);
|
|
void dequeue (int a, char *b, qentry *c, usrspace *d);
|
|
void putdata (char *a, int b, FILE *c);
|
|
void x25lind (qlindparms *a, char *b);
|
|
void disablelink (disableparms *a, char *b, usrspace *c);
|
|
void handler (disableparms a, usrspace *b);
|
|
|
|
void _GetExcData(_INTRPT_Hndlr_Parms_T *parms);
|
|
/**********************************************************/
|
|
/*************** Start Main Program *******************/
|
|
/**********************************************************/
|
|
main (int argc, char *argv[])
|
|
{
|
|
/************ Variable Declarations *******************/
|
|
usrspace inbuff, /* Input Data Buffer */
|
|
indesc, /* Input Buffer Descriptor */
|
|
outbuff, /* Output Data Buffer */
|
|
outdesc, /* Output Buffer Descriptor */
|
|
qname; /* Data Queue */
|
|
int length, /* Data Queue key length */
|
|
inc, i, j; /* counters */
|
|
unsigned short expctid; /* Message ID that is expected */
|
|
char commhandle[10], /* Command Line Parameter */
|
|
rmtdte[17], /* Remote DTE Address */
|
|
*buffer, /* Pointer to buffer */
|
|
key[256]; /* Data Queue key identifier */
|
|
desc *descriptor; /* Pointer to buffer descriptor */
|
|
/** definitions for API functions **/
|
|
enableparms enable;
|
|
disableparms disable;
|
|
sendparms send;
|
|
recvparms recv;
|
|
setfparms setf;
|
|
timerparms timer;
|
|
qlindparms qlind;
|
|
qentry dataq;
|
|
hdrparms *header;
|
|
/****** Annndddddd.... they're off!! ***********/
|
|
<span class="uicontrol">(1)</span>
|
|
|
|
/***--- Open the file to put the received data. ----**/
|
|
if ((fptr = fopen("UDCS_APPLS/OUTFILE))", "w")) == NULL)
|
|
{
|
|
printf("Unable to open target output file in UDCS_APPLS LIB.\n");
|
|
printf("The Program was terminated.\n\n");
|
|
return;
|
|
}
|
|
/***--- Open the display file for error handling. ----**/
|
|
if ((screen = fopen("ERRORSPEC", "ab+ type = record")) == NULL)
|
|
{
|
|
printf("Unable to open display file.\n");
|
|
printf("The Program was terminated.\n\n");
|
|
return;
|
|
}
|
|
/***--- Set the Exception Handler ----**/
|
|
|
|
signal(SIGALL,SIG_DFL);
|
|
/** Clear the command line parameters **/
|
|
strncpy(enable.linename, " ", 10); /* Clear linename */
|
|
strncpy(commhandle, " ", 10); /* Clear Commhandle */
|
|
strncpy(rmtdte, " ", 17); /* Clear Remote DTE */
|
|
/** Receive command line Parameters **/
|
|
strncpy(enable.linename, argv[1], strlen(argv[1]));
|
|
strncpy(commhandle, argv[2], strlen(argv[2]));
|
|
strncpy(rmtdte, argv[3], strlen(argv[3]));
|
|
rmtdte[strlen(argv[3])] = '\0';
|
|
/** Initialize the user spaces **/
|
|
strncpy(inbuff.library, "UDCS_APPLS", 10); /* Input Buffer */
|
|
strncpy(inbuff.name, "TARGETIBUF", 10);
|
|
strncpy(indesc.library, "UDCS_APPLS", 10); /* Input B Desc */
|
|
strncpy(indesc.name, "TARGETIDSC", 10);
|
|
strncpy(outbuff.library, "UDCS_APPLS", 10); /* Output Buffer*/
|
|
strncpy(outbuff.name, "TARGETOBUF", 10);
|
|
strncpy(outdesc.library, "UDCS_APPLS", 10); /* Output B Desc */
|
|
strncpy(outdesc.name, "TARGETODSC", 10);
|
|
strncpy(qname.library, "UDCS_APPLS", 10); /* Data queue */
|
|
strncpy(qname.name, "X25DTAQ ", 10);
|
|
/***** retrieve the line description information ******/
|
|
x25lind (&qlind, enable.linename);
|
|
if ((qlind.retcode != 0) || (qlind.reason != 0))
|
|
{
|
|
printf("Query line description failed.\n");
|
|
printf("Return code = %d\n", qlind.retcode);
|
|
printf("Reason code = %d\n\n", qlind.reason);
|
|
return;
|
|
}
|
|
/***** Hard Code the QOLELINK Input Parameters ******/
|
|
enable.maxdtax25 = 512;
|
|
enable.keylength = 3;
|
|
strncpy(enable.keyvalue, "RCV", 3);
|
|
<span class="uicontrol">(2)</span>
|
|
|
|
/**------- Enable the link -----------**/
|
|
QOLELINK (&(enable.retcode), &(enable.reason), &(enable.tdusize),\
|
|
&(enable.numunits), &(enable.maxdtalan), &(enable.maxdtax25),\
|
|
(char *)&inbuff, (char *)&indesc, (char *)&outbuff,\
|
|
(char *)&outdesc, &(enable.keylength), enable.keyvalue,\
|
|
(char *)&qname, enable.linename, commhandle);
|
|
if ((enable.retcode != 0) || (enable.reason != 0))
|
|
{
|
|
printf("Line %.10s with Commhandle %.10s was NOT ENABLED.\n",\
|
|
enable.linename, commhandle);
|
|
printf("Return code = %d\n", enable.retcode);
|
|
printf("Reason code = %d\n\n", enable.reason);
|
|
return;
|
|
}
|
|
<span class="uicontrol">(3)</span>
|
|
|
|
/**------- Set a timer for Enable link --------**/
|
|
expctid = 0xF0F0;
|
|
settimer(&expctid, "Enable", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F0)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/*************************************************************/
|
|
/*******---- Set a Filter for the Link --------*********/
|
|
/*************************************************************/
|
|
<span class="uicontrol">(4)</span>
|
|
|
|
QUSPTRUS(&outbuff, &header); /* get the output buffer pointer */
|
|
header->function = 1; /* add a filter */
|
|
header->type = 0; /* X.25 PID only */
|
|
header->number = 1; /* set 1 filter */
|
|
header->length = 16; /* X.25 filter length */
|
|
setfilters(header); /* Fill in the filter format */
|
|
/*******---- Set the filter for the Link --------*********/
|
|
QOLSETF (&(setf.retcode), &(setf.reason), &(setf.erroffset),\
|
|
commhandle);
|
|
if ((setf.retcode != 0) || (setf.reason != 0))
|
|
{
|
|
printf("Set Filters Return Code = %.2d\n", setf.retcode);
|
|
printf("Set Filters Reason Codes = %.4d\n", setf.reason);
|
|
printf("Set Filters Error Offset = %.4d\n", setf.erroffset);
|
|
return;
|
|
}
|
|
/*************************************************************/
|
|
/**** Receive the incoming call packet and accept the call **/
|
|
/*************************************************************/
|
|
/**------- Set a timer to receive data --------**/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Inc Call ", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
<span class="uicontrol">(5)</span>
|
|
|
|
/********** Receive the Incoming Data **********/
|
|
QUSPTRUS (&inbuff, &buffer);
|
|
QUSPTRUS (&indesc, &descriptor);
|
|
QOLRECV (&(recv.retcode), &(recv.reason), &(recv.ucep),\
|
|
&(recv.pcep), &(recv.operation), &(recv.numdtaunits),\
|
|
&(recv.dataavail), &(recv.errorspecific), commhandle);
|
|
if ((recv.retcode != 0) || (recv.reason != 0))
|
|
{
|
|
printf("Recv incoming call packet failed\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/*** Interpret the Received Operation ***/
|
|
if (recv.operation != 0xB201)
|
|
{
|
|
printf("Recvd operation %x instead of B201", recv.operation);
|
|
disablelink (&disable, commhandle, &qname);
|
|
return; /**** End the program ***/
|
|
}
|
|
<span class="uicontrol">(6)</span>
|
|
|
|
/******************************************************************/
|
|
/** Send a response to accept the call and establish a connection */
|
|
/******************************************************************/
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS(&outbuff, &buffer);
|
|
QUSPTRUS(&outdesc, &descriptor);
|
|
/******* Set up Send Packet *********/
|
|
send.ucep = 62; /* set UCEP to be 62 */
|
|
send.pcep = recv.pcep; /* get the PCEP number */
|
|
send.operation = 0xB400; /* send a call request response*/
|
|
send.numdtaelmnts = 1; /* send one data unit */
|
|
/**----- Send the packet ----------------**/
|
|
sndformat1 (&send, buffer, rmtdte, commhandle, &qlind);
|
|
if ((send.retcode != 0) || (send.reason != 0))
|
|
{
|
|
printf("Data NOT sent for commhandle %.9s\n", commhandle);
|
|
printf("Return code = %d\n", send.retcode);
|
|
printf("Reason code = %d\n", send.reason);
|
|
printf("new pcep %d\n\n", send.newpcep);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
printf("An X.25 SVC connection was completed\n\n");
|
|
|
|
<span class="uicontrol">(7)</span>
|
|
|
|
/**********************************************************/
|
|
/**** Receive Incoming Data *************************/
|
|
/**********************************************************/
|
|
/**------- Set a timer to receive data --------**/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Inc Data ", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/*******--- Receive the Incoming Data ----******/
|
|
/** Get pointer to user space **/
|
|
QUSPTRUS (&inbuff, &buffer);
|
|
QUSPTRUS (&indesc, &descriptor);
|
|
/** Receive the data **/
|
|
QOLRECV (&(recv.retcode), &(recv.reason), &(recv.ucep),\
|
|
&(recv.pcep), &(recv.operation), &(recv.numdtaunits),\
|
|
&(recv.dataavail), &(recv.errorspecific), commhandle);
|
|
if ((recv.retcode != 0) || (recv.reason != 0))
|
|
{
|
|
printf("Recv op for first data unit failed\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(8)</span>
|
|
|
|
/**************************************************************/
|
|
/******* Start a loop to read in all the incoming data ***/
|
|
/**************************************************************/
|
|
i = 1;
|
|
while (recv.operation == 0x0001)
|
|
{
|
|
printf("%d Data Recvd {%.4x}.\n\n", i++, recv.operation);
|
|
/** Store all the data units in the file **/
|
|
for (j = 1; j <= recv.numdtaunits; j++) {
|
|
putdata (buffer + (j - 1)*enable.tdusize,\
|
|
descriptor->length, fptr);
|
|
descriptor = (desc *)((char *)descriptor + sizeof(desc));
|
|
} /* for */
|
|
/**------- Set a timer to wait for more data -------**/
|
|
if (recv.dataavail == 0)
|
|
{
|
|
/** Set timer **/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Wt Inc Dta", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
}
|
|
/** Get pointer to user space **/
|
|
QUSPTRUS (&inbuff, &buffer);
|
|
QUSPTRUS (&indesc, &descriptor);
|
|
/** Receive the data **/
|
|
QOLRECV (&(recv.retcode), &(recv.reason), &(recv.ucep),\
|
|
&(recv.pcep), &(recv.operation), &(recv.numdtaunits),\
|
|
&(recv.dataavail), &(recv.errorspecific), commhandle);
|
|
} /** End Receive data while loop ******/
|
|
|
|
<span class="uicontrol">(9)</span>
|
|
|
|
/****************************************************/
|
|
/*********** Receive the Clear indication ***********/
|
|
/****************************************************/
|
|
if ((recv.retcode != 83) || (recv.reason != 4002))
|
|
{
|
|
printf("Recv opr for clear request failed\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/* Interpret the Received Operation */
|
|
if (recv.operation != 0xB301)
|
|
{
|
|
printf("Recvd operation %x instead of B301", recv.operation);
|
|
disablelink (&disable, commhandle, &qname);
|
|
return; /**** end the program ***/
|
|
}
|
|
|
|
<span class="uicontrol">(10)</span>
|
|
|
|
/****************************************************************/
|
|
/*********** Send local response to clear indication ***********/
|
|
/****************************************************************/
|
|
/**** Get pointers to the user spaces. ******/
|
|
QUSPTRUS(&outbuff, &buffer);
|
|
QUSPTRUS(&outdesc, &descriptor);
|
|
/******* Set up the packet ****************/
|
|
send.operation = 0xB100; /* send a clear request packet */
|
|
send.numdtaelmnts = 1; /* send one data unit */
|
|
/**----- Send the packet ----------------**/
|
|
sndformat2 (&send, buffer, commhandle);
|
|
if ((send.retcode != 0) && (send.reason != 0))
|
|
{
|
|
printf("Response not sent for clear connection\n");
|
|
printf("Return code = %d\n", send.retcode);
|
|
printf("Reason code = %d\n", send.reason);
|
|
printf("new pcep %d\n\n", send.newpcep);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/******************************************************/
|
|
/*********** Receive the Clear Confirmation **********/
|
|
/******************************************************/
|
|
/**------- Set a timer to receive data --------**/
|
|
expctid = 0xF0F3;
|
|
settimer(&expctid, "Clr Cnfrm", &dataq, &qname, commhandle);
|
|
if (expctid != 0xF0F3)
|
|
{
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
if ((recv.retcode != 00) || (recv.reason != 0000))
|
|
{
|
|
printf("Recv failed for clear confirmation\n");
|
|
printf("return code %d\n", recv.retcode);
|
|
printf("reason code %d\n", recv.reason);
|
|
printespec(&(send.errorspecific));
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
/* Interpret the Received Operation */
|
|
if (recv.operation != 0xB101)
|
|
{
|
|
printf("Recvd opr %x instead of opr B301\n", recv.operation);
|
|
disablelink (&disable, commhandle, &qname);
|
|
return;
|
|
}
|
|
|
|
<span class="uicontrol">(11)</span>
|
|
|
|
/****************************************/
|
|
/** disable the link and end program **/
|
|
/****************************************/
|
|
disablelink (&disable, commhandle, &qname);
|
|
printf("TARGET application completed OK!\n\n");
|
|
} /* End Main */
|
|
/*****************************************************************/
|
|
/************** Start Subroutine Section **********************/
|
|
/*****************************************************************/
|
|
/*****************************************************************/
|
|
/************ Routine to fill X.25 Format I ***********/
|
|
void sndformat1 (sendparms *send,
|
|
char *buffer,
|
|
char *rmtdte,
|
|
char *commhandle,
|
|
qlindparms *qlind)
|
|
{
|
|
format1 *output = (format1 *) buffer;
|
|
register int counter;
|
|
register querydata *qd;
|
|
qd = (querydata *)&(qlind->userbuffer);
|
|
output->type = 0; /* not used */
|
|
output->logchanid = 0x0;
|
|
output->sendpacksize = qd->x25data.defsend;
|
|
output->sendwindsize = qd->x25data.windowsend;
|
|
output->recvpacksize = qd->x25data.defrecv;
|
|
output->recvwindsize = qd->x25data.windowrecv;
|
|
output->dtelength = strlen(rmtdte); /* not used */
|
|
byte(output->dte, 16, rmtdte, strlen(rmtdte)); /* not used */
|
|
output->dbit = 0;
|
|
output->cug = 0; /* not used */
|
|
output->cugid = 0; /* not used */
|
|
output->reverse = 0; /* not used */
|
|
output->fast = 0; /* not used */
|
|
output->faclength = 0;
|
|
byte(output->facilities, 109, "", 0);
|
|
output->calllength = 0;
|
|
byte(output->callud, 128, "00", 2);
|
|
output->misc[0] = 0;
|
|
output->misc[1] = 0;
|
|
output->misc[2] = 0;
|
|
output->misc[3] = 0;
|
|
output->maxasmsize = 16383;
|
|
output->autoflow = 32;
|
|
QOLSEND (&(send->retcode), &(send->reason),
|
|
&(send->errorspecific),\
|
|
&(send->newpcep), &(send->ucep), &(send->pcep),\
|
|
commhandle, &(send->operation), &(send->numdtaelmnts));
|
|
} /* End sndformat1 Subroutine */
|
|
/*****************************************************************/
|
|
/************ Routine to fill X.25 Format II ***********/
|
|
void sndformat2 (sendparms *send,
|
|
char *buffer,
|
|
char *commhandle)
|
|
{
|
|
format2 *output = (format2 *) buffer;
|
|
output->type = 1;
|
|
output->cause = 'FF';
|
|
output->diagnostic = 'FF';
|
|
output->faclength = 0;
|
|
byte(output->facilities, 109, "", 0);
|
|
output->length = 0;
|
|
byte(output->userdata, 128, "", 0);
|
|
QOLSEND (&(send->retcode), &(send->reason),
|
|
&(send->errorspecific),\
|
|
&(send->newpcep), &(send->ucep), &(send->pcep),\
|
|
commhandle, &(send->operation), &(send->numdtaelmnts));
|
|
} /* End sndformat2 Subroutine */
|
|
/********************************************************************/
|
|
/************** Fill in the Buffer for the Filter ****************/
|
|
void setfilters (hdrparms *header)
|
|
{
|
|
x25filter *filters;
|
|
filters = (x25filter *)header->filters;
|
|
filters[0].pidlength = 1;
|
|
filters[0].pid = 0x21; /* set the protocol ID */
|
|
filters[0].dtelength = 0; /* no DTE used in filter */
|
|
byte(filters[0].dte, 12, "", 0);
|
|
filters[0].flags = 0x0;
|
|
filters[0].flags += 0x80; /* Set Reverse Charging to no */
|
|
filters[0].flags += 0x40; /* Set Fast Select to no */
|
|
} /* End setfilters Subroutine */
|
|
/********************************************/
|
|
/******** Routine to disable ***********/
|
|
void disablelink (disableparms *disable,
|
|
char *commhandle,
|
|
usrspace *qname)
|
|
{
|
|
qentry dataq;
|
|
unsigned short expctid;
|
|
disable->vary = 1; /* Hard code device to vary off */
|
|
/** Call disable link **/
|
|
QOLDLINK (&(disable->retcode), &(disable->reason),\
|
|
commhandle, &(disable->vary));
|
|
if ((disable->retcode != 0) && (disable->reason != 00))
|
|
{
|
|
printf ("Link %.10s did not disabled.\n", commhandle);
|
|
printf ("return code = %d\n", disable->retcode);
|
|
printf ("reason code = %d\n\n", disable->reason);
|
|
}
|
|
else
|
|
printf ("%.10s link disabled \n", commhandle);
|
|
/**------- Set a timer to receive message --------**/
|
|
expctid = 0xF0F1;
|
|
settimer(&expctid, "Disable ", &dataq, qname, commhandle);
|
|
if (expctid != 0xF0F1)
|
|
{
|
|
printf("Disable link did not complete successfully");
|
|
return;
|
|
}
|
|
/** close the files **/
|
|
fclose(fptr);
|
|
fclose(screen);
|
|
} /* End disablelink Subroutine */
|
|
/**************************************************************/
|
|
/** Routine to convert string to Hexadecimal format ******/
|
|
void byte (char *dest,
|
|
int dlength,
|
|
char *source,
|
|
int slength)
|
|
{
|
|
register int counter;
|
|
char holder[2];
|
|
for (counter=0;counter<dlength;counter++)
|
|
dest[counter]=0;
|
|
for (counter=slength-1;counter>=0;counter--)
|
|
if isxdigit(source[counter])
|
|
{
|
|
holder[0]=source[counter];
|
|
holder[1]='\0';
|
|
if (counter % 2 == 0)
|
|
dest[counter/2] += (char) hextoint(holder)*16;
|
|
else dest[counter/2] += (char) hextoint(holder);
|
|
}
|
|
} /* End byte Subroutine */
|
|
/**************************************************************/
|
|
/** Routine to display the ErrorSpecific output ******/
|
|
/**************************************************************/
|
|
void printespec(espec *errorspecific)
|
|
{
|
|
especout outparms;
|
|
|
|
sprintf(outparms.hwecode, "%.8X", errorspecific->hwecode);
|
|
sprintf(outparms.timestamp, "%.8X%.8X", errorspecific->timestamphi,\
|
|
errorspecific->timestamplo);
|
|
sprintf(outparms.elogid, "%.8X", errorspecific->elogid);
|
|
if (errorspecific->flags & 0x40)
|
|
outparms.fail = 'Y';
|
|
else outparms.fail = 'N';
|
|
if (errorspecific->flags & 0x20)
|
|
outparms.zerocodes = 'Y';
|
|
else outparms.zerocodes = 'N';
|
|
if (errorspecific->flags & 0x10)
|
|
outparms.qsysopr = 'Y';
|
|
else outparms.qsysopr = 'N';
|
|
sprintf(outparms.cause,"%.2X", errorspecific->cause);
|
|
sprintf(outparms.diagnostic, "%.2X", errorspecific->diagnostic);
|
|
sprintf(outparms.erroffset, "%.6d", errorspecific->erroroffset);
|
|
fwrite(&outparms, 1, sizeof(especout), screen);
|
|
fread("", 0, 0, screen);
|
|
} /* End printespec Subroutine */
|
|
/***************************************************************/
|
|
/******* Dequeues the Incoming Message and processes it ******/
|
|
void dequeue (int length,
|
|
char *key,
|
|
qentry *dataq,
|
|
usrspace *qname)
|
|
{
|
|
char fldlen[3],
|
|
waittime[3],
|
|
keylen[2],
|
|
senderid[2],
|
|
*pointer,
|
|
order[2];
|
|
register int counter;
|
|
waittime[0] = 0;
|
|
waittime[1] = 0;
|
|
waittime[2] = 0x1D; /* Hard code a delay of infinite */
|
|
keylen[0] = 0;
|
|
keylen[1] = 0x3F; /* Hard code a keylength of 3 */
|
|
senderid[0] = 0;
|
|
senderid[1] = 0x0F;
|
|
strncpy(order, "EQ", 2);
|
|
/* Clear the data structures **/
|
|
fflush(stdin);
|
|
pointer = (char *)dataq;
|
|
for (counter = 0; counter < 336; counter++)
|
|
pointer[counter] = 0;
|
|
strncpy (dataq->type, " ", 7);
|
|
while ((strncmp(dataq->type, "*USRDFN", 7) != 0) || (fldlen == 0))
|
|
QRCVDTAQ(qname->name, qname->library, fldlen, dataq, waittime,\
|
|
order, keylen, key, senderid,"");
|
|
} /* End dequeue Subroutine */
|
|
/**********************************************************/
|
|
/************* Set a timer and dequeue next entry ******/
|
|
void settimer (unsigned short *expctid,
|
|
char *process,
|
|
qentry *dataq,
|
|
usrspace *qname,
|
|
char *commhandle)
|
|
{
|
|
timerparms timer;
|
|
disableparms disable;
|
|
int length;
|
|
char key[6];
|
|
timer.interval = 20000; /* set timer for 20 seconds */
|
|
timer.establishcount = 1; /* set establish count to 1 */
|
|
timer.keylength = 3; /* key value */
|
|
strncpy(timer.keyvalue, "TGT", 3); /* set key value /
|
|
timer.operation = 1; /* set a timer */
|
|
/* Call QOLTIMER */
|
|
QOLTIMER (&(timer.retcode), &(timer.reason), timer.handleout,\
|
|
timer.handlein, (char *)qname, &(timer.operation),\
|
|
&(timer.interval), &(timer.establishcount),\
|
|
&(timer.keylength), timer.keyvalue, timer.userdata);
|
|
if ((timer.retcode != 0) || (timer.reason != 0))
|
|
{
|
|
printf("%s timer failed while being set.\n", process);
|
|
printf("Return code = %d\n", timer.retcode);
|
|
printf("Reason code = %d\n\n", timer.reason);
|
|
}
|
|
/**------- Dequeue an entry --------**/
|
|
strncpy(key, "TGT", 3);
|
|
length = 3;
|
|
dequeue (length, key, dataq, qname);
|
|
/***---- Cancel timer -----***/
|
|
if (dataq->msgid != 0xF0F4)
|
|
{
|
|
strncpy(timer.handlein, timer.handleout, 8);
|
|
timer.operation = 2; /* Cancel one timer */
|
|
QOLTIMER (&(timer.retcode), &(timer.reason), timer.handleout,\
|
|
timer.handlein, (char *)qname, &(timer.operation),\
|
|
&(timer.interval), &(timer.establishcount),\
|
|
&(timer.keylength), timer.keyvalue, timer.userdata);
|
|
if ((timer.retcode != 0) || (timer.reason != 0))
|
|
{
|
|
printf("%s timer failed while being canceled\n", process);
|
|
printf("Return code = %d\n", timer.retcode);
|
|
printf("Reason code = %d\n\n", timer.reason);
|
|
}
|
|
}
|
|
if (dataq->msgid != *expctid)
|
|
{
|
|
printf ("A %.4X message ID was received instead of %.4X\n",\
|
|
dataq->msgid, *expctid);
|
|
printf ("%s completion message was not received\n", process);
|
|
*expctid = dataq->msgid;
|
|
}
|
|
} /* End settimer Subroutine */
|
|
/************************************************************/
|
|
/** x25lind: Read a record into buf and return length **/
|
|
void x25lind (qlindparms *qlind, char *linename)
|
|
{
|
|
register int counter;
|
|
for(counter=0;counter<256;counter++)
|
|
qlind->userbuffer[counter]=0;
|
|
qlind->format = 0x01;
|
|
QOLQLIND (&(qlind->retcode), &(qlind->reason), &(qlind->nbytes),\
|
|
qlind->userbuffer, linename, &(qlind->format));
|
|
} /* End x25lind Subroutine */
|
|
/************************************************************/
|
|
/** putdata: Read a record into buf and return length **/
|
|
void putdata (char *buf,
|
|
int dtalen,
|
|
FILE *fptr)
|
|
{
|
|
int i;
|
|
for (i = 0; i < dtalen; i++)
|
|
fwrite(buf + i, 1, 1, fptr);
|
|
} /* End putdata Subroutine */</pre>
|
|
</div>
|
|
<div class="section" id="apiexustran__SPTCTARG"><a name="apiexustran__SPTCTARG"><!-- --></a><h4 class="sectiontitle">Target application program listing references</h4><p>The
|
|
following reference numbers and explanations correspond to the reference numbers
|
|
in the target application's program listing.</p>
|
|
|
|
<div class="tablenoborder"><table cellpadding="4" cellspacing="0" summary="" frame="border" border="1" rules="all"><tbody><tr><th valign="top" class="firstcol" id="d0e350">(1)</th>
|
|
<td valign="top" headers="d0e350 ">Call the C library routines fopen() and signal() to open the target
|
|
file and set up a signal handler to process <span class="keyword">i5/OS</span> exceptions,
|
|
respectively. If an exception situation is encountered, the handler() will
|
|
be called to perform clean-up in order for the program to end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e359">(2)</th>
|
|
<td valign="top" headers="d0e359 ">Call the QOLELINK API to enable the line description using the line
|
|
name and communications handle passed as input parameters to this program.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e364">(3)</th>
|
|
<td valign="top" headers="d0e364 ">Call the QOLTIMER API to time the completion of the enable link operation.
|
|
If the timer expires before the enable-complete message is posted on the this
|
|
program's data queue, then this program will end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e369">(4)</th>
|
|
<td valign="top" headers="d0e369 ">Call the QUSPTRUS API to obtain a pointer to the beginning of the output
|
|
buffer user space. The output buffer will be used to construct a filter list
|
|
for the call to the QOLSETF API.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e374">(5)</th>
|
|
<td valign="top" headers="d0e374 ">Call the QOLRECV API to receive inbound data after reading an incoming
|
|
data message that was posted on the program's data queue by the user-defined
|
|
communications support. Since these programs are operating using the communications
|
|
services of X.25, the first data unit the target program should see is a X'B201'
|
|
operation signalling an incoming call was received.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e379">(6)</th>
|
|
<td valign="top" headers="d0e379 ">Call the QOLSEND API with a X'B400' operation to accept the incoming
|
|
X.25 call. A connection is now established between the source and target application
|
|
programs.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e384">(7)</th>
|
|
<td valign="top" headers="d0e384 ">The target program will now set a timer by calling the QOLTIMER API
|
|
and wait for incoming data. If the timer expires before any incoming data
|
|
is received, then this program will call the QOLDLINK API, and end.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e389">(8)</th>
|
|
<td valign="top" headers="d0e389 ">This is the main receive loop for the target program. When data is
|
|
received from the source program, it will be written to the target file opened
|
|
during the initialization of this program. The loop will process until a message
|
|
other than incoming-data entry is read from the program's data queue.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e394">(9)</th>
|
|
<td valign="top" headers="d0e394 ">Call the QOLSEND API with a X'B001' operation to locally close the
|
|
connection.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e399">(10)</th>
|
|
<td valign="top" headers="d0e399 ">Receives a X'B101' operation from the user-defined communications support.
|
|
This is a local confirmation of X'B100' operation.</td>
|
|
</tr>
|
|
<tr><th valign="top" class="firstcol" id="d0e404">(11)</th>
|
|
<td valign="top" headers="d0e404 ">Call the QOLDLINK API to disable the link previously enabled and end.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<p id="apiexustran__Header_47"><a name="apiexustran__Header_47"><!-- --></a><strong>Includes for source and target programs</strong></p>
|
|
<p>The
|
|
following three includes are used by both the preceding source and target
|
|
programs. They are not in an <span class="keyword">i5/OS</span> library.</p>
|
|
<pre>/*******************************************************************/
|
|
/*******************************************************************/
|
|
/* Include Name: Header */
|
|
/* */
|
|
/* */
|
|
/* Function: */
|
|
/* Type define and declare the structures used to interface */
|
|
/* to the user-defined communications APIs. These structures */
|
|
/* are used by both the source and target application. */
|
|
/* */
|
|
/* */
|
|
/* LANGUAGE: ILE C */
|
|
/* */
|
|
/* APIs USED: QOLDLINK, QOLELINK, QOLSEND, QOLRECV, QOLSETF, */
|
|
/* QOLTIMER, QUSPTRUS, QRCVDTAQ, QCLRDTAQ, QOLQLIND */
|
|
/* */
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
|
|
FILE *screen;
|
|
FILE *rptr;
|
|
FILE *fptr;
|
|
|
|
#include <qoldlink.h>
|
|
#include <qolelink.h>
|
|
#include <qolsend.h>
|
|
#include <qolrecv.h>
|
|
#include <qolsetf.h>
|
|
#include <qoltimer.h>
|
|
#include <qusptrus.h>
|
|
#include <qrcvdtaq.h>
|
|
#include <qclrdtaq.h>
|
|
#include <qolqlind.h>
|
|
|
|
/************ Typedef Declarations *******************/
|
|
|
|
typedef struct usrspace
|
|
{
|
|
char name[10];
|
|
char library[10];
|
|
} usrspace;
|
|
|
|
typedef struct enableparms /* Enable parameters */
|
|
{
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
tdusize, /* Output */
|
|
numunits, /* Output */
|
|
maxdtalan, /* Output */
|
|
maxdtax25, /* Input */
|
|
keylength; /* Input */
|
|
char keyvalue[256], /* Input */
|
|
linename[10]; /* Input */
|
|
} enableparms;
|
|
|
|
typedef struct disableparms /* Disable parameters */
|
|
{
|
|
int retcode, /* Output */
|
|
reason; /* Output */
|
|
char vary; /* Input */
|
|
} disableparms;
|
|
|
|
typedef struct setfparms /* Set Filters parameters */
|
|
{
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
erroffset; /* Output */
|
|
} setfparms;
|
|
|
|
typedef _Packed struct hdrparms /* Filter header */
|
|
{
|
|
char function;
|
|
char type;
|
|
unsigned short number;
|
|
unsigned short length;
|
|
char filters[1];
|
|
} hdrparms;
|
|
|
|
typedef _Packed struct x25filter /* X.25 filter */
|
|
{
|
|
char pidlength;
|
|
char pid;
|
|
char dtelength;
|
|
char dte[12];
|
|
char flags;
|
|
} x25filter;
|
|
|
|
typedef struct sendparms /* Send parameters */
|
|
{
|
|
espec errorspecific; /* Output */
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
newpcep, /* Output */
|
|
ucep, /* Input */
|
|
pcep, /* Input */
|
|
numdtaelmnts; /* Input */
|
|
unsigned short operation; /* Input */
|
|
} sendparms;
|
|
|
|
typedef struct recvparms /* Receive parameters */
|
|
{
|
|
espec errorspecific; /* Output */
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
newpcep, /* Output */
|
|
ucep, /* Output */
|
|
pcep, /* Output */
|
|
numdtaunits; /* Output */
|
|
char dataavail; /* Output */
|
|
unsigned short operation; /* Output */
|
|
} recvparms;
|
|
|
|
typedef struct timerparms /* Timer parameters */
|
|
{
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
interval, /* Input */
|
|
establishcount, /* Input */
|
|
keylength; /* Input */
|
|
char handleout[8], /* Output */
|
|
handlein[8], /* Input */
|
|
operation, /* Input */
|
|
keyvalue[256], /* Input */
|
|
userdata[60]; /* Input */
|
|
} timerparms;
|
|
|
|
|
|
typedef struct especout
|
|
{
|
|
char hwecode[8];
|
|
char timestamp[16];
|
|
char elogid[8];
|
|
char fail;
|
|
char zerocodes;
|
|
char qsysopr;
|
|
char cause[2];
|
|
char diagnostic[2];
|
|
char erroffset[6];
|
|
} especout;
|
|
|
|
typedef struct qlindparms /* Query line parameters */
|
|
{
|
|
int retcode, /* Output */
|
|
reason, /* Output */
|
|
nbytes; /* Output */
|
|
char userbuffer[256];
|
|
char format;
|
|
} qlindparms;
|
|
|
|
typedef _Packed union content /* Queue support parameters */
|
|
{
|
|
_Packed struct other
|
|
{
|
|
char commhandle[10];
|
|
char reserved[58];
|
|
} other;
|
|
_Packed struct enable
|
|
{
|
|
char commhandle[10];
|
|
char status;
|
|
char reserved[57];
|
|
} enable;
|
|
_Packed struct timer
|
|
{
|
|
char timerhandle[8];
|
|
char userdata[60];
|
|
} timer;
|
|
} content;
|
|
|
|
typedef _Packed struct qentry /* Queue parameters */
|
|
{
|
|
char type[10];
|
|
unsigned short msgid;
|
|
content message;
|
|
char key[256];
|
|
} qentry;
|
|
</pre>
|
|
<p>The following typedef include has new type declarations used
|
|
by both source and target programs.</p>
|
|
<pre>/*******************************************************************/
|
|
/*******************************************************************/
|
|
/* Include Name: Typedef */
|
|
/* */
|
|
/* Function: */
|
|
/* Define the buffer spaces used to pass the data to the */
|
|
/* APIs. */
|
|
/* */
|
|
/* */
|
|
/* LANGUAGE: ILE C */
|
|
/* */
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
/*These definitions and C library #include files are either global, or
|
|
are used by multiple modules in the Open FM API driver.*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <xxcvt.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <recio.h>
|
|
|
|
typedef struct queuein
|
|
{
|
|
char library[10];
|
|
char name[10];
|
|
char option;
|
|
} queuein;
|
|
|
|
typedef struct namelib
|
|
{
|
|
char library[10];
|
|
char name[10];
|
|
} namelib;
|
|
|
|
typedef _Packed struct format1
|
|
{
|
|
char type;
|
|
char reserved1;
|
|
unsigned short logchanid;
|
|
unsigned short sendpacksize;
|
|
unsigned short sendwindsize;
|
|
unsigned short recvpacksize;
|
|
unsigned short recvwindsize;
|
|
char reserved2[7];
|
|
char dtelength;
|
|
char dte[16];
|
|
char reserved3[8];
|
|
char dbit;
|
|
char reserved4[7];
|
|
char cug;
|
|
char cugid;
|
|
char reverse;
|
|
char fast;
|
|
char faclength;
|
|
char facilities[109];
|
|
char reserved5[48];
|
|
unsigned short calllength;
|
|
char callud[128];
|
|
char reserved6[128];
|
|
unsigned char misc[4]; /* control flags */
|
|
unsigned int maxasmsize;
|
|
unsigned short autoflow;
|
|
} format1;
|
|
|
|
typedef _Packed struct format2
|
|
{
|
|
unsigned short type;
|
|
char cause;
|
|
char diagnostic;
|
|
char reserved[4];
|
|
char faclength;
|
|
char facilities[109];
|
|
char reserved2[48];
|
|
unsigned short length;
|
|
char userdata[128];
|
|
} format2;
|
|
|
|
typedef _Packed struct desc
|
|
{
|
|
unsigned short length;
|
|
char more; /*These 4 char's are only used for X.25.*/
|
|
char qualified;
|
|
char interrupt;
|
|
char dbit;
|
|
char reserved[26];
|
|
} desc;
|
|
|
|
typedef _Packed struct llcheader
|
|
{
|
|
unsigned short headerlength;
|
|
char macaddr[6];
|
|
char dsap;
|
|
char ssap;
|
|
char priority;
|
|
char priorctl;
|
|
unsigned short routlen;
|
|
unsigned short userdtalen;
|
|
char data[1];
|
|
} llcheader;
|
|
|
|
typedef _Packed struct espec
|
|
{
|
|
char reserved[2];
|
|
unsigned int hwecode;
|
|
unsigned int timestamphi;
|
|
unsigned int timestamplo;
|
|
unsigned int elogid;
|
|
char reserved2[10];
|
|
char flags;
|
|
char cause;
|
|
char diagnostic;
|
|
char reserved3;
|
|
unsigned int erroroffset;
|
|
char reserved4[4];
|
|
} espec;
|
|
|
|
typedef struct tableentry
|
|
{
|
|
char handle[10];
|
|
char type;
|
|
char inbuff[20];
|
|
char indesc[20];
|
|
char outbuff[20];
|
|
char outdesc[20];
|
|
unsigned int totaldusize;
|
|
struct tableentry *next;
|
|
} tableentry;
|
|
|
|
/******* Data structure for X.25 line ********/
|
|
/******* descriptions as returned by QOLQLIND. ******/
|
|
|
|
typedef struct x25info
|
|
{
|
|
char addrlen;
|
|
char addr[9];
|
|
char addrtype;
|
|
char insert;
|
|
char modulus;
|
|
char dtedce;
|
|
unsigned short maxsend;
|
|
unsigned short maxrecv;
|
|
unsigned short defsend;
|
|
unsigned short defrecv;
|
|
char windowsend;
|
|
char windowrecv;
|
|
unsigned short numlc;
|
|
char lcinfo[4];
|
|
} x25info;
|
|
|
|
typedef struct querydata
|
|
{
|
|
char header[12]; /* line header info */
|
|
x25info x25data; /* preliminary data */
|
|
} querydata;</pre>
|
|
<pre>/*******************************************************************/
|
|
/*******************************************************************/
|
|
/* Include Name: Hexconv */
|
|
/* */
|
|
/* Function: */
|
|
/* This include brings in procedures to convert hexadecimal */
|
|
/* to integer values and vice versa. */
|
|
/* */
|
|
/* */
|
|
/* LANGUAGE: ILE C */
|
|
/* */
|
|
/*******************************************************************/
|
|
/*******************************************************************/
|
|
#include <stdio.h>
|
|
|
|
unsigned int hextoint(char *);
|
|
|
|
char *inttohex(decimal,hex) /*Converts a 4-byte integer into a
|
|
string of 2 uppercase hex characters.*/
|
|
unsigned int decimal;
|
|
char *hex;
|
|
|
|
{
|
|
sprintf(hex,"%.2X",decimal);
|
|
return(hex);
|
|
}
|
|
|
|
unsigned int hextoint(hex) /*Converts a string containing hex
|
|
digits into a 4-byte integer. */
|
|
char *hex;
|
|
{
|
|
int decimal;
|
|
|
|
sscanf(hex,"%x",&decimal);
|
|
return(decimal);
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="familylinks">
|
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="apiexmp.htm" title="Contains example programs that use APIs and exit programs.">Examples: APIs</a></div>
|
|
</div>
|
|
<div class="relref"><strong>Related reference</strong><br />
|
|
<div><a href="../apis/qolsetf.htm">Set Filter (QOLSETF) API</a></div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |