Appendix D: xfNetLink Synergy Sample Code

This code sample illustrates how to use RXSUBR and the RX_xxx routines in a Synergy client application. Synclt.dbl calls a subroutine named HELLO on the server.

Client application (synclt.dbl)

The synclt program prompts you for the server name and port number, calls %RX_START_REMOTE to request a remote execution session, and then calls %RXSUBR to make the remote call. It calls the subroutine HELLO on the remote server, which returns the phrase “Hello, <your name>.” Then the program closes down the session with RX_SHUTDOWN_REMOTE. Synclt also includes error handling code that illustrates how to use RX_GET_HALTINFO and RX_GET_ERRINFO.

If you want to try running this program, see the instructions following the code sample. This code is included in the dbl\examples directory in your Synergy/DE distribution.

.main synclt
; Synergy client routine
.define CHAN            ,1                  ; display channel
.define HELLO_MODULE    ,"hello_routine"    ; Remote procedure name
; Modify the following define statement for your system
.define NAME            ,"Mark"             ; Name to display
external function
    rc_api        ,^val
.include "DBLDIR:rxapi.def"
.define RX_ERR_DEF
record errinforec
.include "DBLDIR:rxerr.def"
.undefine RX_ERR_DEF
.define RX_FATAL_DEF
record haltinforec
.include "DBLDIR:rxerr.def"
.undefine RX_FATAL_DEF
.align
record
    netid          ,i4              ; network connection ID
    status         ,i4              ; return status
    syserr         ,i4              ; returned system error
    port           ,i4              ; port number
record
    aport          ,a4
    machine        ,a80
    message        ,a30             ; message text
.proc
    xcall flags(4020, 1)
    open(CHAN, O:C, "TT:")
    display(1, "Enter machine: ")
    reads(1, machine, done)
    display(1, "Enter port number: ")
    reads(1, aport, done)
    onerror done
    port = aport
    offerror
    status = %RX_START_REMOTE(netid, machine, port) ; Start xfServerPlus
    syserr = %syserr
    if (status)
      begin
        writes(1, "Unable to connect to remote session:")
        writes(1, "         status = " + %string(status))
        writes(1, "         syserr = " + %string(syserr))
        goto done
      end
    call do_hello                           ; Call subroutine
done,
    if (netid)
         xcall RX_SHUTDOWN_REMOTE(netid)    ; Stop xfServerPlus
    close(CHAN)
    stop
do_hello,       ; Subroutine to call the remote procedure and handle errors
    display(CHAN, $SCR_CLR(SCREEN), $SCR_MOV(2,20))
    clear message
    ;trap fatal and timeout separately, then trap all others
    onerror ($ERR_XFHALT) handle_fatal, ($ERR_TIMOUT) handle_timeout, handle_other  
    xcall rxsubr(netid, HELLO_MODULE, NAME, message)
    offerror
    display(CHAN, "**** " + %atrim(message) + " ****")
    return
; Error handling routines
handle_fatal,
    offerror
    writes(CHAN, "Fatal error trapped")
    xcall RX_GET_HALTINFO(netid, haltinforec)
    call disp_halt
    goto done
handle_timeout,
    offerror
    writes(CHAN, "Timeout error trapped")
    xcall RX_GET_ERRINFO(netid, errinforec)
    call disp_err
    goto done
handle_other,
    offerror
    writes(CHAN, "Error trapped")
    xcall RX_GET_ERRINFO(netid, errinforec)
    call disp_err
    goto done
disp_halt,
    writes(CHAN, "Subroutine:     " + %atrim(haltinforec.rx_fatalerror.subroutine_name))
    writes(CHAN, "Error line #:   " + %string(haltinforec.rx_fatalerror.error_line_number))
    writes(CHAN, "Error #:        " + %string(haltinforec.rx_fatalerror.error_num))
    writes(CHAN, "System Error #: " + %string(haltinforec.rx_fatalerror.error_num))
    writes(CHAN, "Program name:   " + %atrim(haltinforec.rx_fatalerror.prog_name))
    writes(CHAN, "Error text:     " + %atrim(haltinforec.rx_fatalerror.error_text))
        return
disp_err,
    writes(CHAN, "Method ID:      " + %atrim(errinforec.rx_stderror.method_id))
    writes(CHAN, "# of errors:    " + %string(errinforec.rx_stderror.num_of_errors))
    writes(CHAN, "Error #:        " + %string(errinforec.rx_stderror.error_num))
    writes(CHAN, "Description:    " + %atrim(errinforec.rx_stderror.description))
    writes(CHAN, "Clarification:  " + %atrim(errinforec.rx_stderror.clarifying_desc))
    return
.end

Server-side code (HELLO subroutine)

The HELLO subroutine is the remote routine (on the server) called by synclt. This code is included in the dbl\examples directory in your Synergy/DE distribution.

.subroutine hello
;Arguments
     a_name       ,a
     a_message    ,a
.define     HELLO       ,"Hello "
.define     NONAME      ,"No name passed "
.proc
     if (^passed(a_name)) then
          a_message = %atrim(HELLO + a_name)
     else
          a_message = NONAME
     xreturn
.end

Running the hello program

1. Create an ELB or shared image named hello.elb containing the HELLO subroutine. Put the ELB on your server machine (the machine that xfServerPlus is running on).
2. Start the Method Definition Utility and create a method in the SMC for the HELLO subroutine. (See Using the MDU to define Synergy methods for instructions.) Include the following information in your MDU entry:

Method name = hello_routine

Method ID = hello_routine (this is copied from the method name)

Routine name = hello

ELB/shared image name = DBLDIR:hello (change the logical if necessary)

Return type = No return value

The subroutine has two parameters, name and message. Set them up as follows:

Parameter name = name

Data type = Alpha

Length = 20

Data passed = In

Pass by = Descriptor

Required

Parameter name = message

Data type = Alpha

Length = 30

Data passed = In/Out

Pass by = Descriptor

Required

3. If xfServerPlus is not already running, start it on the server machine. See one of the following for details:
4. Put synclt.dbl on the client machine and edit the NAME identifier.
5. Compile and link synclt.dbl.
6. Run synclt.dbr. You’ll be prompted to enter the machine name and port where xfServerPlus is running.