Writing Advanced Applications with the C Wrapper

This document covers the following topics:


Using the RPC Runtime

As a general rule, before using the EntireX RPC runtime, a program/thread must be registered with it using the ERXRegister function. Hence ERXRegister must be the first call to the EntireX RPC runtime and ERXUnregister the last. The number of registrations and unregistrations should be symmetric for every thread, otherwise the thread's resources that are held by the EntireX RPC runtime will not be freed. However, successful unregistration of the last thread within a process will free all EntireX RPC runtime resources.

Each thread of a process has to register separately with the EntireX RPC runtime. After registration the EntireX RPC runtime maintains on a per-thread basis

The following limitations and restrictions also apply:

  • Up to 256 threads can be registered in parallel within a process.

  • Multiple registration up to 32,767 per thread before unregistration is possible but not recommended.

All functions provided by the EntireX RPC runtime to handle the variable-length data types and unbounded arrays can be used without registration.

  • Functions to handle variable-length data types are defined in the header file erxvdata.h and are prefixed with "erxVData".

  • Functions to handle unbounded arrays are defined in the header file erxarray.h and are prefixed with "erxArray".

Examine the RPC Runtime and Interface Object Version

The EntireX C Wrapper API provides an interface to examine the version of the RPC Runtime, see ERXGetVersion.

Examine the Interface Object Version

If you generate interface objects according to the instructions given in Using the C Wrapper for the Client Side, a function to examine the interface object version on a per-library basis is also generated:

int ERX_CALL_DECLARATION GetVersionEXAMPLEStub(
     char    *pMessage,
     size_t   uMessageLength
);

Calling this function will provide you with the version and patch level under which the interface object was generated.

Example

EntireX C Wrapper Version=10.7.0, Patch Level=0

Tracing

There are several possibilities to trace the EntireX C Wrapper. See Tracing webMethods EntireX under UNIX | Windows | BS2000 | z/VSE.

Programming Multithreaded RPC Clients

The EntireX C Wrapper runtime supports RPC clients in multithreaded environments. Every thread can establish its own RPC and broker context for communication, which is separate from every other thread's context, see also Using the RPC Runtime.

The functions ERXSetContext and ERXGetContext together with client interface objects generated using the instructions given in Using the C Wrapper in Multithreaded Environments (UNIX, Windows) assist in programming multithreaded RPC clients.

The ERXSetContext function can be executed prior to any business logic to provide the RPC and broker context individually on a per-thread basis. ERXSetContext saves the context information in a structure ERX_CONTEXT_BLOCK. The client interface object picks up the context from the calling thread using the reverse function ERXGetContext. Hence legacy applications may not be changed to transport this information.

Additional Notes:

  • To use the ERXSetContext and ERXGetContext functions, client interface objects must be generated with the check box Multithreaded Client switch. See Generate C Source Files from Software AG IDL Files.

  • A maximum of 256 threads are supported in parallel.

  • The ERXSetContext function can be called multiple times (within the same thread). This also makes it possible to change RPC and broker context with each RPC request.

  • Nothing needs to be considered for servers. EntireX RPC servers support multithreading without any further activities.

Logon to Natural Library

By default the library name sent to the RPC server is retrieved from the IDL file (see library-definition under Software AG IDL Grammar in the IDL Editor documentation). The library name can be overwritten. This is useful if communicating with a Natural RPC server.

Start of instruction setTo overwrite the library name

  1. Set the medium ERX_TM_BROKER_LIBRARY in the ERX_SERVER_ADDRESS structure.

  2. Specify the library in the ERX_SA_BROKER_LIBRARY structure in the szLibraryName parameter you want to log on to.

  3. Set the parameter cNaturalLogon to "ERX_NATURAL LOGON_YES" in the ERX_SA_BROKER_LIBRARY structure.

If you need to set security credentials too, refer to Using the Broker and RPC User ID/Password.

Using Variable-length Data Types AV, BV, KV and UV

