/*@@file***********************************************************************
 *
 * DESCRIPTION:
 *  This is an IS/2 sample client program for the APPC/2 interface. This sample
 *  is distributed "As Is" and without warranty. It is intended to be used 
 *  only as an example of how the functions of IS/2 can be invoked 
 *  using APPC on an OS/2 system.
 *
 ****************************************************************************/

#ifdef  DOCUMENT

    This file contains all the information needed to build and execute the IS/2
    sample client program using APPC on an OS/2 system. When used in conjunction
    with the Interface Services/2 Programmer's Guide, SC28-8258, the sample
    program will help you to understand IS/2 and the program structure
    requirements of APPC and Host Link/2.

FUNCTION:

    The function of APC2SAMP is to send three IS/2 transactions to the
    IS/2 Server, EA_AUTHORIZE, EA_SYMLOOK, and EA_EXIT.  For each transaction
    APC2SAMP.EXE waits for the IS/2 response message and displays it on the
    console.  At the end of this sequence, the program terminates. The program
    can be re-executed as many times as desired.

    The program has two layers.  The top layer establishes the variables for
    IS/2 and APPC. It then calls the bottom layer to send an IS/2 transaction
    message to the IS/2 server. The lower layer establishes an APPC session
    with the Host Link/2 communication REM. It then sends the IS/2 transaction
    message, including the DAE destination routing information, and waits for
    the response message from IS/2.

COMPONENTS PROVIDED (as separate files):

    IS/2 Server side:

      eaappc2.cfg   Sample OS/2 APPC communication manager configuration file
      easerv2.cbs   Sample DAE configuration description file for server side

    Client side:

      apc2samp.txt  Sample documentation and the sample listing (this file)
      eaclnt2.cfg   Sample OS/2 APPC communication manager configuration file

