26
Tue, Nov
0 New Articles

Programming with the CPI-C API

APIs
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

The Common Programming Interface-Communications (CPI-C) provides a way for applications to communicate and exchange data across multiple platforms and operating systems. It allows programmers to create elegant client/server applications using PCs and AS/400s. The CPI-C API provides a standard set of function calls for getting session information, establishing communications, sending and receiving data, and confirming receipt of the data. It can be used from almost any SNA platform and may be used with several programming languages as well. The beauty of the CPI-C API is the ease of establishing communication with it; it can take as few as six function calls to begin the communication session. This article will provide an introduction to CPI-C programming by looking at one of the simplest CPI-C programs, APING.

Before looking at the program, we should look at some of the details of how a CPIC session is established. At its simplest level, a CPI-C session is merely a conversation between two transaction programs (TPs). In the example shown in Figure 1, a TP is started on the server and awaits a connection request from a client. The TP on the client then allocates a session and begins the transfer of data between the two TPs. The TP on the client is known as the invoking TP, since it establishes the communication. The TP on the server is the invoked TP, because it waits to begin processing until a client makes a request. All of this communication occurs over a previously created LU 6.2 pairing, and the CPI-C TPs must know the names of both LUs, as well as the mode and security level of the conversation. This information is usually contained in the communications side information (CSI) object, which is passed to the CPI-C TP as an argument at startup. In Client Access/400, the configuration of the LU 6.2 pair and the CSI object takes place in the NetSoft Router. (For more information on how this works, see “Enabling CPIC-C Communications in Client Access/400 for Windows 95,” Client Access/400 Expert, May/June 1997.) After the connection to the AS/400 is up, the CPI-C TPs are ready to communicate.


The APING and APINGD Transaction Programs

It should be obvious that CPI-C only works between a pair of programs. APING is no exception to this rule, and in order to understand how it communicates, we need to look both at APING and its server-side partner, APINGD. The APING program is a simple way to test communications between two Advanced Program-to-Program Communications (APPC) platforms. It functions in the same manner as the more familiar TCP/IP PING program, with one computer sending out messages and timing the response from another remote computer. APING is the client side of the equation, the invoking TP, and is passed the name of a server LU that is running APINGD. APINGD is the invoked TP, and, like most server-side TPs, is designated by the letter-D suffix. Any examination of the CPI-C API must begin with an invoked TP that has been started on a server and is awaiting a connection from a client. Figure 2 shows the order of the function calls and the flow of conversation between our two TPs.

Figures 3 and 4 show the code listings for APING and APINGD. Because the code is so extensive, I’ve shown only the relevant CPI-C function calls.

The CPI-C error-handling routines have also been removed. The full versions of the programs illustrated here are by Peter J. Schwaller and are available from the APPC (Advanced Program-to-Program Communications) forum file libraries on CompuServe. (The text about these programs states that they are fair game for just about any purpose, so if you have access, you should pull them down and see what uses you can find for the code.)

The first call each program makes is WinCPICStartup. The CPI-C API is currently at version 1.2, but some additional functions have been added to adapt CPI-C to the Windows environment. The WinCPIC API contains all of the functions from CPI-C 1.2, as well as support for asynchronous communications. With the exception of WinCPICStartup, which initializes the API and the Windows environment, APING and APINGD do not use the WinCPIC extensions. Next, APINGD must prepare for a conversation from a client TP. It issues the cmsltp function (Specify_Local_TP_Name) to set the local transaction program name, which the client will call when it requests a conversation. APINGD next issues cmaccp (Accept_Conversation) and is ready for the client to connect. Notice that cmaccp uses the cm_conv_id variable. This will identify the CPI-C conversation once a client has connected and will be used by all subsequent function calls. Since APINGD does not use the asynchronous WinCPIC functions, it must also issue cmwait (Wait_For_Conversation) in case the client does not connect immediately. At this point, APINGD is blocked, meaning that no further processing will take place until the CPI-C function call is completed.

Conversations between TPs

APING is now ready to invoke a conversation with APINGD. Before we look at its function calls, it is necessary to talk about conversation states. A TP can only be in a send state or a receive state, but never both, so that only one TP in a conversation may send data at a time. At any time, a programmer may use the cmecs (Extract_Conversation_State) function to learn the current state of a TP. In addition, the send or receive type may be used to specify how a TP will handle data. APING begins by using cmsptr (Set_Prepare_To_Receive_Type) to set Cm_Prep_To_Receive_Flush, which is used to flush the contents of the local LU’s send buffer and change the conversation to the receive state. APING then issues cmallc (Allocate) to initiate a conversation with APINGD, which also sets the conversation back to the send state. Most problems with CPI-C programs or LU setups will appear as return error codes from the Allocate function, so be sure to have a good error-handling routine ready. After the successful

Allocate, APINGD uses cmepln (Extract_Partner_LU_Name) to learn the name of the LU that it is communicating with.


APING and APINGD are now ready to send data packets back and forth. APING is currently in the send state and APINGD is in the receive state. APING begins by using the cmsst (Set_Send_Type) function to fill the send buffer with data. It will then issue cmsend (Send) for a number of consecutive times specified by the user of the starting APING, minus one. APINGD will perform an equal number of cmrcv (Receive) functions. Before the last send, APING will use the Set Send Type function again to indicate what type of response it expects from APINGD.

