Simple TCP Client connecting to a server using Telnet Line Mode Network Virtual Terminal

@NET
************************************************************************
* Network Configuration:  Simple TCP Client simulation                 *
*                                                                      *
* Description:  This WSim script will simulate one Simple TCP Client   *
*               connecting to a server, issuing a request to that      *
*               server, receiving data until the server closes the     *
*               connection, and then repeating the process.            *
*                                                                      *
*               The server to which this Simple TCP Client connects    *
*               is assumed to have the following characteristics:      *
*                1) requests to it must use ASCII code;                *
*                2) the end of a request is marked by the              *
*                   carriage return/line feed (CR/LF) sequence;        *
*                3) the server closes the connection when all response *
*                   data has been sent.                                *
*                                                                      *
*               Some values may need to be changed in this data set in *
*               order to operate in your environment.  They are        *
*               indicated by the "<== " string.                        *
*                                                                      *
************************************************************************
 
*----------------------------------------------------------------------*
* Network statement operands.                                          *
*----------------------------------------------------------------------*
STCPLNMD NTWRK HEAD='Telnet Line Mode NVT', * Set the title line
               CONRATE=YES,         * Print message rates on console
               OPTIONS=(MONCMND,debug),   * Network Options
               ITIME=1,             * Interval report every 1 minute
               BUFSIZE=32000,       * Specify buffer size
               THKTIME=UNLOCK,      * Wait for keyboard unlock
               UTI=100,             * User time interval is 1 second
               MSGTRACE=YES,        * Trace messages
               STLTRACE=YES,        * Trace messages
               TCPNAME=TCPIP        * <== Default name of the local
*                                   *     TCPIP virtual machine
*----------------------------------------------------------------------*
STCPDECK PATH  STCPDECK
*----------------------------------------------------------------------*
* Define the network resources.                                        *
*                                                                      *
* This is a TCP/IP connection with 1 simulated device.  You may        *
* add additional operands on the device if desired.  See the WSim      *
* Script Guide and Reference for details on valid operands.            *
*----------------------------------------------------------------------*
TCONN1   TCPIP
DEV010   DEV  TYPE=STCP,            * Simple TCP Client
              PORT=23,              * Server Port for connection
              SERVADDR=9.67.127.216,* Server IP Address for connect
              PATH=(STCPDECK)       * Path Sequence for this DEV
&ENDNET
 
&program=stcpprog
integer  shared nextnum
integer  nextid
integer  startpos
constant crlf '0D0A'x
constant ff 'FF'x
 
stcpdeck:  msgtxt
/*---------------------------------------------------------------------*
* The Message Generation deck.                                         *
*                                                                      *
* Generates requests for the server hypothesized in the network        *
*           description above, waits for the connection to be          *
*           closed, and then generates another request.                *
*---------------------------------------------------------------------*/
/*  Initialize table for translation to EBCDIC                        */
  asc2ebc = '00010203372D2E2F1605250B0C0D0E0F'X∥, /* 00-0F */
            '101112133C3D322618193F27221D351F'X∥, /* 10-1F */
            '405A7F7B5B6C507D4D5D5C4E6B604B61'X∥, /* 20-2F */
            'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'X∥, /* 30-3F */
            '7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'X∥, /* 40-4F */
            'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'X∥, /* 50-5F */
            '79818283848586878889919293949596'X∥, /* 60-6F */
            '979899A2A3A4A5A6A7A8A9C04FD0A107'X∥, /* 70-7F */
            '00010203372D2E2F1605250B0C0D0E0F'X∥, /* 80-8F */
            '101112133C3D322618193F27221D351F'X∥, /* 90-9F */
            '405A7F7B5B6C507D4D5D5C4E6B604B61'X∥, /* A0-AF */
            'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'X∥, /* B0-BF */
            '7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'X∥, /* C0-CF */
            'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'X∥, /* D0-DF */
            '79818283848586878889919293949596'X∥, /* E0-EF */
            '979899A2A3A4A5A6A7A8A9C04FD0A107';   /* F0-FF */