RELATED REQUIREMENTS:

    Run Time Environment Hardware requirements
    ---------------------------------------------------

    o   Two Systems running OS/2 1.2, CS/2 1.1, Host Link/2, and IS/2 as
        configured below.

    o   The Communication Manager configuration files, "eaappc2.cfg" and
        "eaclnt2.cfg" describe an SDLC connection between the two systems.
        Two SDLC cards, a modem eliminator, and two RS232C (25 pin) cables can
        be used to support this configuration.

    o   You may change "eaapcc2.cfg & eaclnt2.cfg" to use other hardware, such
        as a Token-Ring, to connect the two machines if you prefer to run APPC
        in that environment. The two 'cfg' files must be changed accordingly.

    Run Time Environment Network Software requirements
    --------------------------------------------------

    o   The system which runs IS/2 is designated as the 'server node'.
        The system running the user program is designated as the 'client node'.

    o   The 'server node' has to have the following software:
        1.  OS/2 EE Version 1.2
        2.  OS/2 EE Communication Manager Version 1.2
        3.  CS/2 Version 1.1
        4.  DAE APPC Communication REM (CS2APR00)
        5.  DAE Hostlink Server (CS2HTR00)
        6.  PlantWorks Execution Services/2 with CSD 1
        7.  PlantWorks IS/2 Version 1.0

    o   The 'client node' has to have the following software:
        1.  OS/2 EE Version 1.2
        2.  OS/2 EE Communication Manager 

    Run Time Environment DAE Configuration requirements
    --------------------------------------------------------

    o   The 'server node' must be configured for DAE as follows:
        1.  NIB = "NODE5"
        2.  ACB = "CS2APR00.CS2NODE" (APPC Communication REM)
        3.  ACB = "CS2HTR00.CS2NODE" (Host Link/2 Server)
        4.  ACB = "EAPI.CS2NODE"     (PlantWorks IS/2 Server)
        5.  CACB= "CS2AP000.CS2NODE" (APPC CACB)
        6.  LCCB= "NODE5.CS2AP000"   (Local CCB)
            Inbound Server = standard
            Outbound Server = standard
        7.  RCCB= "HOST1.CS2AP000"   (Remote CCB)
            Inbound Server  = "CS2HTR00"
            Outbound Server = "CS2HTR00"
        8.  See 'easerv2.cbs' for more details

    o   The 'client node' has no DAE requirements

    Run Time Environment APPC Configuration requirements
    ----------------------------------------------------

    o   Copy "eaappc2.cfg" to the \CMLIB directory on the 'server node' for the
        OS/2 Communication Manager configuration. The following shows the
        highlights of that file:

        1.  SNA Base Profiles
            a.  Network Name:               "CHESTNUT"
        2.  Data Link Profiles
            a.  SDLC, non-switched, non NRZI
            b.  Link Station Role:          "Negotiable"
            c.  PU 2.1
        3.  Logical Unit Profiles
            a.  LU Alias Name:              "NODE5"
            b.  LU Name:                    "NODE5"
        4.  Partner Logical Unit Profiles
            a.  Partner LU Alias Name:      "HOST1"
            b.  Fully Qualified Partner LU: "        .HOST1"
            c.  LU Alias:                   "NODE5"
        5.  Transmission Service Profiles
            a.  Mode Name:                  "CS2MODE"
        6.  Initial Session Limit Profiles
            a.  Contention Winner's Source:  "2"
            b.  Contention Losers Target:    "2"
            c.  PU 2.1
        7.  Remotely Attachable TP
            a.  TP Profile Name:            "NODE5"
            b.  TP Name:                    "NODE5"
            c.  TP Operation:               "Queued Operator Started"

    o   Copy "eaclnt2.cfg" to the \CMLIB directory on the 'client node'
        for the OS/2 Communication Manager configuration. The following shows
        the highlights of that file:

        1.  SNA Base Profiles
            a.  Network Name:               "CHESTNUT"
        2.  Data Link Profiles
            a.  SDLC, non-switched, non NRZI
            b.  Link Station Role:          "Negotiable"
            c.  PU 2.1
        3.  Logical Unit Profiles
            a.  LU Alias Name:              "HOST1"
            b.  LU Name:                    "HOST1"
        4.  Partner Logical Unit Profiles
            a.  Partner LU Alias Name:      "NODE5"
            b.  Fully Qualified Partner LU: "        .NODE5"
            c.  LU Alias:                   "HOST1"
        5.  Transmission Service Profiles
            a.  Mode Name:                  "CS2MODE"
        6.  Initial Session Limit Profiles
            a.  Contention Winners Source:  "2"
            b.  Contention Losers Target:   "2"
            c.  PU 2.1
        7.  Remotely Attachable TP
            (none)

EXECUTION SEQUENCE:

    Before the sample program can be executed some PW variables must be
    defined. The sample assumes that a user ID and password and a PW item
    have been defined as described below:

    o   PlantWorks user identification

        1. User Name ID:  EAPIDEMO
        2. User Password: EAPIDEMO
           NOTE: This user ID should have 'full access'. See page 2-12 in the
           IS/2 Programmer's Guide for a description of how to do this.

    o   PlantWorks Item

        1. Item Name:     APP:VAR1
           This item must be defined as a floating point variable and assigned
           a value. If you define it as anything except floating point, the
           sample program must be changed.


    Once these two tasks have been accomplished you are now ready to run
    the sample program. The following describes this process:

    o   Build the IS/2 Sample APPC Client Program with IBM C/2 compiler

        1. Copy apc2samp.txt and rename it to apc2samp.c
        2. Compile and link the program with these parameters:

           cl /AL /G2 /W1 /Zp  /F 4000 apc2samp.c /link acs.lib

    o   Startup the IS/2 Server Node

        1. Start the OS/2 Communication Manager
        2. Start the DAE System Software
        3. Start the PlantWorks Software
           with the IS/2 Server

    o   Startup the Sample program

        1. Start the 'client node' APPC by typing "cm eaclnt2" on that node
        2. Execute the program by typing "apc2samp" on the 'client node'.

