!
! Client part of RMIF crosstalk test
! Note: For user's with this scenario, they will have to set the requireOpen
!       boolean flag to true to prevent "unknown" remote's packets from getting
!       forwarded onto the macro via /PPT={REQUIREOPEN=TRUE} switch
!
! @author  Neon Ngo
! @bug 1548: RMIF cross talk
! @requires NeXtMidas 2.7.3 (for killing RMIF instance)
!
! <cntrl> - The parent macro object
! <port>  - The KNOWN port of the server 1 (server 2 port is port+1).
! <host>  - The KNOWN host of the server 1.
!
startmacro O:cntrl L:port S:host["localhost"]
  switch DEBUG   debug        GET DEF=false SDEF=true
  switch VERBOSE verbose      GET DEF=false SDEF=true
  switch STATEM  statemachine GET DEF=false SDEF=true

  set reg.cntrl cntrl
  set L:anyAvailablePort -1
  set cPort anyAvailablePort
  set rmifid     "RMIFCIENT1"

  set L:client1AckCount 0
  set L:client2AckCount 0
  set z:isclient2 false ! false for client1, true for client2
  set minExpectedAcks   31

  pipe on
    rmif/id=^{rmifid}/msgid=main/PPT={REQUIREOPEN=TRUE}/STATEM=^statemachine/VERBOSE=^verbose anyAvailablePort
    set cPort reg.^{rmifid}.port

    message FUNC=sendw ID=^{rmifid} NAME="OPEN" DATA={ID=CLIENT1,HP="^host:^port"}
  pipe off

endmacro

!******************************************************************************!
procedure processMessage m:msg
  if debug then
    say "^reg.main.name: Got message name=^msg.name fid=^msg.fid info=^msg.info data=^msg.data"
  endif

  if msg.name eqs "STOP_TEST" then
    set client1Tests TEST(client1AckCount,GE,minExpectedAcks)
    set client2Tests TEST(client2AckCount,GE,minExpectedAcks)
    message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="got ACKs from RMIF CLIENT1, count=^{client1AckCount}",TEST=^client1Tests}
    message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="got ACKs from RMIF CLIENT2, count=^{client2AckCount}",TEST=^client2Tests}

    rem reg.cntrl ! we put this in manually, now remove it
    pipe stop     ! sent by ctrl

  elseif msg.name eqs "START_TEST" then
    ! open channel to ACKs from remote for RMIF client1
    message FUNC=send ID=CLIENT1 NAME="ADDC" INFO=0 DATA="Q:ACK"

    ! set timer to switch to RMIF client2
    set this.timer(0) 5.0

  elseif msg.name eqs "TIMER" then
    set this.timer(0) 0

    ! kill RMIF instance (for testing only)
    message FUNC=SENDW ID=^{RMIFID} NAME=KILL_FOR_TESTING_ONLY  ! This message is for testing only, do not use in your macros.

    ! give a tiny amount of time for killed RMIF to shutdown
    pause 0.25

    ! verify that RMIF was KILLED for test case
    set isRmifNotInRegistry TEST(reg.^{RMIFID},nrexists)
    message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="killed RMIF client instance for testing",TEST=^isRmifNotInRegistry}

    ! pause so that at least one outstanding RDP packets from RMIF Server 1 to Client 1 gets reported as a LINKERR: packet drop
    pause 1.0

    ! start RMIF CLIENT2
    call startRMIFClient2

  elseif msg.name eqs "SWITCH_TO_CLIENT2" then
    if /debugc then say "====> switching to RMIF Client2...."
    set z:isClient2 true

  elseif msg.name eqs "OPENED" then
    message FUNC=send ID=cntrl NAME=CLIENT_STARTED INFO=0 DATA={TEST=PASS}
    if isClient2 then
      message FUNC=send ID=CLIENT2 NAME="ADDC" INFO=0 DATA="Q:ACK"
    endif

    ! following line is only for manual standalone testing
    if cntrl isNull then message FUNC=send ID=main NAME=START_TEST info=0

  elseif msg.name eqss "CLOSE" then
    ! ignore CLOSE and CLOSED messages

  elseif msg.name eqs "NULL"
    ! ignore

  elseif msg.name eqs "ACK" then
    if /debugc then say "Got ACK name=^msg.name from=^msg.fid info=^msg.info data=^msg.data"

    if isClient2 isTrue then
      calc L:client2AckCount client2AckCount 1 +
      if msg.data.src neqs "Server2" then
        message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="CLIENT2 got ACK from invalid server! data=^msg.data",TEST=FAIL}
      elseif CALC(client2AckCount,10,mod) eq 1
        ! only send pass client test message to control macro for every 10th ACK
        message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="CLIENT2 got ACK from server2. count=^client2AckCount",TEST=PASS}
      endif

      ! got expect # of ACKs from RMIF Client2, test case is done
      if client2AckCount eq minExpectedAcks then
        message FUNC=send ID=cntrl NAME=CLIENT_DONE DATA={TEST=TRUE,COMMENT="client2 AckCount=^client2AckCount"}
      endif
    else  ! else client 1
      calc L:client1AckCount client1AckCount 1 +
      if msg.data.src neqs "Server1" then
        message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="CLIENT1 got ACK from invalid server! data=^msg.data",TEST=FAIL}
      elseif CALC(client1AckCount,10,mod) eq 1
        ! only send pass client test message to control macro for every 10th ACK
        message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="CLIENT1 got ACK from server1. count=^client1AckCount",TEST=PASS}
      endif
    endif

  elseif msg.name eqs "LINKERR"
    WARN "CLIENT: Received a LINKERR. ^msg.data"
    ! notify control macro of link error
    message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="got LINKERR Message=^{msg.data.text}",TEST=FAIL}

  else
    message FUNC=send ID=cntrl NAME=CLIENT_TEST INFO=0 DATA={TEXT="got unhandled message name=^msg.name data=^msg.data",TEST=FALSE}
  endif
return

!******************************************************************************!
procedure startRMIFClient2
  set rmifid     "RMIFCIENT2"
  message FUNC=send ID=main NAME="SWITCH_TO_CLIENT2"

  rmif/bg/id=^{rmifid}/msgid=main/PPT={REQUIREOPEN=TRUE}/STATEM=^statemachine/VERBOSE=^verbose cport
  if reg.^{rmifid} REXISTS then
    info "Restarted RMIF on port ^reg.^{rmifid}.port"
  else
    warn "FAILED to restart RMIF client for testing"
  endif

  calc L:server2port port 1 +
  message FUNC=sendw ID=^{rmifid} NAME="OPEN" DATA={ID=CLIENT2,HP="^host:^server2port"}
return