If it sets the send type to Cm_Send_And_Prep_To_Receive, APING will change to the receive state, and APINGD will change to the send state. APINGD may now use the Send function to echo APING’s communication. If, however, APING sets the send type to Cm_Send_And_Confirm, APINGD will only confirm that it has received the data, but will remain in the receive state. After responding with data or a confirmation, APINGD will use the Set Send Type function to return APING to the send state. This entire process may be performed once or repeated many times, depending on a variable specified by the user when starting APING. It should be apparent from this example that the conversation state is critical to a successful CPI-C conversation, and any pair of TPs must carefully coordinate their changing roles.

With the data exchanged, the conversation may now be terminated. As the invoking TP, APING takes care of this chore, although, in theory, either TP could perform this function. APING uses cmsdt (Set_Deallocate_Type) to control what type of deallocation will be performed, in this case using Cm_Deallocate_Flush to empty the send buffer. APING then issues the cmdeal (Deallocate) function and ends the conversation.

While APING and APINGD are relatively simple programs, they do illustrate the basic principles of a CPI-C conversation. The full context of the CPI-C function calls listed in this article may be found in any CPI-C reference. It is most critical, however, that CPI-C TPs have the correct conversation state and partner information. If they don’t, the programs will fail to communicate. Once these concepts are understood, a programmer can create powerful client/server applications with minimal effort and take full advantage of CPI-C’s cross-platform nature.

References:

AS/400 Data and Networking Communications Sourcebook by Kris Neely, Midrange Computing

Common Programming Interface- Communications Reference (SC26-4399) Microsoft SNA Server CPI-C Programmer’s Guide, Microsoft


Programming_with_the_CPI-_C_API04-00.jpg 400x273

Figure 1: A CPI-C Conversation

Overview of APING CPI-Flows

Client (APING) Server (APINGD) Set up conversation Allocate Accept Conversation

For number of iterations (x)

For number of consecutive packets (z)

Send Data Receive For number of consecutive packets (z) Receive Send Data

Shut down the conversation

Deallocate (FLUSH)

Figure 2: CPI-C Program Flows in APING

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

* MODULE NAME: APING.C

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

/* These are the defaults to be used if the user does not provide arguments */
/* to override these values. */
#define DEFAULT_TP_NAME “APINGD”
#define DEFAULT_MODE_NAME “#INTER”
#define DEFAULT_SYM_DEST “APINGD”

#if (defined(WIN32) || defined(WINDOWS)) /*WIN32*/

/****************************************************************WIN32*/

/* Initialisation for WinCPIC *WIN32*/

/****************************************************************WIN32*/

if (WinCPICStartup(WinCPICVERSION,&CPICData)) /*WIN32*/

{ /*WIN32*/

return ; /*WIN32*/

} /*WIN32*/
#endif /*WIN32*/

CM_PREPARE_TO_RECEIVE_TYPE prep_to_receive = CM_PREP_TO_RECEIVE_FLUSH;
cmsptr(cm_conv_id, &prep_to_receive, &cm_rc); /* Set prepare to receive type */

cmallc(cm_conv_id, &cm_rc);

CM_SEND_TYPE send_type = CM_BUFFER_DATA;
cmsst(cm_conv_id, &send_type, &cm_rc);

start_time = get_time();


for (curr_concurrent = 1; /* Start current at one so we */

curr_concurrent

curr_concurrent++ ) { /* loop than the specifed number */

cmsend(cm_conv_id, buffer, &length, &rts_received, &cm_rc);

}

/*

* For the final send in the number of concurrent sends, set the send

* type to do a send and a prepare to receive. This will send both

* the data and the send permission indicator to our partner all at

* once.

*

* If the one_way_flag has been set, we will issue a Confirm along

* with the Send_Data. This will allow us to know when the partner

* has actually received all the data so we can get an accurate

* timing.

*

* On the partner side, if Send status is received, the partner will

* know to echo the data. If Confirm status is received, the partner

* will know to issued Confirmed and then get ready to receive

* more data, since the partner won’t be echoing.

*/

{

CM_SEND_TYPE send_type;

if (flags.one_way_flag != 1) {

send_type = CM_SEND_AND_PREP_TO_RECEIVE;

} else {

send_type = CM_SEND_AND_CONFIRM;

}

cmsst(cm_conv_id, &send_type, &cm_rc);

}

cmsend(cm_conv_id, buffer, &length, &rts_received, &cm_rc);

if (flags.one_way_flag != 1) {

max_receive_len = flags.size;

do {

cmrcv (cm_conv_id, /* Receive Data */

buffer, /* Data Pointer */

&max_receive_len, /* Size of Data Buffer */

&data_received, /* returned - data received */

&received_len, /* returned - length of data */

&status_received, /* returned - status received */

&rts_received, /* returned - request to send */

&cm_rc);

}

if (data_received != CM_NO_DATA_RECEIVED) {

curr_concurrent—;

}

} while ((status_received != CM_SEND_RECEIVED));