#endif  /* DOCUMENT */



/**********************************************************************
 *----- Beginning of C program
 **********************************************************************/

/*
 *
 */
#include <stddef.h>
#include <string.h>
#include <dos.h>
#include <os2.h>

#include <APPC_C.H>
#include <ACSSVCC.H>
#include <eapimsg.h>

/*--------------------------------------------------------------------------*/
/*             Configuration Parameter Variables                            */
/*--------------------------------------------------------------------------*/
/*             APPC Variables                                               */
/*--------------------------------------------------------------------------*/
char client_luname[8]    ="HOST1   ";   /* APPC Local LU Alias Name */
char client_tpname[64]   ="HOST1TP1";   /* APPC Attach Manager TP Name */
char hostlink_luname[8]  ="NODE5   ";   /* APPC Partner LU Name */
char hostlink_tpname[64] ="NODE5   ";   /* APPC Partner TP Name */
char hostlink_modename[8]="CS2MODE ";   /* APPC Partner Mode Name Profile */
/*--------------------------------------------------------------------------*/
/*             DAE Variables                                                */
/*--------------------------------------------------------------------------*/

char cs2_rwa_orig_name[17] = "HOST1TP1.HOST1";
                                        /* Host Link Header Origination
                                         * [APPC TP Name].[APPC LU Name] */
char cs2_rwa_dest_name[17] = "EAPI.CS2NODE  ";
                                        /* Host Link Header Destination
                                         * IS/2 Server CS/2 ACB Name
                                         * [User Name].[Node Name] */
/*--------------------------------------------------------------------------*/
/*             IS/2 Variables                                               */
/*--------------------------------------------------------------------------*/
struct ear_authorize ea_authorize_data = {
    EA_AUTHORIZE, 1, EA_APPC2, 0,
    "EAPIDEMO",
    "EAPIDEMO"
    };
struct ear_symlookup symbol = {
    EA_SYMLOOKUP, 2, "APP:VAR1"
    };
struct eas_symlookup *symdata;
struct ear_exit ea_exit_data = {
    EA_EXIT, 3,1
    };


/*--------------------------------------------------------------------------*/
/*             Verb Control Block - Union of Structures                     */
/*--------------------------------------------------------------------------*/

typedef struct VCB
  {
  union
    {
    struct appc_hdr              hdr;
    struct receive_allocate      rcv_alloc;
    struct mc_allocate           alloc;
    struct mc_deallocate         dealloc;
    struct mc_receive_and_wait   rcv_wait;
    struct mc_send_data          send;
    struct mc_confirmed          confirmed;
    struct tp_started            tpstarted;
    struct tp_ended              tpended;
    struct convert               cnvt;
    } type;
  } VCB;

#define MESSAGE_SIZE 4096

typedef struct APPC_MSG {
        char rwa_cs2_orig[17];
        char rwa_cs2_dest[17];
        char rwa_data_type;
        char data[1];
} APPC_MSG;



char client_tpname_ebcdic    [64];
char hostlink_tpname_ebcdic  [64];
char hostlink_modename_ebcdic[8];

/*--------------------------------------------------------------------------*/
/*             End of Configuration Parameter Variables                     */
/*--------------------------------------------------------------------------*/
/*             APPC Verb Control Block Variables                            */
/*--------------------------------------------------------------------------*/

VCB vcbdef;                             /* Global vcb definition        */
VCB *vcbptr=&vcbdef;                    /* Global vcb pointer           */
/* pointers for each structure definition                               */
/* Note they all occupy the same memory space and redefine each other   */
struct appc_hdr            *pvcb_header    = &vcbdef.type.hdr;
struct receive_allocate    *pvcb_rcv_alloc = &vcbdef.type.rcv_alloc;
struct mc_allocate         *pvcb_alloc     = &vcbdef.type.alloc;
struct mc_deallocate       *pvcb_dealloc   = &vcbdef.type.dealloc;
struct mc_receive_and_wait *pvcb_rcv_wait  = &vcbdef.type.rcv_wait;
struct mc_send_data        *pvcb_send      = &vcbdef.type.send;
struct mc_confirmed        *pvcb_confirmed = &vcbdef.type.confirmed;
struct tp_started          *pvcb_tpstarted = &vcbdef.type.tpstarted;
struct tp_ended            *pvcb_tpended   = &vcbdef.type.tpended;
struct convert             *pvcb_cnvt      = &vcbdef.type.cnvt;

