#!/bin/sh

[ ! -e /etc/init.d/omr-bypass ] && exit 0
# The time of the last pass is runtime state, kept in /var/state (see
# omr-state.sh): committed to /etc/config/omr-bypass, it rewrote the file,
# with all the user's bypass rules, every 10 minutes.
_bypass_lc="$(uci -q -P /var/state get omr-bypass.global.lc)"
if [ -z "$_bypass_lc" ] || [ $(($(date +"%s") - _bypass_lc)) -gt 600 ]; then
	# What openmptcprouter-vps set_bypass_ips sends, for the checksums
	# below: every element of omr-bypass's fw4 set, as text (an address, a
	# prefix or a range, without its timeout)
	_bypass_set_elements() {
		nft list set inet fw4 "$1" 2>/dev/null | awk '
			/elements = \{/ { e = 1; sub(/.*elements = \{/, "") }
			e {
				done = sub(/\}.*/, "")
				n = split($0, parts, ",")
				for (i = 1; i <= n; i++) {
					split(parts[i], w, " ")
					if (w[1] != "") printf "%s\"%s\"", (c++ ? "," : ""), w[1]
				}
				if (done) exit
			}'
	}
	bypassipv4s=$(_bypass_set_elements omr_dst_bypass_srv_vpn1_4)
	bypassipv6s=$(_bypass_set_elements omr_dst_bypass_srv_vpn1_6)
	vpnipv4md5=$(echo "${bypassipv4s}" | md5sum | awk '{print $1}' | tr -d "\n")
	vpnipv6md5=$(echo "${bypassipv6s}" | md5sum | awk '{print $1}' | tr -d "\n")
	# The checksums of the last lists sent are runtime state too: the sets
	# change with every address dnsmasq adds for a domain, and each change
	# was committed to /etc/config/omr-bypass (41_omr-bypass drops those).
	# After a reboot the lists are sent once again.
	if [ "$vpnipv4md5" != "$(uci -q -P /var/state get omr-bypass.global.vpn_ipv4_md5)" ] || [ "$vpnipv6md5" != "$(uci -q -P /var/state get omr-bypass.global.vpn_ipv6_md5)" ]; then
		_log "Set bypass ip on servers"
		# set_bypass_ips says nothing of how it went: the checksums used to be
		# stored anyway, so a list a VPS never got (API down) was never sent
		# again. Its per-server bypass_pushed (in /var/state) tells: set when
		# a VPS took the list of this run. An empty list only goes to a VPS
		# that had one (bypass_sent, kept in the config), and that flag is
		# removed when it took it. bypass_sent used to be dropped here before
		# each push and committed again after: a flash write each time.
		_bypass_servers=""
		for _bypass_srv in $(uci -q show openmptcprouter | sed -n "s/^openmptcprouter\.\([^.=]*\)=server$/\1/p"); do
			# the servers openmptcprouter-vps sends the list to
			[ "$(uci -q get openmptcprouter.${_bypass_srv}.disabled)" = "1" ] && continue
			[ -z "$(uci -q get openmptcprouter.${_bypass_srv}.username)" ] && continue
			[ -z "$(uci -q get openmptcprouter.${_bypass_srv}.password)" ] && continue
			[ -z "$(uci -q get openmptcprouter.${_bypass_srv}.port)" ] && continue
			_bypass_servers="$_bypass_servers $_bypass_srv"
			uci -q -P /var/state revert openmptcprouter.${_bypass_srv}.bypass_pushed
		done
		/etc/init.d/openmptcprouter-vps set_bypass_ips
		_bypass_failed=""
		for _bypass_srv in $_bypass_servers; do
			if [ -n "$bypassipv4s$bypassipv6s" ]; then
				[ "$(uci -q -P /var/state get openmptcprouter.${_bypass_srv}.bypass_pushed)" = "1" ] && continue
			else
				[ "$(uci -q get openmptcprouter.${_bypass_srv}.bypass_sent)" != "1" ] && continue
			fi
			_bypass_failed="$_bypass_failed $_bypass_srv"
		done
		if [ -z "$_bypass_failed" ]; then
			# revert first: each set adds a line to the state file
			uci -q -P /var/state revert omr-bypass.global.vpn_ipv4_md5
			uci -q -P /var/state revert omr-bypass.global.vpn_ipv6_md5
			uci -q -P /var/state set omr-bypass.global.vpn_ipv4_md5="${vpnipv4md5}"
			uci -q -P /var/state set omr-bypass.global.vpn_ipv6_md5="${vpnipv6md5}"
		else
			_log "Bypass ip not set on server(s)${_bypass_failed}, try again later"
		fi
	fi
	uci -q -P /var/state revert omr-bypass.global.lc
	uci -q -P /var/state set omr-bypass.global.lc=$(date +"%s")
fi