!
! Server (receiver) side of RMIF RDP receive buffer test.
!
! <cntrl>   - The parent control macro object
! <port>    - The KNOWN port of the server.  Client uses any available port.
! <msgCnt>  - The number of messages the client (sender) will send out to verify
!             against the number of SET messages received.
!
! @bug     1193
! @author  Neon Ngo
! @since   NeXtMidas 2.5.1
!
startmacro O:cntrl L:port L:msgCnt[1000]
  switch WINDOW  window       GET DEF=0
  switch DEBUG   debug        GET DEF=false SDEF=true
  switch VERBOSE verbose      GET DEF=false SDEF=true
  switch STATEM  statemachine GET DEF=false SDEF=true

  if window EQ 0 then
    if statemachine then
      res window 64
    else
      invoke window nxm.sys.net.Rmif.DEFAULT_MAX_WINDOW
    endif
  endif

  invoke headless nxm.sys.lib.Shell.isHeadless()
  if statemachine and headless then
    info "SKIPPING ^reg.main.name because this test intermittently fails with /STATEM in HEADLESS mode."
  else
    set reg.cntrl cntrl   ! control macro

    set wait     5        ! Number of extra seconds to wait for extra messages
    set L:count  0        ! Total SET messages received
    set L:lostPackets  0  ! Total number of lost packets (messages)
    set L:index        1  ! index of next message (it could also be greater if we have packet loss)
    set L:outOfOrder   0  ! Total number of out of order packets (messages)
    set passFail "PASS"   ! Overall status

    if debug then
      file open/T/N logfile test-rmif-receiver.log
      timex now s:currentTime
      file write logfile "---------- ^reg.main.name (RECIVER) BEGIN TEST: ^currentTime ----------"
    endif

    pipe on
      ! startup RMIF server (to receive messages from client)
      rmif/id=RECEIVER/msgid=MAIN/xlog=rmifreceiver.log//PPT={WINDOW=^window}/STATEM=^statemachine/VERBOSE=^verbose ^port

      message FUNC=send ID=cntrl NAME=SERVER_STARTED INFO=0 DATA={TEST=PASS}
    pipe off

    if debug then
      timex now s:currentTime
      file write logfile "---------- ^reg.main.name (RECIVER) END TEST: ^currentTime ----------"
      file close logfile
      set logfile null
    endif
  endif
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 "START_TEST" then
    ! do nothing, waiting for client to send packets

  elseif msg.name eqs "STOP_TEST" then
    ! STOP_TEST is sent by cntrl macro
    ! check if we received correct # of messages
    calc L:expectedCount msgCnt lostPackets -
    set passFail TEST(count,EQ,expectedCount)
    message FUNC=send ID=cntrl NAME=SERVER_TEST &
            DATA={TEXT="received ^{msgCnt} messages-^{lostPackets} lost packets, count=^{count}.",TEST=^passFail}
    set outOfOrderResult TEST(outOfOrder,EQ,0)
    message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 &
            DATA={TEXT="zero out of order packets, got ^{outOfOrder}.",TEST=^outOfOrderResult}
    rem reg.cntrl  ! we put this in manually, now remove it
    pipe stop

  elseif msg.name eqs "SET" then
    calc L:count count 1 +
    result L:msgIndex msg.data.i
    if debug then
      file write logfile "^msgIndex"
    endif
    if msgIndex lt index then
      calc L:outOfOrder outOfOrder 1 +
      if debug then
        file write logfile "===> WARN: i=^{msgIndex} index=^{index} count=^{count} curTime=^{currentTime}"
      endif
      if passFail then   ! only print this warning and send test failure to control macro ONCE
       set passFail FAIL
       timex now s:currentTime
       warn "===> got i=^{msgIndex} expected index=^{index} count=^{count} curTime=^{currentTime}"
       message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 &
               DATA={TEXT="got message ^msgIndex < expected [^{index}]; count=^{count}.",TEST=^passFail}
      endif
    else ! i >= index
      calc L:index index 1 +
      if msgIndex gt index then
        set prevIndex index
        calc L:index msgIndex 1 +
        if debug then
          timex now s:currentTime
          file write logfile "===> INFO: i=^{msgIndex}  prevIndex=^{prevIndex} nextIndex=^{index} count=^{count}, curTime=^{currentTime}"
        endif
      endif
    endif

    if count GT msgCnt then
      ! received more messages than expected, mark overal test as failed
      set passFail FAIL
    elseif count EQ msgCnt-lostPackets then
      ! We should be done now, but wait a few seconds to see if extra messages are sent...
      set this.timer(0) wait
    endif

  elseif msg.name eqs "OPEN" then
    ! ignore
  elseif msg.name eqss "CLOSE" then
    ! ignore CLOSE and CLOSED messages
  elseif msg.name eqs "NULL" then
    ! ignore
  elseif msg.name eqs "TIMER" then
    ! done waiting for any extra messages
    message FUNC=send ID=cntrl NAME=SERVER_DONE DATA={TEST=^passFail}

  elseif msg.name eqs "LINKERR" then
    if msg.data.text EQSS "PKTLOST" then
      sedit msg.data.text L:beginSeq ELEM 3 " "
      sedit msg.data.text L:endSeq   ELEM 5 " "
      if endSeq LT beginSeq then
        ! NTN: account for case where RDP seq wraps around by adding max RDP sequence
        !      of 127 to endSeq to make below calculation correct in this scenario
        res L:endSeq endSeq+128
      endif
      calc L:lostPackets endSeq beginSeq - lostPackets +
      ! print warning for PKTLOST messages
      ! warn "Received a LINKERR: ^{msg.data.text}. count=^{count}"
      if debug then
        file write logfile "Received a LINKERR: ^{msg.data.text}. count=^{count} lostPackets=^{lostPackets}"
      endif
    else
      ! notify control macro of all other link error as a failed test
      message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 &
              DATA={TEXT="got unexpected LINKERR: ^{msg.data.text}.",TEST=FAIL}
    endif
  else
    ! notify control macro of unknown message as a failed test
    message FUNC=send ID=cntrl NAME=SERVER_TEST INFO=0 &
            DATA={TEXT="got unhandled message name=^msg.name data=^{msg.data}.",TEST=FAIL}
  endif
return