APPC_MSG *pmsgbuf;                      /* Shared Segment APPC Message */
APPC_MSG rwa_header;                    /* RWA Minimal Header */
APPC_MSG *prwa_header=&rwa_header;      /* RWA Minimal Header pointer */



/*
 *      Main program
 */
main()
{
  unsigned char rcv_buf[4096];
  int      rcv_len,i;
  unsigned short selector;              /* Selector from DOSALLOCSEG    */
  unsigned short dos_rc;

                                        /* APPC requires a data buffer  */
                                        /* in a shared unnamed segment  */
  if (dos_rc=DosAllocSeg (MESSAGE_SIZE, (unsigned far *)&selector, 1))
    {
    printf("Error on get share memory buffer error code = <%x>\n", dos_rc);
    exit(1);
    }
  FP_OFF(pmsgbuf) = 0;                   /* set the offset to zero      */
  FP_SEG(pmsgbuf) = selector;            /* address = Selector:0        */
  /*
   *    The APPC headers use EBCDIC Names
   */
  convert_a2e(client_tpname,    client_tpname_ebcdic,           64);
  convert_a2e(hostlink_tpname,  hostlink_tpname_ebcdic,         64);
  convert_a2e(hostlink_modename,hostlink_modename_ebcdic,       8);
  convert_a2e(cs2_rwa_orig_name,prwa_header->rwa_cs2_orig,      17);
  convert_a2e(cs2_rwa_dest_name,prwa_header->rwa_cs2_dest,      17);
  convert_a2e("B", &prwa_header->rwa_data_type, 1);

  send_rcv((char *) &ea_authorize_data, sizeof(ea_authorize_data),
           rcv_buf, &rcv_len);
  printf("AUTHORIZE status = %d.\n",((struct eas_header *)rcv_buf)->status);
  symdata	= (struct eas_symlookup *)rcv_buf;
  send_rcv((char *) &symbol, sizeof(symbol),
           symdata, &rcv_len);
  printf("SYMLOOKUP has %d. bytes of data:\n", rcv_len);
  printf("  status=%d.  node name=[%s] type=%d.  length=%d.\n", 
        symdata->status, symdata->node_name,symdata->data_type,
        symdata->data_length);
  send_rcv((char *) &ea_exit_data, sizeof(ea_exit_data),
           rcv_buf, &rcv_len);
  printf("EXIT status = %d.\n",((struct eas_header *)rcv_buf)->status);
}       /* End of Mainline      */

/*
 *              Send message and Receive response
 */