The following functions are used to send and receive the variable-length data types (IDL data types AV, BV, KV and UV). All variable-length data is controlled by so-called VData instances. A VData instance is a handle (pointer) to a memory location encapsulated in the erxVData... functions in the EntireX RPC runtime.

A VData instance has the following type definition:

typedef void * ERX_HVDATA; /* Handle of VData instance */

See the following overview of VData functions.

Task Function
Allocate a new VData instance erxVDataAllocBytes
erxVDataAllocString
erxVDataAllocWideString
Remove a VData instance erxVDataFree
Get the contents held by a VData instance erxVDataGetByteAddress
erxVDataGetLength
erxVDataGetString
erxVDataGetWideString
Assign new contents to the VData instance erxVDataCopy
erxVDataReAllocBytes
erxVDataReAllocString
erxVDataReAllocWideString
erxVDataReset

Usage with EntireX RPC Client

Before issuing the RPC request, allocate all VData instances including the instances for direction out (which is returned by the RPC server only), see attribute-list.

Start of instruction setTo allocate and create VData instances

  1. For the directions in and inout, use erxVDataAllocBytes (IDL data type BV and KV), erxVDataAllocString (IDL data type AV) or erxVDataAllocWideString (IDL data type UV) with the appropriate parameters to allocate the VData instances.

  2. For the direction out use erxVDataAllocBytes(NULL,0) (IDL data type BV and KV), erxVDataAllocString(NULL) (IDL data type AV) or erxVDataAllocWideString(L"") (IDL data type UV)to create an empty VData instance, which will contain the data returned by the server.

Following the RPC request, you can examine the server reply.

Start of instruction setTo examine the server reply

  • Use the functions erxVDataGetString (IDL data type AV), erxVDataGetWideString (IDL data type UV) and erxVDataGetLength, erxVDataGetByteAddress (IDL data type BV and KV).

Start of instruction setTo remove VData instances

  • Use the function erxVDataFree if they are no longer needed.

Usage with EntireX RPC Server

When your implemented server is called, all VData instances are allocated by the RPC C runtime and RPC Server. The data sent by the client can be examined in the server program (in the same way the client does upon server reply). The RPC Server and the RPC C runtime will remove the VData instances if they are no longer needed. Do not remove any VData instances in server programs yourself!

Start of instruction setTo examine the client data

  • Use the functions erxVDataGetString (IDL data type AV), erxVDataGetWideString (IDL data type UV) and erxVDataGetLength, erxVDataGetByteAddress (IDL data type BV and KV).

Start of instruction setTo assign data to be returned

  • Use the functions erxVDataReAllocBytes (IDL data type BV and KV), erxVDataReAllocWideString (IDL data type UV) and erxVDataReAllocString (IDL data type AV).

Using Unbounded Arrays

The following functions are used to send and receive unbounded array data types of EntireX RPC (data types defined with V in the indices). All unbounded arrays are controlled by so-called arrays instances. An arrays instance is a handle (pointer) to a memory location encapsulated by the EntireX RPC Runtime.

An array instance has the following type definition:

typedef void * ERX_HARRAY; /* Handle of Array instance */

See the following overview of functions for use with unbounded arrays.

Task Function
Allocate a new array instance erxArrayAlloc
Remove an array instance erxArrayFree
Get the contents of an array instance erxArrayGetElement
Assign new contents to an array instance erxArrayCopy
erxArrayReset
erxArraySetElement
Get the characteristics of an array instance erxArrayGetAttributes
erxArrayGetBounds
erxArrayGetDimension
erxArrayGetElementLength
erxArrayGetTypeCode
Change upper bounds of an array instance erxArrayRedimAll
erxArrayRedimVector

Usage with EntireX RPC Client

Before calling the client interface object (that is, before issuing the remote procedure call) allocate all array instances and create instances for out data. You cannot change any type, attribute, length or dimension. When the instances are created, only the upper bounds can be changed.