/*  Initialize table for translation to ASCII              */
  ebc2asc = '000102031A091A7F1A1A1A0B0C0D0E0F'X∥, /* 00-0F */
            '101112131A1A081A18191A1A1C1D1E1F'X∥, /* 10-1F */
            '1A1A1C1A1A0A171B1A1A1A1A1A050607'X∥, /* 20-2F */
            '1A1A161A1A1E1A041A1A1A1A14151A1A'X∥, /* 30-3F */
            '20A6E180EB909FE2AB8B9B2E3C282B7C'X∥, /* 40-4F */
            '26A9AA9CDBA599E3A89E21242A293B5E'X∥, /* 50-5F */
            '2D2FDFDC9ADDDE989DACBA2C255F3E3F'X∥, /* 60-6F */
            'D78894B0B1B2FCD6FB603A2340273D22'X∥, /* 70-7F */
            'F861626364656667686996A4F3AFAEC5'X∥, /* 80-8F */
            '8C6A6B6C6D6E6F7071729787CE93F1FE'X∥, /* 90-9F */
            'C87E737475767778797AEFC0DA5BF2F9'X∥, /* A0-AF */
            'B5B6FDB7B8B9E6BBBCBD8DD9BF5DD8C4'X∥, /* B0-BF */
            '7B414243444546474849CBCABEE8ECED'X∥, /* C0-CF */
            '7D4A4B4C4D4E4F505152A1ADF5F4A38F'X∥, /* D0-DF */
            '5CE7535455565758595AA0858EE9E4D1'X∥, /* E0-EF */
            '30313233343536373839B3F7F0FAA7FF'X;  /* F0-FF */
   /* clear data received each time data is transmitted */
 onout then
  data_in=''
   /* if no data is received, the connection is closed */
 onin buffer='' then abort
   /* store data received until data transmitted */
 onin then
  data_in=data_in∥buffer
 
 
 type '0D0A'x
 
 /* this script does not account for 'FF'x at the end of data    */
 /* look at each received stream of data and transmit a response */
 /* WILL and DO will be responded back with WONT and DONT        */
 /* the client will look like a Network Virtual Terminal         */
 /* the script assumes that there will be a prompt to check      */
 /* for to indicate the when the client can send data            */
 
  /* set look_for to what you expect to receive */
 look_for='login'
 call wait4it
 
 say devid() ' received login'
 nextid =nextnum                   /* index for user tables */
 nextnum=nextnum+1
 if nextnum=utblmax(ids) then
  nextnum=0
 type translate(utbl(ids,nextid),ebc2asc)∥crlf
 
  /* change 'Password' to what you expect to receive */
 look_for='Password'
 call wait4it
 
 say devid() ' received Password'
 type translate((utbl(pws,nextid)),ebc2asc)∥crlf
 
 do nextcmd=0 to utblmax(cmds)
 
      /* change '$' to what prompt you expect to receive */
  look_for='$'
 
  call wait4it
  say devid() ' sending COMMAND' utbl(cmds,nextcmd)
  type translate((utbl(cmds,nextcmd)),ebc2asc)∥crlf
 end
 suspend()
 quiesce
 endtxt
 
 
 wait4it: msgtxt
 
  /* wait for specific data deck -                             */
  /* set look_for to the data expected                         */
  /* check for FF in the data stream in case more negotiations */
  /* need to take place                                        */
 
 look_for = translate(look_for,ebc2asc)
 notfound = on
 do while notfound=on                 /* wait until data found   */
  delay(0)
  transmit and wait until onin
  if index(data_in,ff) > 0 then       /* look for commands first */
   call negotiat                      /* negotiate commands      */
  else
   if index(data_in,look_for) > 0 then  /* look for data next    */
    notfound = off
 end
 endtxt
 
 
 negotiat: msgtxt
 
  /* negotiation deck -                                         */
  /* parse through data for FF, look at next bytes for the      */
  /* commands and options                                       */
  /* looks for DO, DONT, WILL, WONT and DATA MARK commands      */
  /* looks for the Suppress Go Ahead option                     */
 
 data_out=''                          /* clear output buffer      */
 data_ck=''                           /* clear data parsing field */
 datalen=length(data_in)              /* get data length          */
 if datalen>1 then                    /* >1 implies not just FF   */
  do
   startpos=index(data_in,ff)         /* find FF in data          */
        /* start at command past ff */
   data_ck=substr(data_in,startpos+1,length(data_in)-startpos)
   fffound=on
   do while fffound=on
        /* get first byte of parsed data */
    data_byte=substr(data_ck,1,1)
        /* get second byte of parsed data */
    data_byte2=substr(data_ck,2,1)
    if data_byte='FD'x │ data_byte='FE'x then  /* DO or DONT    */
     if data_byte2='03'x then              /* Suppress GO Ahead */
      data_out=data_out∥'FFFB'x∥data_byte2  /* WILL */
     else                                  /* any other option  */
      data_out=data_out∥'FFFC'x∥data_byte2  /* WONT */
    else
     if data_byte='FC'x │ data_byte='FB'x then /* WILL or WONT  */
      if data_byte2='03'x then             /* Suppress GO Ahead */
       data_out=data_out∥'FFFD'x∥data_byte2 /* DO */
      else                                 /* any other option  */
       data_out=data_out∥'FFFE'x∥data_byte2 /* DONT */
     else
      if data_byte='F2'x then            /* data mark, synch    */
       do                                /* assume synch signal */
        data_in=buffer                   /* clear previous data */
        data_out=''                      /* no response sent    */
       end
    startpos=index(data_ck,ff)           /* look for ff         */
    if startpos=0 then
     do  /* no ff */
      fffound=off
      startpos=index(data_in,look_for)   /* search for specific data */
      if startpos>0 then                 /* found specific data      */
       notfound=off                      /* get out of loop          */
     end   /* no ff */
    else
       /* found ff, parse through commands */
     data_ck=substr(data_ck,startpos+1,length(data_ck)-startpos)
   end  /* fffound on */
   if data_out¬;='' then                  /* check if data to transmit */
    type data_out                        /* transmit data             */
  end
 endtxt
 
ids: msgutbl
 'userid1'
 'userid2'
 'userid3'
 'userid4'
 'userid5'
endutbl
 
pws: msgutbl
 'pswd1'
 'pswd2'
 'pswd3'
 'pswd4'
 'pswd5'
endutbl
 
cmds: msgutbl
 'cd /usr/lpp'
 'ls'
 'logout'
endutbl