send_rcv(send_buf, send_len, rcv_buf, rcv_len)
char *send_buf;                         /* in: data to send             */
int   send_len;                         /* in: data length              */
char *rcv_buf;                          /* out: buffer to receive data  */
int  *rcv_len;                          /* out: received data length    */
{
  memset(vcbptr, 0, sizeof(VCB));       /* default to 0's               */
                                        /* APPC TP_STARTED              */
  pvcb_tpstarted->opcode = AP_TP_STARTED;
  memcpy (pvcb_tpstarted->lu_alias, client_luname, 8);
  memcpy (pvcb_tpstarted->tp_name, client_tpname_ebcdic, 64);
  APPC_C ((long) vcbptr);
  check_rc(vcbptr);
                                        /* save the returned TP_ID      */
  memcpy (pvcb_alloc->tp_id, pvcb_tpstarted->tp_id, 8);
                                        /* MC_ALLOCATE                  */
  pvcb_alloc->opcode    = AP_M_ALLOCATE;
  pvcb_alloc->opext     = AP_MAPPED_CONVERSATION;
  pvcb_alloc->rtn_ctl   = AP_WHEN_SESSION_ALLOCATED;
  pvcb_alloc->security  = AP_NONE;
  pvcb_alloc->sync_level= AP_CONFIRM_SYNC_LEVEL;
  memcpy (pvcb_alloc->plu_alias,hostlink_luname,        8);
  memcpy (pvcb_alloc->tp_name,  hostlink_tpname_ebcdic, 64);
  memcpy (pvcb_alloc->mode_name,hostlink_modename_ebcdic,8);
  APPC_C((long) vcbptr);
  check_rc(vcbptr);
                                        /* Build the Message            */
  memcpy(pmsgbuf->rwa_cs2_orig, prwa_header->rwa_cs2_orig, 35);
  memcpy(pmsgbuf->data, send_buf, send_len);

                                        /* MC_SEND_DATA                 */
  pvcb_send->opcode     = AP_M_SEND_DATA;
  pvcb_send->dlen       = sizeof(APPC_MSG) -1 + send_len;
  pvcb_send->dptr       = (char *) pmsgbuf;
#ifndef OS2_1_1
                                  /* AP_SEND_DATA_DEALLOCATE_SYNC_LEVEL */
  pvcb_send->type       = AP_NONE;
#endif
  APPC_C((long) vcbptr);
  check_rc(vcbptr);

                                        /* MC_DEALLOCATE_CONFIRM        */
  pvcb_dealloc->opcode  = AP_M_DEALLOCATE;
  pvcb_dealloc->dealloc_type    = AP_SYNC_LEVEL;
  APPC_C((long) vcbptr);
  check_rc(vcbptr);

                                        /* TP_ENDED                     */
  pvcb_tpended->opcode  = AP_TP_ENDED;
#ifndef OS2_1_1
  pvcb_tpended->type    = AP_SOFT;
#endif
  APPC_C((long) vcbptr);
  check_rc(vcbptr);


/****************************************************************************/
/*                          RECEIVE MESSAGE                                 */
/****************************************************************************/

  memset(vcbptr, 0, sizeof(VCB));

                                        /*  RECEIVE_ALLOCATE            */
  pvcb_rcv_alloc->opcode = AP_RECEIVE_ALLOCATE;
  pvcb_rcv_alloc->sync_level    = AP_CONFIRM_SYNC_LEVEL;
  memcpy (pvcb_rcv_alloc->tp_name, client_tpname_ebcdic, 64);
  APPC_C((long) vcbptr);
  check_rc(vcbptr);
                                        /* copy the TP_ID and CV_ID     */
  memcpy (pvcb_rcv_wait->tp_id, pvcb_rcv_alloc->tp_id, 8);
  pvcb_rcv_wait->conv_id=  pvcb_rcv_alloc->conv_id;
  pvcb_rcv_wait->opext  = pvcb_rcv_alloc->conv_type;
                                        /* MC_RECEIVE_AND_WAIT (for Data) */
  pvcb_rcv_wait->opcode = AP_M_RECEIVE_AND_WAIT;
  pvcb_rcv_wait->max_len= MESSAGE_SIZE;
  pvcb_rcv_wait->dptr   = (char *) pmsgbuf;
#ifndef OS2_1_1
  pvcb_rcv_wait->rtn_status     = AP_NO;
#endif
  APPC_C((long) vcbptr);                 /* Call APPC                   */
  check_rc(vcbptr);

  *rcv_len=((pvcb_rcv_wait->dlen) - (sizeof(APPC_MSG) - 1));
  memcpy(rcv_buf, pmsgbuf->data, *rcv_len);

                                        /* MC_RECEIVE_AND_WAIT(Deallocate)*/
  pvcb_rcv_wait->opcode = AP_M_RECEIVE_AND_WAIT;
  pvcb_rcv_wait->max_len= MESSAGE_SIZE;
  pvcb_rcv_wait->dptr   = (char *) pmsgbuf;
  APPC_C((long) vcbptr);                /* Call APPC                    */
#ifndef OS2_1_1
  pvcb_rcv_wait->rtn_status     = AP_NO;
#endif
  check_rc(vcbptr);

                                        /* MC_CONFIRMED                 */
  pvcb_confirmed->opcode= AP_M_CONFIRMED;
  APPC_C ((long) vcbptr);
  check_rc(vcbptr);
}

