#!/bin/sh

# Tests forwarding of payloads from one end-point to another, and the
# reverse of that scenario. This also tests "record session to a file"
# functionality and subsequent decoding of the audio using extractaudio.
#
# The setup is as follows. We setup 3 rtpproxy instances:
#
# +-----+      +-----+      +-----+
# |Gen.O|<---->| Fwd |<---->|Gen.A|
# +-----+      +-----+      +-----+
#
# Uni-directional RTP streams are generated by the Gen.O and Gen.A
# instances simultaneously and they are delivered to the Fwd instance.
# Each of the Gen.O and Gen.A instances also records incoming streams into
# disk files, Gen.O in the AdHoc format and Gen.A in the PCAP format. All
# streams are then decoded and checksum is compared to the reference value.
# 
# We also setup several streams (for all supported codecs) and enable
# re-packetization from 10ms for most codecs (20ms for GSM) to 40ms in one
# direction and 60ms in the other.

BASEDIR="`dirname "${0}"`/.."
. "${BASEDIR}/functions"

TEST_CODECS="0 3 8 18 9"
#TEST_CODECS="9 9 9 9 9"
FWD_SPORT=13342
GENO_SPORT=12000
GENA_SPORT=15000
RTPP_DEBUG_LVL="dbug"

rotate_CODECSA() {
  first_codec="${1}"
  shift
  CODECSA="${@} ${first_codec}"
}

setup_gen() {
  direction="${1}"
  START_PORT="${2}"
  shift 2
  PORT=${START_PORT}
  i=1
  for codec in ${1} ${2}
  do
    CID="forwarding1_${direction}_${i}"
    SED_TRANS="s|%%PORT1%%|${PORT}| ; s|%%PORT2%%|${TRASH_PORT1}| ; s|%%CALLID%%|${CID}| ; s|%%CODEC%%|${codec}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.rec${direction}.input
    PORT=$((${PORT} + 4))
    i=$((${i}+1))
  done
  sleep 1
  i=1
  for codec in ${1} ${2}
  do
    CID="forwarding1_${direction}_${i}"
    SED_TRANS="s|%%CODEC%%|${codec}| ; s|%%CALLID%%|${CID}| ; s|%%NTIMES%%|4|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.gen${direction}.input
    i=$((${i}+1))
  done
  sleep 25
  i=1
  for codec in ${1} ${2}
  do
    CID="forwarding1_${direction}_${i}"
    SED_TRANS="s|%%CODEC%%|${codec}| ; s|%%CALLID%%|${CID}| ; s|%%NTIMES%%|1|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.gen${direction}.input
    i=$((${i}+1))
  done
  sleep 8
  i=1
  for codec in ${1} ${2}
  do
    CID="forwarding1_${direction}_${i}"
    SED_TRANS="s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.sstats.input
    i=$((${i}+1))
  done
  cat session_timeouts/stats.input forwarding/forwarding1.stats.input
}

setup_fwd() {
  START_PORTO=$((${1} + 2))
  START_PORTA=$((${2} + 2))
  shift 2
  i=1
  PORTO=${START_PORTO}
  PORTA=${START_PORTA}
  for codec in ${1}
  do
    CID="forwarding1_${i}"
    SED_TRANS="s|%%PORTO%%|${PORTO}| ; s|%%PORTA%%|${PORTA}| ; s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.input
    PORTO=$((${PORTO} + 4))
    PORTA=$((${PORTA} + 4))
    i=$((${i}+1))
  done
  for codec in ${2}
  do
    CID="forwarding1_${i}"
    SED_TRANS="s|%%PORTO%%|${PORTO}| ; s|%%PORTA%%|${PORTA}| ; s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.repack.input
    PORTO=$((${PORTO} + 4))
    PORTA=$((${PORTA} + 4))
    i=$((${i}+1))
  done
  while [ ${i} -gt 1 ]
  do
    i=$((${i}-1))
    CID="forwarding1_${i}"
    PORTA=$((1024 + (${i} * 8)))
    PORTO=$((${PORTA} + 2))
    PORT6A=$((${PORTA} + 4))
    PORT6O=$((${PORTA} + 6))
    SED_TRANS="s|%%PORTO%%|${PORTO}| ; s|%%PORTA%%|${PORTA}| ; \
     s|%%PORT6O%%|${PORT6O}| ; s|%%PORT6A%%|${PORT6A}| ; s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.copy.input
  done
  sleep 6
  i=1
  PORTO=${START_PORTO}
  PORTA=${START_PORTA}
  for codec in ${1}
  do
    CID="forwarding1_${i}"
    SED_TRANS="s|%%PORTO%%|${PORTO}| ; s|%%PORTA%%|${PORTA}| ; s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.relatch.input
    PORTO=$((${PORTO} + 4))
    PORTA=$((${PORTA} + 4))
    i=$((${i}+1))
  done
  for codec in ${2}
  do
    CID="forwarding1_${i}"
    SED_TRANS="s|%%PORTO%%|${PORTO}| ; s|%%PORTA%%|${PORTA}| ; s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.repack.input
    PORTO=$((${PORTO} + 4))
    PORTA=$((${PORTA} + 4))
    i=$((${i}+1))
  done
  sleep 30
  j=$((${i}-1))
  while [ ${j} -gt $((${i}/2)) ]
  do
    CID="forwarding1_${j}"
    SED_TRANS="s|%%CALLID%%|${CID}|"
    ${SED} "${SED_TRANS}" forwarding/forwarding1.sstats.input forwarding/forwarding1.delete.input
    j=$((${j} - 1))
  done  
  cat session_timeouts/stats.input forwarding/forwarding1.stats.input
}