For the directions in and inout, use erxArrayAlloc with appropriate parameters to allocate an array instance. For the direction out, create an array instance of correct type, attributes, length and dimension with all upper bounds set to 0. This is an empty array instance with no elements. Upon return it will contain the elements assigned by the server.

EntireX RPC supports unbounded arrays which must not necessarily be a square (when 2-dimensional) or a cube (when 3-dimensional). Any vector within any dimension could have different upper bound settings. Such an array could be created in two ways:

  • Start with an empty array and set the upper bounds of the first dimension with erxArrayRedimVector. Subseqeuently loop through this dimension and set any vector of the second dimension using also erxArrayRedimVector. If it is a 3-dimensional array, do the same with the third dimension.

  • Create a square (2-dimensional) or cube (3-dimensional) with erxArrayAlloc or erxArrayRedimAll and subsequently deform the array with erxArrayRedimVector.

Data to be sent can be assigned using the function erxArraySetElement as long as the index is within the current upper bounds. Otherwise an error will occur. Because any vector of any dimension could have different upper bound settings, the upper bounds must be examined separately for every vector. See the following code fragment:

int             i,j,k;
ERX_HARRAY      hArray;
ERX_ARRAY_INDEX uArrayIndex[3];
.....
for (i=0;i<erxArrayGetBounds(hArray,(unsigned int)1,NULL);i++)
{
        uArrayIndex[0] = i;
        for (j=0;j<erxArrayGetBounds(hArray,(unsigned int)2,uArrayIndex);j++)
        {
                uArrayIndex[1] = j;
                for (k=0;k<erxArrayGetBounds(hArray,(unsigned int)3,uArrayIndex);k++)
                {
                        Data = ...;

                     uArrayIndex[2] = k;
                        rc = erxArraySetElement(
                                hArray,
                                uArrayIndex,
                                &Data
                        );
                }
        }
}

To examine the data received from the server the same scheme can be used:

int             i,j,k;
ERX_HARRAY      hArray;
ERX_ARRAY_INDEX uArrayIndex[3];
.....
for (i=0;i<erxArrayGetBounds(hArray,(unsigned int)1,NULL);i++)
{
        uArrayIndex[0] = i;
        for (j=0;j<erxArrayGetBounds(hArray,(unsigned int)2,uArrayIndex);j++)
        {
                uArrayIndex[1] = j;
                for (k=0;k<erxArrayGetBounds(hArray,(unsigned int)3,uArrayIndex);k++)
                {
                        uArrayIndex[2] = k;
                        rc = erxArrayGetElement(
                                hArray,
                                uArrayIndex,
                                &Data
                        );

                   ... = Data;
                }
        }
}

Remove previously created array instances (if they are no longer needed) with the function erxArrayFree.

Usage with EntireX RPC Server

When the server is called, all array instances are allocated by the EntireX RPC Runtime and EntireX RPC Server.

The data sent by the client can be examined in the server program the same way the client examines data upon server reply.

The upper bounds of the array instance can be changed with the erxArrayRedimAll or erxArrayRedimVector function before setting any return data:

  • When you use the erxArrayRedimAll function, the result will be an array in the form of a vector (1-dimensional), a square (2-dimensional) or a cube (3-dimensional). Thus all vectors of a dimension have the same upper bounds. Subsequently with the erxArrayRedimVector the square or cube can be deformed.

  • You can also remove all elements of the unbounded array. This results in an unbounded array with no elements when setting the bounds parameter of erxArrayRedimAll to "0". Afterwards you can set the upper bounds of the first dimension with erxArrayRedimVector. Subseqeuently loop through this dimension and set any vector of the second dimension also using erxArrayRedimVector. If it is a 3-dimensional array, do the same with the third dimension. You cannot change any type, attribute, length or dimension. Only upper bounds can be changed.

Data to be returned can be assigned using the function erxArraySetElement the same way the client does before send.

Important:
Do not remove any array instances in server programs.

Using Conversational RPC

It is assumed that you are familiar with the concepts of conversational and non-conversational RPC. See Common Features of Wrappers and RPC-based Components.