/*
 *                  Convert ASCII to EBCDIC
 */
convert_a2e(ascii_string, ebcdic_string, len)
char *ascii_string;
char *ebcdic_string;
int  len;
{
  VCB temp_vcb, *ptemp_vcb=&temp_vcb;
  int i;
  /* ASCII string is terminated by NULL or length
   * EBCDIC string is left-justified, padded to right with blanks
   */
  memset(ebcdic_string, ' ', len);
  for (i=0; i<len; i++)
    {
    if (!ascii_string[i])
      break;
    ebcdic_string[i]    = ascii_string[i];
    }
                                        /* Translate the ASCII to EBCDIC */
  memset(ptemp_vcb, 0, sizeof(VCB));
  temp_vcb.type.cnvt.opcode     = SV_CONVERT;
  temp_vcb.type.cnvt.direction  = SV_ASCII_TO_EBCDIC;
  temp_vcb.type.cnvt.char_set   = SV_AE;
  temp_vcb.type.cnvt.len        = len;
  temp_vcb.type.cnvt.source     = ebcdic_string;
  temp_vcb.type.cnvt.target     = ebcdic_string;
  ACSSVC_C ((long) ptemp_vcb);
}

/*
 *                  Check and Process the Return Code
 */
check_rc(vcbptr)
VCB *vcbptr;                            /* in: APPC request status      */
{
  unsigned short opcode;
  unsigned short appc_rc_p;
  union byte_swap {
           unsigned char c[4];
           unsigned long l;
           };
  union byte_swap t;
  union byte_swap appc_rc_s;

                                        /* convert response opcode      */
  opcode        =  (vcbptr->type.hdr.opcode << 8)
                 | (vcbptr->type.hdr.opcode >> 8);

                                        /* convert primary return code  */
  appc_rc_p     =  (vcbptr->type.hdr.primary_rc << 8)
                 | (vcbptr->type.hdr.primary_rc >> 8);

                                        /* convert secondary return code*/
  t.l           =  vcbptr->type.hdr.secondary_rc ;
  appc_rc_s.c[0]=  t.c[3];
  appc_rc_s.c[1]=  t.c[2];
  appc_rc_s.c[2]=  t.c[1];
  appc_rc_s.c[3]=  t.c[0];

  if (appc_rc_p != AP_OK)
    {
    printf("APPC ERROR, opcode=<%x>, primary rc=<%x>, secondary rc=<%lx>\n",
            opcode, appc_rc_p, appc_rc_s.l);
    exit(1);
    }
}

/*
 *------------------------ End of C program ----------------------------------
 */



#ifdef  DOCUMENT


APPC INTERFACE DISCUSSION
-------------------------

    The basic concept of APPC is built around the idea of "Conversations"
    between application programs.  A conversation is established when one
    application issues an Allocate Verb and the other issues a Receive_Allocate
    verb.  A conversation is a unique entity and has an associated temporary
    identity consisting of a Conversation ID within a Transaction ID.

    Each conversation is uniquely identified by:

        TRANSACTION ID
        CONVERSATION ID

    Many conversations may exist within a transaction thread, and many
    transaction threads may co-exist simultaneously. With the exception of the
    verbs which establish conversations, all APPC verb requests must specify
    the conversation which the request is for through the use of the
    Transaction ID/Conversation ID.

    In addition to satisfying the APPC requirements, programs written for IS/2
    must also satisfy the requirements of Host Link/2. The following discussion
    of the operational flow of the sample program demonstrates this.