cumnlost=0
MAX_CUMNLOST=5

verify_results()
{
  direction="${1}"
  shift
  i=1
  for codec in ${1} ${2}
  do
    rm -f forwarding1.${codec}.wav
    ${EXTRACTAUDIO} -n -s forwarding1_${direction}_${i}=from_tag_1 forwarding1.${codec}.wav | \
      grep -v 'delta ' | tee forwarding1.${codec}.eout
    report "extractaudio forwarding1_${direction}_${i} forwarding1.${codec}.wav"
    nlost=`grep plost= forwarding1.${codec}.eout | sed 's|.* plost=||'`
    if [ ${nlost} -eq 0 ]
    then
      sha256_verify forwarding1.${codec}.wav forwarding/forwarding1.checksums
    else
      cumnlost=$((${cumnlost} + ${nlost}))
      if [ ${cumnlost} -lt ${MAX_CUMNLOST} ]
      then
        ok "Some packet loss detected, skipping checksum validation for the forwarding1.${codec}.wav"
      else
        fail "Cumulative packet loss is too high ${cumnlost} current, ${MAX_CUMNLOST} max"
      fi
    fi
    i=$((${i}+1))
  done
}

CODECSO="${TEST_CODECS}"
CODECSA="${TEST_CODECS}"
PORTO=$((${FWD_SPORT} + 2))

FORWARDING_RFILES=""
for codec in ${TEST_CODECS}
do
  FORWARDING_RFILES="forwarding1.${codec} ${FORWARDING_RFILES}"
done
rm -f ${FORWARDING_RFILES}
${MAKEANN} ${BASEDIR}/ringback.sln ${BASEDIR}/forwarding1
report "makeann forwarding1"

_CODECSO=""
_CODECSA=""
i=0
while [ ${i} -eq 0 -o "${CODECSO}" != "${CODECSA}" ]
do
  i=1
  _CODECSO="${_CODECSO} ${CODECSO}"
  _CODECSA="${_CODECSA} ${CODECSA}"
  rotate_CODECSA ${CODECSA}
done
REPACK_CODECSO="${CODECSO}"
rotate_CODECSA ${CODECSA}
REPACK_CODECSA="${CODECSA}"
CODECSO="${_CODECSO}"
CODECSA="${_CODECSA}"

RECORD_DIR="${BUILDDIR}"

setup_buffers
setup_test_net_3

witness_start forwarding1 "forwarding1.rout forwarding1.geno.rout forwarding1.gena.rout forwarding1.rlog forwarding1.geno.rlog forwarding1.gena.rlog"

RTPPROXY_ARGS="-T5 --bridge_symmetric -b -s stdio: -f -d ${RTPP_DEBUG_LVL} -l 0.0.0.0 -6 /:: --config forwarding/rtpproxy.conf"

if [ -e rtpproxy_acct.csv ]
then
  rm rtpproxy_acct.csv
fi

#sts=`date "+%Y%m%d%H%M%S"`
(setup_fwd ${GENO_SPORT} ${GENA_SPORT} "${CODECSO}" "${REPACK_CODECSO}" | \
  ${RTPPROXY} -i -s cunix:/tmp/forwarding1.sock ${RTPPROXY_ARGS} \
   -m ${FWD_SPORT} > forwarding1.rout 2>forwarding1.rlog) &
FWD_PID=${!}
(setup_gen "o" ${FWD_SPORT} "${CODECSO}" "${REPACK_CODECSO}" | \
  ${RTPPROXY} -P -r "${RECORD_DIR}" -m ${GENO_SPORT} ${RTPPROXY_ARGS} \
   > forwarding1.geno.rout 2>forwarding1.geno.rlog) &
GENO_PID=${!}
(setup_gen "a" ${PORTO} "${CODECSA}" "${REPACK_CODECSA}" | \
  ${RTPPROXY} -r "${RECORD_DIR}" -m ${GENA_SPORT} ${RTPPROXY_ARGS} \
   > forwarding1.gena.rout 2>forwarding1.gena.rlog) &
GENA_PID=${!}
wait ${FWD_PID}
#ets=`date "+%Y%m%d%H%M%S"`
#echo $((${ets} - ${sts}))
report "wait for rtpproxy Fwd shutdown, PID: ${FWD_PID}"
wait ${GENO_PID}
report "wait for rtpproxy Gen.O shutdown, PID: ${GENO_PID}"
wait ${GENA_PID}
report "wait for rtpproxy Gen.A shutdown, PID: ${GENA_PID}"
${DIFF} forwarding/forwarding1.output forwarding1.rout
DIFF_FWD_RC=${?}
${DIFF} forwarding/forwarding1.geno.output forwarding1.geno.rout
DIFF_GENO_RC=${?}
${DIFF} forwarding/forwarding1.gena.output forwarding1.gena.rout
DIFF_GENA_RC=${?}

verify_results "o" "${CODECSA}" "${REPACK_CODECSA}"
verify_results "a" "${CODECSO}" "${REPACK_CODECSO}"

report_rc ${DIFF_FWD_RC} "checking rtpproxy.fwd stdout"
report_rc ${DIFF_GENO_RC} "checking rtpproxy.geno stdout"
report_rc ${DIFF_GENA_RC} "checking rtpproxy.gena stdout"

witness_stop

test -e rtpproxy_acct.csv
report "checking if rtpproxy_acct.csv is present"

nlexpected="181"
anlines=$((`wc -l < rtpproxy_acct.csv`))
test ${anlines} -eq ${nlexpected}
report "checking number of lines in rtpproxy_acct.csv: ${anlines} vs ${nlexpected}"