Start of instruction setTo use conversational RPC

  1. Open a conversation with the ERXConnect function call (see ERXConnect). Save the server address ERX_SERVER_ADDRESS and reuse it for the complete RPC conversation.

  2. Issue your RPC requests as within non-conversational mode using the generated interface objects. Different interface objects can participate in the same RPC conversation.

Start of instruction setTo abort a conversational RPC communication

  • Abort an RPC conversation unsuccessfully with the function call ERXDisconnect.

Start of instruction setTo close and commit a conversational RPC communication

Warning:
Natural and EntireX RPC servers behave differently when ending an RPC conversation.

See Conversational RPC.

Using EntireX Security

EntireX C Wrapper Applications which require security can use the security services offered by EntireX Security. See EntireX Security for a general overview.

Start of instruction setTo use EntireX Security

  1. Specify a user ID and password in the parameters *pUserId and *pPassword of the ERX_CLIENT_IDENTIFICATION structure.

  2. Set security with the function ERXSetBrokerSecurity to force a secure call to a broker running with EntireX Security. You can use the same values as for broker ACI field KERNELSECURITY. See KERNELSECURITY under Broker ACI Fields. The function works together with any broker kernel version that supports EntireX Security, regardless of the ACI version used.

Note:
The broker's security token is maintained inside the EntireX RPC Runtime on a per-thread basis, see Using the RPC Runtime. If you are communicating with more than one broker in a single thread:

  • you have to save the broker's security token provided in the ERX_CLIENT_IDENTIFICATION structure after an ERXLogon function call

  • you have to provide the correct previously saved Broker's security token with the ERXSetSecurityToken function to the RPC Runtime before calling one of the following functions:

    • ERXCall

    • ERXConnect

    • ERXDisconnect

    • ERXDisconnectCommit

    • ERXLogon

    • ERXLogoff

    • ERXTerminateServer

    • ERXIsServing

    • ERXWait

    Other functions are executed locally and do not communicate with the Broker, the Broker's security token is not required.

Using the Broker and RPC User ID/Password

EntireX supports two user ID/password pairs: a broker user ID/password pair and an (optional) RPC user ID/password pair sent from RPC clients to RPC servers. With EntireX Security, the broker user ID/password pair can be checked for authentication and authorization.

The RPC user ID/password pair is designed to be used by the receiving RPC server. This component's configuration determines whether the pair is considered or not. Useful scenarios are:

  • Credentials for Natural Security

  • Impersonation under z/OS (CICS, Batch, IMS)

  • Web Service Transport Security with the RPC Server for XML/SOAP, see XML Mapping Files

  • Service execution with client credentials for EntireX Adapter Listeners, see Configuring Listeners

  • etc.

Sending the RPC user ID/password pair needs to be explicitly enabled by the RPC client. If it is enabled but no RPC user ID/password pair is provided, the broker user ID/password pair is inherited to the RPC user ID/password pair.

With cNaturalLogon (see below) sending the RPC user ID/password pair is enabled for C RPC clients. If you do so, we strongly recommend Using SSL/TLS.

Start of instruction setTo use the broker and RPC user ID/password

  1. Specify a broker user ID and optional broker password in the parameters pUserId and pPassword of the ERX_CLIENT_IDENTIFICATION structure.

  2. Set the medium ERX_TM_BROKER_LIBRARY in the ERX_SERVER_ADDRESS structure.

  3. Set the parameter cNaturalLogon to "ERX_NATURAL LOGON_YES" in the ERX_SA_BROKER_LIBRARY structure to enable sending the RPC user ID/password pair.

  4. If different user IDs and/or passwords are used for broker and RPC, use the parameters pRpcUserId and pRpcPassword to provide a different RPC user ID/password pair.

  5. By default the library name sent to the RPC server is retrieved from the IDL file (see library-definition under Software AG IDL Grammar in the IDL Editor documentation). The library name can be overwritten. This is useful if communicating with a Natural RPC server. Specify a library in the ERX_SA_BROKER_LIBRARY structure in the szLibraryName parameter.