SAMPLE PROGRAM - OPERATIONAL FLOW
---------------------------------

    Global variables are used for the configuration values specified in the
    APPC verb parameters and for the routing values placed in the
    "Host Link Transaction Header", accompanying each IS/2 message.

VARIABLES :

    cs2_rwa_orig_name   "HOST1TP1.HOST1"
    cs2_rwa_dest_name   "EAPI.CS2NODE"
    client_luname       "HOST1"
    client_tpname       "HOST1TP1"
    hostlink_luname     "NODE5"
    hostlink_tpname     "NODE5"
    hostlink_modename   "CS2MODE"

LOGIC:

    The mainline of the program calls the function, send_rcv(), each time
    it wishes to send an IS/2 message and receive a response, as follows:

    send_rcv(eapi_request_message,
         eapi_request_message_length,
         eapi_response_message_buffer,
         eapi_response_message_length)

    The send_rcv() function performs the APPC protocols with the Host Link/2 REM
    to send the message and receive the response from the IS/2 Server.  The
    function consists of two parts, Send and Receive.  Note that the API
    boundary between the application and the OS/2 Communication Manger is a
    control block interface.  For all APPC verb requests, the application
    passes the Communication Manager a pointer to a Verb Control Block (VCB)
    structure.  Some of the members of this structure are used to pass
    information from the application program to the Communication Manager,
    while members are used to return information.

Send Message logic:

    Build APPC Message

    First, because of an APPC requirement, a DOS Shared Memory Segment is
    allocated to be used as the Message Buffer.  The APPC Message is built
    into this area.  Building a message consists of creating the "Minimal
    DAE Header" followed by the IS/2 transaction message which was passed on
    the send_rcv() function call.  The "Minimal DAE Header" consists of two
    pieces of routing information built from global variables as follows:

        cs2_rwa_orig_name   "HOST1TP1.HOST1"
        cs2_rwa_dest_name   "EAPI.CS2NODE"

    The two parts of the origination name correspond respectively to the OS/2
    Communication Manager configuration as follows:

        "HOST1TP1"      Remotely Attachable Transaction Program Profile
        "HOST1"         Local LU Alias

    The two parts of the destination name correspond to the DAE ACB name of the
    IS/2 Server.

    APPC TP_STARTED verb

    This verb starts a transaction program thread for the LU and TP specified
    in the VCB, resulting in the local LU being able to initiate conversations
    with other LUs.  These two elements are derived from the global variables
    shown below:

        <client_luname>     "HOST1"
        <client_tpname>     "HOST1TP1"

    The <client_luname> corresponds to the Local LU Profile Name, "HOST1", in
    the OS/2 Communication Manager configuration.  The <client_tpname> does not
    seem to have a real function in the TP_STARTED request except perhaps as an
    informational identification.  The value coded in the global variable
    corresponds to the configuration in the Remotely Attachable Transaction
    Program Profiles section.  The TP Name must be specified in EBCDIC format
    while the LU Name is specified in ASCII.

    When control returns to the application, the VCB contains a uniquely
    assigned Transaction ID, which is then specified in all future APPC verb
    requests for this local LU.

    APPC MC_ALLOCATE verb

    This verb initiates a conversation between the local LU (this application)
    and a Partner LU (IS/2 Hostlink Gateway).  The Transaction ID returned from
    the previous APPC verb request, APPC_TP_STARTED, is placed in the VCB to
    establish the local LU.  The partner side identity of the conversation
    consists of three elements, Partner LU name, Partner TP name, and Modename.
    These three elements are placed into the VCB, their values derived from the
    following global variables:

        <hostlink_luname>   "NODE5"
        <hostlink_modename> "CS2MODE"
        <hostlink_tpname>   "NODE5"

    Two of the variables correspond to OS/2 Communication Manager configuration
    on the client node and the other corresponds with configuration on the
    Host Link node as follow:

        <hostlink_luname>   Partner LU Alias
        <hostlink_modename> Partner LU Modename Profile

        <hostlink_tpname>   Hostlink configuration - Remotely Attachable
                            Transaction Program Name Profile

    Note that the OS/2 APPC interface requires the TP Name and Modename in the
    VCB(APPC) to be in EBCDIC format rather than ASCII; however, the LU Name is
    specified in ASCII format.

    When control returns to the application, the VCB contains a uniquely
    assigned Conversation ID.  This, together with the Transaction Id, is
    specified in the VCB for all future verb requests against this conversation.

    APPC MC_SEND verb

    This verb causes the logical message, built in this function, to be sent to
    the partner application, Host Link.  The application places the Transaction
    ID and Conversation ID returned from previous requests into the VCB before
    this verb is executed.  It also places the address of the message buffer
    and the number of bytes to be sent.  When control returns to the
    application, the message has been queued.

    APPC MC_DEALLOCATE_CONFIRM verb

    This verb causes a request to be made with confirmation, that the
    conversation be deallocated.  The application places the Transaction ID and
    Conversation ID returned from previous requests into the VCB before this
    verb is executed.  When control returns to the application, the
    conversation is deallocated.

    APPC TP_ENDED verb

    This verb terminates the transaction thread between this application
    program and the Communication Manager. At this point, the Host Link Gateway
    has received the APPC message, and has routed it to the IS/2 server
    application from the "Host Transaction Header" information. The response 
    message will be returned to the Host Link Gateway based on that inforamtion.
    As a result, the Host Link Gateway will initiate a conversation with the
    client application and perform exactly the APPC protocol as has just been
    described.

