#!/usr/bin/env bash
trap 'killm f' EXIT
#
# Scott Burleigh
# January 18, 2021
#

# documentation boilerplate
CONFIGFILES=" \
./1.bench.stcp/bench.bprc \
./1.bench.stcp/bench.ionconfig \
./1.bench.stcp/bench.ionrc \
./1.bench.stcp/bench.ionsecrc \
./1.bench.stcp/bench.ipnrc \
./2.bench.stcp/bench.bprc \
./2.bench.stcp/bench.ionconfig \
./2.bench.stcp/bench.ionrc \
./2.bench.stcp/bench.ionsecrc \
./2.bench.stcp/bench.ipnrc \
./3.bench.stcp/bench.bprc \
./3.bench.stcp/bench.ionconfig \
./3.bench.stcp/bench.ionrc \
./3.bench.stcp/bench.ionsecrc \
./3.bench.stcp/bench.ipnrc \
./4.bench.stcp/bench.bprc \
./4.bench.stcp/bench.ionconfig \
./4.bench.stcp/bench.ionrc \
./4.bench.stcp/bench.ionsecrc \
./4.bench.stcp/bench.ipnrc \
"

echo "########################################"
echo
pwd | sed "s/\/.*\///" | xargs echo "NAME: "
echo
echo "PURPOSE: demonstrate contact graph routing (SABR) over a diamond
    topology and confirm end-to-end bundle delivery.  The nodes use the
    simplified TCP convergence-layer protocol and reside on the same
    computer; source node 1 sends to destination node 4 via relay nodes
    2 and 3 that are not mutually visible, so CGR must select a path
    across the contact plan.  This is a configuration demonstration and
    a delivery smoke test -- a moderate, fixed number of bundles is sent
    and delivery is confirmed -- not a throughput measurement (loopback
    throughput is not representative of any real deployment)."

echo
echo "CONFIG: 4 node custom:"
echo
for N in $CONFIGFILES
do
    echo "$N:"
    cat "$N"
    echo "# EOF"
    echo
done
echo "OUTPUT: Terminal messages will relay results."
echo
echo "########################################"

./cleanup
sleep 1
echo "Starting ION..."
export ION_NODE_LIST_DIR=$PWD
rm -f ./ion_nodes
RETVAL=0

# Start nodes.
cd 1.bench.stcp
./ionstart
../../../system_up -i "p 30" -b "p 30"
if [ $? -eq 2 ]; then
    echo ""
else
    echo "Node 1 not started: Aborting Test"
    exit 1
fi

cd ../2.bench.stcp
./ionstart
../../../system_up -i "p 30" -b "p 30"
if [ $? -eq 2 ]; then
    echo ""
else
    echo "Node 2 not started: Aborting Test"
    exit 1
fi

cd ../3.bench.stcp
./ionstart
../../../system_up -i "p 30" -b "p 30"
if [ $? -eq 2 ]; then
    echo ""
else
    echo "Node 3 not started: Aborting Test"
    exit 1
fi

cd ../4.bench.stcp
./ionstart
../../../system_up -i "p 30" -b "p 30"
if [ $? -eq 2 ]; then
    echo ""
else
    echo "Node 4 not started: Aborting Test"
    exit 1
fi

sleep 3

# Delivery smoke test: send a moderate, fixed number of bundles from node 1
# to node 4 and confirm they arrive.  CGR must route each across the diamond
# via relay 2 or 3.  This is a configuration demonstration, not a throughput
# measurement, so the volume is small and delivery is bounded in time.
cd ..
ROOT=$PWD
BUNDLES=10
WAIT_SECS=120
IONSENDFILE="$ROOT/1.bench.stcp/benchsend.txt"
IONRECEIVEFILE="$ROOT/4.bench.stcp/ionreceivefile.txt"
echo "This is a bench-cgr demonstration bundle." > "$IONSENDFILE"
rm -f "$IONRECEIVEFILE"

echo ""
echo "Sending $BUNDLES bundles from node 1 to node 4 across the diamond."

# Receiver on node 4.
cd "$ROOT/4.bench.stcp"
bpsink ipn:4.1 > "$IONRECEIVEFILE" &
BPSINKPID=$!
sleep 1

# Send from node 1; CGR routes each bundle via relay 2 or 3.
cd "$ROOT/1.bench.stcp"
i=1
while [ "$i" -le "$BUNDLES" ]
do
    bpsource ipn:4.1 < "$IONSENDFILE" 1>/dev/null 2>/dev/null
    i=$((i + 1))
done
cd "$ROOT"

# Wait (bounded) for delivery at node 4.  The diamond contact plan opens
# relay windows through +90s, so allow generous headroom; a shortfall fails
# fast here rather than hanging until the harness timeout.
echo "Waiting up to ${WAIT_SECS}s for delivery at node 4..."
elapsed=0
got=0
while [ "$elapsed" -lt "$WAIT_SECS" ]
do
    got=$(grep -c "^ION event: Payload delivered\." "$IONRECEIVEFILE" 2>/dev/null)
    [ -z "$got" ] && got=0
    if [ "$got" -ge "$BUNDLES" ]
    then
        break
    fi
    sleep 2
    elapsed=$((elapsed + 2))
done

if [ "$got" -ge "$BUNDLES" ]
then
    echo "SUCCESS: $got of $BUNDLES bundles delivered to node 4 via CGR."
    RETVAL=0
else
    echo "FAILURE: only $got of $BUNDLES bundles delivered after ${WAIT_SECS}s."
    RETVAL=1
fi

# Per-node stats, for the demonstration.
for N in 1 2 3 4
do
    cd "$ROOT/$N.bench.stcp"
    bpstats
done
cd "$ROOT"

# Stop the receiver.
kill -2 "$BPSINKPID" >/dev/null 2>&1
sleep 1
kill -9 "$BPSINKPID" >/dev/null 2>&1

echo "Stopping ION..."
killm f
echo "...demonstration terminated."
exit $RETVAL