/* Repeat the receive loop until SEND permission has been rcvd. */

if (curr_concurrent != 0) {

write_error(

“ERROR. ”);

write_error(

“Partner did not send the expected number of records. ”);

}

} else {

}

end_time = get_time(); /* stop timer */

elapsed_time = end_time - start_time; /* calculate elapsed time */

write_output(“%16ld”, elapsed_time);

write_output(“%17lu”, flags.size * flags.number_concurrent *

flags.one_way_flag);

{

CM_DEALLOCATE_TYPE deallocate_type = CM_DEALLOCATE_FLUSH;

cmsdt(cm_conv_id, &deallocate_type, &cm_rc);

}

cmdeal(cm_conv_id, &cm_rc); /*****************************************************************************

* MODULE NAME: APINGD.C

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

Figure 3: APING CPI-C Function Calls


#if (defined(WIN32) || defined(WINDOWS)) /*WIN32*/

/****************************************************************WIN32*/

/* Initialisation for WinCPIC *WIN32*/

/****************************************************************WIN32*/

if (WinCPICStartup(WinCPICVERSION,&CPICData)) /*WIN32*/

{ /*WIN32*/

return ; /*WIN32*/

} /*WIN32*/
#endif /*WIN32*/

cmsltp(“APINGD”,&temp,&cm_rc);

cmaccp(cm_conv_id, /* Accept Conversation */

&cm_rc);
/*

* Note that as we have used cmsltp to specify our local TP name,

* cmaccp may return asynchronously, so we must do a cmwait

*/

if (cm_rc == CM_OPERATION_INCOMPLETE) /*WIN32*/
{ /*WIN32*/ cmwait(cm_conv_id, &cm_rc, &temp); /*WIN32*/
} /*WIN32*/
if (cm_rc != CM_OK)

{

cmepln(cm_conv_id, (unsigned char *)destination, &pln_length, &cm_rc );
}

CM_PREPARE_TO_RECEIVE_TYPE prep_to_receive = CM_PREP_TO_RECEIVE_FLUSH;
cmsptr(cm_conv_id, &prep_to_receive, &cm_rc); /* Set prepare to receive type */

do {

unsigned long count; /* number of consecutive */

/* sends or receives */

count = 0; /* initialize count of recvs */

do {

cmrcv (cm_conv_id, /* Receive Data */

buffer, /* Data Pointer */

&max_receive_len, /* Size of Data Buffer */

&data_received, /* returned - data received */

&received_len, /* returned - length of data */

&status_received, /* returned - status received */

&rts_received, /* returned - request to send */

&cm_rc);

if (data_received != CM_NO_DATA_RECEIVED) {

count++; /* keep track of receives */

}

} while ( (status_received != CM_SEND_RECEIVED) &&

(status_received != CM_CONFIRM_RECEIVED) &&

!cm_rc);

/*

* loop until we get permission to send data or until error

*/

if (cm_rc != CM_OK) {

if (cm_rc == CM_DEALLOCATED_NORMAL) {

do_exit(EXIT_SUCCESS);

} else {

cpicerr_handle_rc(cpicerr, MSG_CMRCV, cm_rc);

}

}

if (status_received != CM_CONFIRM_RECEIVED) {

/*

* count is now equal to the number of data blocks we received

* now we will send back the same number of data blocks of equal

* size

*/

{

CM_SEND_TYPE send_type = CM_BUFFER_DATA;

cmsst(cm_conv_id,

&send_type,

&cm_rc);

if (cm_rc != CM_OK) cpicerr_handle_rc(cpicerr, MSG_CMSST, cm_rc);

}

/* send back the same number except for one */

for ( count—; count && !cm_rc; count— ) {

length = received_len;

cmsend(cm_conv_id,

buffer,

&length,

&rts_received,

&cm_rc);

if (cm_rc != CM_OK) {

cpicerr_handle_rc(cpicerr, MSG_CMSEND, cm_rc);

}

}

/*


* Set the send type to do a send and a prepare to receive.

* This will send both the data and the send permission indicator

* to our partner all at once.

*/

{

CM_SEND_TYPE send_type = CM_SEND_AND_PREP_TO_RECEIVE;

cmsst(cm_conv_id,

&send_type,

&cm_rc);

if (cm_rc != CM_OK) cpicerr_handle_rc(cpicerr, MSG_CMSST, cm_rc);

}

length = received_len;

cmsend(cm_conv_id,

buffer,

&length,

&rts_received,

&cm_rc);

if (cm_rc != CM_OK) cpicerr_handle_rc(cpicerr, MSG_CMSEND, cm_rc);

} else {

/*

* The partner has requested one way data transfer only.

* We’ll just issue Confirmed, then go back up to receive

* more data.

*/

cmcfmd(cm_conv_id,

&cm_rc);

if (cm_rc != CM_OK) cpicerr_handle_rc(cpicerr, MSG_CMCFMD, cm_rc);

}

} while (cm_rc == CM_OK);

do_exit(EXIT_SUCCESS);
}

Figure 4: APINGD CPI-C Function Calls


BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: