!
! Server part of RMIF test
!
! @author  Neon Ngo
! @bug     2017 OPENED remote clients do not timeout sometimes
!
! <cntrl> - The parent macro object
! <port>  - The port of the server.
!
startmacro o:cntrl L:port
  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:count           0
  set L:expLinkerrCount 0
  set L:linkerrCount    0
  set messageInterval   1.0
  invoke ACK_FUNC nxm.sys.net.Rmif.ACK
  set clientOpenTime 0  ! time when connection is opened to client
  set newTimeout     10 ! reduce timeout (sec) for test case
  set dropTimeout    17 ! RMIF timeout is 10 + 5 (for RDP retries) + 2 (sec) for wiggle room

  pipe on
    rmif/id=RMIFSRV/msgid=main/PPT={TIMEOUT=^newTimeout}/STATEM=^statemachine/VERBOSE=^verbose ^port
    message FUNC=send ID=cntrl NAME=SERVER_STARTED INFO=0 DATA={TEST=PASS}

    ! using two timers for this test (1st to send out ACKs and 2nd to stop test case)
    set this.timers 2

    ! following line is only for manual standalone testing
    if cntrl isNull then message FUNC=send ID=main NAME=START_TEST
  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 testResult TEST(linkerrCount,LE,0)
    message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 DATA={TEXT="unexpected LINKERRs=^linkerrCount expected LINKERRs=^expLinkerrCount",TEST=^testResult}
    rem reg.cntrl ! we put this in manually, now remove it
    pipe stop     ! sent by ctrl

  elseif msg.name eqs "START_TEST" then
    ! start timer to send ACK messages periodically
    set this.timer(0) messageInterval

  elseif msg.name eqs "TIMER" then
    if msg.info eq 1 then
      ! got timer2, send server test finish to control macro and break, return from procedure
      if /debugs then say "^reg.main.name: Got TIMER 2 from=^msg.fid info=^msg.info data=^msg.data"
      message FUNC=send ID=cntrl NAME=SERVER_DONE INFO=0 DATA={TEST=TRUE}
      return
    endif

    calc L:count count 1 +
    timex now curTime
    if /debugs then say "^reg.main.name: Got TIMER 1: ^count at time=^curTime  sending ACKs to RMIF servers"
    message send RMIFSRV ,, "ACK",, "{X=^count,UPDATE=s:^curTime}"

  elseif msg.name eqs "OPEN" then
    ! start timer to STOP server side of test (dropTime + 10 seconds)
    set this.timer(1) dropTimeout+10

    timex now clientOpenTime
    message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 DATA={TEXT="got open from RMIF client.",TEST=TRUE}

  elseif msg.name eqss "CLOSE" then
    if /debugs then say "^reg.main.name: Got ^msg.name from ^msg data=^msg.data"
    ! ignore CLOSE and CLOSED messages

  elseif msg.name eqs "LINKERR" then
    timex now curTime
    calc timeDiff curTime clientOpenTime -
    if /debugs then say  "DEBUG: Received a LINKERR. ^msg data=^msg.data timeDiff=^timeDiff clientOpenTime=^{clientOpenTime}..."

    ! ignore packet drop (PKTDROP link errors for ACK packets) within dropTimeout period
    res s:text ^{msg.data.text}
    if timeDiff > dropTimeout OR ^msg.data.packet isNull OR text.startsWith("PKTDROP") isFalse OR ^msg.data.packet.func neq ^ACK_FUNC then
      warning "got a LINKERR. ^msg data=^msg.data timeDiff=^timeDiff"
      calc L:linkerrCount linkerrCount 1 +
      message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 DATA={TEXT="got unexpected LINK ERROR: ^msg ^{msg.data}",TEST=FALSE}
    else
      calc L:expLinkerrCount expLinkerrCount 1 +
    endif

  elseif msg.name eqs "NULL"
    ! ignore

  else
    say "^reg.main.name: Got unknown msg from ^msg data=^msg.data"
    message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 DATA={TEXT="got unhandled message name=^msg.name data=^msg.data",TEST=FALSE}
  endif
return