Receive Logic :

    APPC MC_RECEIVE_ALLOCATE verb

    This verb causes the application to wait for the receipt of an incoming
    Allocate request for a particular Transaction Program ID and Modename. These
    two VCB elements, specified in EBCDIC format, are derived from the following
    global variables:

        <hostlink_tpname>   "HOST1TP1"
        <hostlink_modename> "CS2MODE"

    These values correspond to the following OS/2 Communication Manager
    configuration items:

        "HOST1TP1"      Remotely Attachable Transaction Program Profile
        "CS2MODE"       Partner LU Modename Profile

    When control returns to the application, a conversational session has been
    established with the Host Link Gateway and the VCB has uniquely assigned
    values for the Transaction ID and Conversation ID.  These values are placed
    in the VCB for all subsequent APPC verb requests against this conversation.

    APPC MC_RECEIVE verb

    This verb causes the application to receive the data which the Hostlink
    Gateway has sent.  The Transaction ID and Conversation ID are placed in the
    VCB before the verb is executed.  Also placed in the VCB is the address of
    the Receive Buffer and the maximum length message it can hold. This receive
    buffer is the DOS Shared Memory Segment which was obtained for the send
    message logic.

    When control returns to the application, the VCB return code indicates that
    data has been received, and the number of bytes is indicated in the received
    data length element.  The application copies the IS/2 reponse message after
    the "Minimal DAE Header" into the receive buffer which was passed on the
    send_rcv() function call.  The application also updates the received data
    length element passed by the calling function.

    APPC MC_RECEIVE verb

    This verb causes the application to receive the Deallocate_Confirm request
    from the Host Link Gateway.  All of the same elements in the VCB are set up
    as in the previous request.

    When control returns to the application, the VCB return code indicates that
    a Deallocate_Confirm request was received from the Host Link Gateway.

    APPC SEND_CONFIRMED verb

    This verb causes the Host Link Gateway to receive the confirmation
    acknowledgement to the Deallocate request.  The Transaction ID and
    Conversation ID are placed in the VCB prior to executing this verb. When
    control returns to the application, the conversation is deallocated.

    Return Control to Calling Function

This ends the sequence of operations performed by the send_rcv() function.

#endif  /* DOCUMENT */
/*
 *      End of File
 */
