#!/bin/sh

state=""

state() {
  case "${1}" in
  [Dd][Oo][Ww][Nn])
    if [ "${state}" != "down" ]
    then
      echo "$(date): ${gateway} down"
      state="down"
    fi
    ;;
  [Uu][Pp])
    if [ "${state}" != "up" ]
    then
      echo "$(date): ${gateway} up"
      state="up"
    fi
    ;;
  *)
    echo "Unhandled '${1}'" >&2
  esac
}

gateway="${1:-66.253.36.1}"
intervalms="${2:-1000}"
intervals="$(( ${intervalms} / 1000 ))"
chasm=3

printf "Pingelating %s every %ums, %u second grace\n" "${gateway}" "${intervalms}" "${chasm}"

time="$(date +%s)"
last_check="${time}"
last_ping="0"

(
  ping -n -W "${intervalms}" "${gateway}" &
  echo "pid_ping=${!}"
  ( while true; do echo "Pingelate"; sleep "${intervals}"; done ) &
  echo "pid_elate=${!}"
) | while read line
do
  time="$(date +%s)"
  case "${line}" in
  pid_*)
    eval "${line}"
    trap "kill -TERM ${pid_ping} ${pid_elate}" exit hup int term kill
    ;;
  *\ bytes\ from\ ${gateway}:\ *)
    diff="$(( ${time} - ${last_ping} ))"
    [ "${diff}" -ge "${chasm}" ] && state up "${time}" "${last_ping}" "${last_check}" "${diff}" "${chasm}"
    last_ping="${time}"
    ;;
  Pingelate)
    # Was the last ping more than ${chasm} seconds before this checkpoint?
    diff=$(( ${time} - ${last_ping} ))
    [ "${diff}" -ge "${chasm}" ] && state down "${time}" "${last_ping}" "${last_check}" "${diff}" "${chasm}"
    last_check="${time}"
    ;;
  *)
    ;;
  esac
done