#!/bin/sh
# The state hook (ADR 0108 §2.3): `fv up --state-hook /usr/libexec/forestvpn/state` runs `state <state> <reason|->` on every change
# of (state, reason), argv only, an empty environment but PATH, one at a time, killed after 10 s. It only changes set membership and
# ip rules (fv_sync); it never reloads the firewall, so a kill mid-run leaves a defined state (the next run or include completes it).
# `cannot_start` is sent by the init script and the updater (A-1, A-5) when the daemon is not running on purpose: no installed fv can
# run, or a deliberate stop (`stop`, LuCI's stop, `enabled 0`, opkg remove). Seam S12: under Standard that releases the devices
# (the internet works without the VPN), under Strict it blocks them. A crash or a kill sends nothing: the last state stands and
# the devices stay held until procd has the daemon back. A restart, a reboot's shutdown and an upgrade are not stops.
. "${FV_LIB:-/lib/forestvpn}/adapter.sh"

st=${1:-}
rs=${2:--}
case $st in
	connecting | connected | reconnecting | waiting_network | stopped_local | stopped_refused | cannot_start) ;;
	*) echo "forestvpn state: unknown state '$st'" >&2; exit 2 ;;
esac
echo "$rs" | grep -Eq '^(-|[a-z][a-z0-9_.]{0,63})$' || { echo "forestvpn state: bad reason" >&2; exit 2; }

record() {
	local prev flush=0
	prev=$(cut -d' ' -f1 "$FV_RUN/adapter.state" 2> /dev/null)
	echo "$st $rs" > "$FV_RUN/adapter.state.tmp" && mv "$FV_RUN/adapter.state.tmp" "$FV_RUN/adapter.state"
	# a new connection (first connect, reconnect, location change): protected hosts' old connections go (PRO-8)
	[ "$st" = connected ] && [ "$prev" != connected ] && flush=1
	fv_sync "$flush"
}
# a firewall stop (fw4 flushes foreign tables too) deletes the table of ForestVPN's own sockets (lib/forestvpn/direct.nft): put it back.
# Not for `cannot_start`: no daemon runs then, `start` loads the table, and a removal's last stop (opkg's default_prerm, after `uninstall pkg`
# took the table out) must not bring it back
[ "$st" = cannot_start ] || nft list table inet forestvpn_direct > /dev/null 2>&1 || nft -f /lib/forestvpn/direct.nft > /dev/null 2>&1
fv_locked record
rc=$?
# the notice pages are A-3's: static per-state pages, written here so they match the state the firewall shows
[ -x /usr/libexec/forestvpn/notice/write ] && /usr/libexec/forestvpn/notice/write "$st" "$rs"
exit $rc