If you need to log on to a Natural library without setting security credentials, refer to Logon to Natural Library.

Using SSL/TLS

RPC client applications can use Secure Sockets Layer/Transport Layer Security (SSL/TLS) as the transport medium. The term "SSL" in this section refers to both SSL and TLS. RPC-based clients are always SSL clients. The SSL server can be either the EntireX Broker or Direct RPC in webMethods Integration Server (IS inbound). For an introduction see SSL/TLS, HTTP(S), and Certificates with EntireX in the platform-independent Administration documentation.

With the C Wrapper, the SSL parameters (e.g. certificates) are provided in the ERX_CLIENT_IDENTIFICATION structure.

Start of instruction setTo use SSL

  1. To operate with SSL, certificates need to be provided and maintained. Depending on the platform, Software AG provides default certificates, but we strongly recommend that you create your own. See SSL/TLS Sample Certificates Delivered with EntireX in the EntireX Security documentation.

  2. Specify the Broker ID, using one of the following styles:

    If no port number is specified, port 1958 is used as default.

  3. Specify SSL parameters on the pSSLParameter parameter in the ERX_CLIENT_IDENTIFICATION structure, for example:

    "VERIFY_SERVER=N&TRUST_STORE=c:\\certs\\CaCert.pem"

    If the SSL client checks the validity of the SSL server only, this is known as one-way SSL. The mandatory trust_store parameter specifies the file name of a keystore that must contain the list of trusted certificate authorities for the certificate of the SSL server. By default a check is made that the certificate of the SSL server is issued for the hostname specified in the Broker ID. The common name of the subject entry in the server's certificate is checked against the hostname. If they do not match, the connection will be refused. You can disable this check with SSL parameter verify_server=no.

    If the SSL server additionally checks the identity of the SSL client, this is known as two-way SSL. In this case the SSL server requests a client certificate (the parameter verify_client=yes is defined in the configuration of the SSL server). Two additional SSL parameters must be specified on the SSL client side: key_store and key_passwd. This keystore must contain the private key of the SSL client. The password that protects the private key is specified with key_passwd.

    The ampersand (&) character cannot appear in the password.

    SSL parameters are separated by ampersand (&). See also SSL/TLS Parameters for SSL Clients.

  4. Make sure the SSL server to which the RPC component connects is prepared for SSL connections as well. The SSL server can be EntireX Broker, Broker SSL Agent, or Direct RPC in webMethods Integration Server (IS inbound). See:

Using Compression

EntireX C Wrapper Applications may compress the messages sent to and received from the broker.

Start of instruction setTo use compression

Using Internationalization with the C Wrapper

For RPC clients, the RPC runtime itself does not convert your application data. The application's data is shipped and received as given. The application must ensure the encoding of the data matches the codepage sent to the broker.

Under the Windows operating system:

  1. The RPC runtime assumes by default the data is given in the encoding of the Windows ANSI codepage configured for your system. A codepage identifier of this Windows ANSI codepage is automatically transferred to tell the broker how the data is encoded, even if no codepage name is provided with function ERXSetCodepage, see API Function Descriptions.

  2. If you want to adapt the Windows ANSI codepage, see the Regional Settings in the Windows Control Panel and your Windows documentation.

  3. If you want to encode the data different to your Windows ANSI codepage, provide the data in the desired encoding and provide the codepage name with function ERXSetCodepage. During receive, decode the data if necessary.

Under all other operating systems:

  • The RPC runtime does not automatically send a codepage identifier to the broker.

  • It is assumed the broker's locale string defaults match. See Locale String Mapping. If they do not match, provide the correct codepage name with function ERXSetCodepage.

Enable character conversion in the broker by setting the service-specific attribute CONVERSION to "SAGTRPC". See also Configuring ICU Conversion under z/OS | UNIX | Windows | BS2000. More information can be found under Internationalization with EntireX.