#!/bin/bash

# Copyright 2009-2021 INRIA Rhone-Alpes, Service Experimentation et
# Developpement
# This file is part of Execo, released under the GNU Lesser Public
# License, version 3 or later.

usage() {
    cat <<EOF

WARNING: this program is intended to be used from within execo, users
         should not run it directly
usage:
  $(basename $0) <filename> <dest dir> <nc> <client_timeout> <server_timeout> <port> <host tries> <chain tries> <delay> <index> <remote hosts file> [--autoremove]

  <filename>: name of the file to send
  <dest dir>: destination dir on remote hosts
  <nc>: path of netcat executable
  <client_timeout>: netcat client connection timeout
  <server_timeout>: netcat server connection timeout
  <port>: port to use for netcat
  <host tries>: number of netcat client connection retries per next hop
  <chain tries>: number of next hop retries
  <delay>: delay between netcat client connection retries
  <index>: index of the remote or local host on which this command is run
      index is 0 based:
          0 = localhost, the host sending the file
          1-n = remote hosts
  <remote hosts file>: path to file containing the list of remote hosts

  if there is an additional argument --autoremove, the script will
  autodelete itself and the hostfile

EOF
}

log () {
    echo "$(date "+%Y-%m-%d %H:%M:%S%z") - $@"
}

if [ $# -lt 11 ] ; then usage ; exit 1; fi
FILENAME="$1"
DESTDIR="$2"
NC="$3"
CLIENT_TIMEOUT=$4
SERVER_TIMEOUT=$5
PORT=$6
HOSTTRIES=$7
CHAINTRIES=$8
DELAY=$9
INDEX=${10}
HOSTSFILE="${11}"
AUTOREMOVE=1
if [ $# -eq 12 -a "${12}" == "--autoremove" ] ; then
    AUTOREMOVE=0
fi

IFS=$'\n' read -d '' -r -a HOSTS < "$HOSTSFILE"

set -o pipefail
set -e

forwarddata() {
    (
        S=1
        CHAINTRY=$CHAINTRIES
        while [ $CHAINTRY -gt 0 -a $INDEX -lt ${#HOSTS[*]} -a $S -ne 0 ] ; do
            CHAINTRY=$((CHAINTRY-1))
            log "trying sending to ${HOSTS[INDEX]} ($((INDEX+1))/${#HOSTS[*]}) ($CHAINTRY hosts remaining)"
            HOSTTRY=$HOSTTRIES
            while [ $HOSTTRY -gt 0 ] ; do
                HOSTTRY=$((HOSTTRY-1))
                log "try $((HOSTTRIES-HOSTTRY))..."
                $NC -w $CLIENT_TIMEOUT -q 0 "${HOSTS[INDEX]}" $PORT && S=0 || S=1
                if [ $S -eq 0 ] ; then
                    log "...success"
                    break
                fi
                log "...failed"
                sleep $DELAY
            done
            INDEX=$((INDEX+1))
        done
        if [ $S -ne 0 ] ; then
            log "end of chain"
            cat > /dev/null
        fi
        exit 0
    )
}

if [ $INDEX -eq 0 ] ; then
    log "localhost starting chain"
    forwarddata < "$FILENAME"
else
    log "host ${HOSTS[INDEX-1]} ($INDEX/${#HOSTS[*]}) receiving and forwarding"
    $NC -l -w $SERVER_TIMEOUT -p $PORT | tee "$DESTDIR/$(basename $FILENAME)" | forwarddata
fi
log "end"
if [ $AUTOREMOVE -eq 0 ] ; then
    SCRIPTFILE=$(cd `dirname "$0"` && pwd)/`basename "$0"`
    log "auto deleting $HOSTSFILE and $SCRIPTFILE"
    rm -f "$HOSTSFILE"
    rm -f "$SCRIPTFILE"
fi
