Previous Topic: Assembler TCP/IP Client ProgramNext Topic: CA ADS Examples


Assembler TCP/IP Generic Listener Server Program

TITLE 'Sample ASSEMBLER listener TCP/IP'
* ASMLIS   RENT EP=ASMLISEP
******************************************************************
* The following program is an example of a TCP/IP generic        *
* listener server program written in Assembler.                  *
* The processing is the following:                               *
*  - read a message from the client (first 4 bytes = data length)*
*  - send the message back to the client program                 *
*  - if the message text is equal to "STOP" or if the connection *
*    is closed, then it closes its socket and return to the      *
*    generic listener service.                                   *
*  - if the message text is not equal to "STOP", then it returns *
*    to the generic listener service without closing its socket. *
******************************************************************
*---------------------------------------------------------------------*
         MACRO
&LABEL.   #SAVEREG
&LABEL.   ST    R12,0(,R13)         Save R12
         ST    R14,4(,R13)         Save R14
         STM   R2,R8,8(R13)        Save R2-R8
         LA    R13,9*4(,R13)
         MEND
*---------------------------------------------------------------------*
         MACRO
&LABEL.   #RESTREG
&LABEL.   LA    R12,9*4             Get register stack entry length
         SR    R13,R12             Get A(previous register stack entry)
         L     R12,0(,R13)         Restore R12
         L     R14,4(,R13)         Restore R14
         LM    R2,R8,8(R13)        Restore R2-R8
         MEND
*---------------------------------------------------------------------*
         MACRO
&LABEL.   MSGTXT &TXT.
         LCLC  &TMP.
&TMP.     SETC  '&SYSNDX'.
&LABEL.   DC    AL1(L2&TMP).
L1&TMP.   DC    C&TXT.
L2&TMP.   EQU   *-L1&TMP.
         MEND
*---------------------------------------------------------------------*
ASMLIS CSECT
         @MODE MODE=IDMSDC
         #MOPT CSECT=ASMLIS,ENV=USER,RMODE=ANY,AMODE=ANY
         ENTRY ASMLISEP
ASMLISEP DS    0H
         BALR  R12,0
         BCTR  R12,0
         BCTR  R12,0
         USING ASMLISEP,R12
GETWORK  #GETSTG TYPE=(USER,SHORT),ADDR=(R1),PLIST=*,INIT=X'0',        X
               LEN=WORKAREL
         LR    R11,R1
         USING WORKAREA,R11
         LA    R13,REGSTACK
         MVI   OUTAREA,L'OUTAREAT
         MVC   OVRLOG,=X'8000000000'
         MVC   OVRLOGCO,=X'C000000000'
         MVC   WKCLEAR,=XL8'0F0F0F0F0F0F0F0F'
         MVC   TRTAB,=CL16'0123456789ABCDEF'
         MVC   TRTABX,=XL6'FAFBFCFDFEFF'
*
TCPSTART DS    0H
******************************************************************
* Read the first 4 bytes: will contain the remaining length      *
******************************************************************
*
         LA    R5,4
         ST    R5,WK_LEN                Set read length to 4.
         XR    R5,R5
         ST    R5,BUFLEN                Set buffer length to 0.
         LA    R7,BUFFER_A              R7 -> Buffer array.
         BAL   R4,TCPREAD               Perform the read.
*
         CLC   BUFLEN(4),=F'80'          Incoming buffer less than 80?
         BL    READCLI                    Y. Read client message.
         LA    R1,MSG04                   N. Message too long,issue
         L     R15,=A(DISLINE)               error message
         BALR  R14,R15                             and
         B     TCPCLOSE                        close socket.
READCLI  DS    0H
         MVC   WK_LEN,BUFLEN             client msg length=read length.
         LA    R7,BUFFER_A+4             R7 -> client message to read.
         BAL   R4,TCPREAD                Read client message.
*
         XC    OUTAREAT(L'OUTAREAT),OUTAREAT  Clear out message area
         MVC   OUTAREAT(15),=C'Buffer Length: '   Build
         L     R1,BUFLEN                            buffer length
         CVD   R1,WORK1                               display
         OI    WORK1+7,X'0F'
         UNPK  WORK2(9),WORK1+3(5)
         MVC   WORK2(8),WORK2+1    Shift value 1 byte to the left.
         MVI   WORK2+8,C' '
         MVI   WORK2+9,C' '        Clear last 2 bytes from WORK2 field.
         MVC   OUTAREAT+15(2),WORK2+6
         LA    R1,OUTAREA            Display read buffer length.
         L     R15,=A(DISLINE)
         BALR  R14,R15
         XC    OUTAREAT(L'OUTAREAT),OUTAREAT        Build
         MVC   OUTAREAT(8),=C'Buffer: '                buffer
         MVC   OUTAREAT+8,BUFTXT80                       display.
         LA    R1,OUTAREA            Display read buffer text.
         L     R15,=A(DISLINE)
         BALR  R14,R15
******************************************************************
* Send the message back to the client                            *
******************************************************************
         MVC   WK_LEN,BUFLEN
         L     R5,WK_LEN
         LA    R5,4(R5)               Include 1st 4 bytes
         ST    R5,WK_LEN                 in message length.
         LA    R7,BUFFER_A             R7 -> Buffer array.
         BAL   R4,TCPWRITE             Perform the write.
         CLC   BUFLEN,=F'4'            Incoming buffer length = 4?
         BNE   LISEXIT                   N. Return.
         CLC   BUFTXT04,=C'STOP'         Y. Stop listener?
         BNE   LISEXIT                      N. Return.
         B     TCPCLOSE                     Y. Close socket.
******************************************************************
* Routine to read a message from the client                      *
******************************************************************
TCPREAD  DS    0H
         LA    R1,MSG01                  Display socket read function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
        #SOCKET  READ,SOCK=S_NEWSOC,BUFFER=(R7),                       X
               RETLEN=RETLEN,BUFFERL=WK_LEN,                           X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG06                  Display results of read.
         L     R15,=A(DISRC)
         BALR  R14,R15                   Display the 3 return codes.
         CLC   RETCODE,=F'0'             Successful read?
         BNE   TCPCLOSE                    N.  Error close socket.
         CLC   RETLEN,=F'0'              Anything left to read?
         BE    TCPCLOSE                   N.Close socket.
         A     R7,RETLEN                 Adjust buffer array pointer
         L     R5,WK_LEN                  and
         S     R5,RETLEN                     read length
         ST    R5,WK_LEN                        with message length.
         CLI   WK_LEN,0
         BNE   TCPREAD
         BR    R4
******************************************************************
* Routine to send a message to the client                        *
******************************************************************
TCPWRITE DS    0H
         LA    R1,MSG02                Display socket write function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
        #SOCKET WRITE,SOCK=S_NEWSOC,BUFFER=(R7),                       X
               RETLEN=RETLEN,BUFFERL=WK_LEN,                           X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG05                Display results of socket write.
         L     R15,=A(DISRC)
         BALR  R14,R15                 Display the 3 return codes.
*
         CLC   RETCODE,=F'0'           Write successful?
         BNE   TCPCLOSE                 N. Close socket.
         A     R7,RETLEN               Adjust buffer array
         L     R5,WK_LEN                and
         S     R5,RETLEN                 write length
         ST    R5,WK_LEN                  with message length.
         CLI   WK_LEN,0                Anything left to write?
         BNE   TCPWRITE                 Y. Loop back.
         BR    R4                       N. Return.
******************************************************************
* Close the socket and exit                                      *
******************************************************************
TCPCLOSE DS    0H
         #SOCKET CLOSE,SOCK=S_NEWSOC,                                  X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG07                Display socket close function.
         L     R15,=A(DISRC)
         BALR  R14,R15                 Display the 3 return codes.
*
LISEXIT  DS    0H
*
         #RETURN                            Return to caller
         #BALI
*
         DROP  R12
         LTORG
         TITLE 'ASMLIS01 - DISRC : DISPLAY THE RETURN CODES'
*---------------------------------------------------------------------*
*-  Rotuine to display the 3 return values from any TCP/IP calls.    -*
*-  Input : RETCODE, ERRNO and RSNCODE from the workarea             -*
*-          R1 -> String to start with (e.g.MSGTXT FORMAT)           -*
*---------------------------------------------------------------------*
DISRC    DS    0H
*
         #SAVEREG
*
         LR    R12,R15
         USING DISRC,R12
*
         MVI   OUTAREAT,C' '
         MVC   OUTAREAT+1(L'OUTAREAT-1),OUTAREAT
*
         XR    R2,R2
         IC    R2,0(,R1)               Get message length.
         BCTR  R2,0                    -1 FOR EX.
         EX    R2,DISRCEX              Copy text.
         LA    R2,1+1+OUTAREAT(R2)     Point to next free space.
*
         MVC   WORK1(4),RETCODE
         UNPK  WORK2(9),WORK1(5)
         NC    WORK2(8),WKCLEAR
         TR    WORK2(8),TRTAB
         MVC   0(8,R2),=CL8'RETCODE='
         MVC   8(8,R2),WORK2
*
         L     R15,ERRNO
         CVD   R15,WORK1
         OI    WORK1+7,X'0F'
         UNPK  WORK2(10),WORK1+2(6)
         LA    R14,WORK2
         LA    R15,9
DISRC01  DS    0H
         CLI   0(R14),C'0'
         BNE   DISRC02
         MVI   0(R14),C' '
         LA    R14,1(,R14)
         BCT   R15,DISRC01
DISRC02  DS    0H
         MVC   17(8,R2),=CL6'ERRNO='
         MVC   23(8,R2),WORK2+2
*
         MVC   WORK1(4),RSNCODE
         UNPK  WORK2(9),WORK1(5)
         NC    WORK2(8),WKCLEAR
         TR    WORK2(8),TRTAB
         MVC   32(8,R2),=CL8'RSNCODE='
         MVC   40(8,R2),WORK2
*
         LA    R1,OUTAREA
         L     R15,=A(DISLINE)
         BALR  R14,R15
*
         #RESTREG
*
         BR    R14
*
         DROP  R12
*
DISRCEX  MVC   OUTAREAT(0),1(R1)       Copy text
         LTORG
         TITLE 'ASMLIS - DISLINE : WRITE MESSAGE LINE TO LOG'
*---------------------------------------------------------------------*
*-  Subroutine to write a message line to the log.                   -*
*-  Input : R1 = A(output message) (first byte = message length)     -*
*-----------------------------------------------------------------
DISLINE  DS    0H
         #SAVEREG
*
         LR    R12,R15
         USING DISLINE,R12
         LR    R3,R1                   Get parm in R3.
*
         #WTL  MSGID=M#999043,MSGDICT=NO,OVRIDES=OVRLOG,               X
               PARMS=((R3)),RGSV=(R2-R8)
*
         #RESTREG
*
         BR    R14
*
         DROP  R12
M#999043 DC  PL4'9990430'
         LTORG
*
*
MSG01 MSGTXT 'Starting read.'
MSG02 MSGTXT 'Starting write.'
MSG03 MSGTXT 'Closing Socket.'
MSG04 MSGTXT 'Data length too long.'
MSG05 MSGTXT 'WRITE call:'
MSG06 MSGTXT 'READ call:'
MSG07 MSGTXT 'CLOSE call:'
         DS    0F
         TITLE 'ASMLIS - WORK AREA'
WORKAREA DSECT
*----------------------------------*
*-  DYNAMIC DATA                  -*
*----------------------------------*
SYSPLIST DS    16F
REGSTACK DS    32F
*
         DS    0D
WORK1    DC    XL10'00'
         DS    0D
WORK2    DC    XL10'00'            AT LEAST 10 BYTES DOUBLEWORD ALIGNED
*
*
WK_LEN   DS    F
*
*
SOCKADDC DS    (SIN#LEN)X          SOCKADDR for the LISTENER
S_NEWSOC DS    F
RETLEN   DS    F
RETCODE  DS    F
ERRNO    DS    F
RSNCODE  DS    F
*
*
         DS    0F
BUFFER   DS    CL84
         ORG   BUFFER
BUFLEN   DS    F
BUFTXT80 DS    CL80
         ORG   BUFTXT80
BUFTXT04 DS    CL4
BUFTXT76 DS    CL76
         ORG   BUFFER
BUFFER_A DS    CL84
*
*
OUTAREA  DS    X
OUTAREAT DC    CL80' '             OUTPUT AREA
         DS    0D
*
*
*----------------------------------*
*-  STATIC DATA                   -*
*----------------------------------*
*
OVRLOG   DS    X'8000000000'       #WTL TO LOG ONLY
OVRLOGCO DS    X'C000000000'       #WTL TO LOG + CONSOLE
*
WKCLEAR  DS    XL8'0F0F0F0F0F0F0F0F'
TRTAB    DS    CL16'0123456789ABCDEF'
TRTABX   DS    XL6'FAFBFCFDFEFF'
*
WORKAREL EQU   *-WORKAREA
*
*---------------------------------------------------------------------*
*-  TCP/IP TABLES                                                    -*
*---------------------------------------------------------------------*
*
         #SOCKET TCPIPDEF
         #SOCKET ERRNOS
*
         END   ASMLISEP