#!/bin/sh
# shellcheck shell=dash
# shellcheck disable=SC1091
# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 :

HOST="gra.perf.overthebox.net"

. /lib/overthebox
. /lib/functions.sh
. /lib/functions/network.sh

trap : HUP INT TERM

_rule_create(){
    nft add rule ip nat socks_emitted_by_myself ip daddr "$HOST" jump socks_decision comment \" Test download proof \"
}

_rule_delete(){
    # get handle of test rule
    rule_handle=$(nft -a list chain ip nat socks_emitted_by_myself | grep "socks_decision" | awk '{print $NF}')

    # delete rule with handle value
    nft delete rule ip nat socks_emitted_by_myself handle "$rule_handle"
}

_speedtest_json() {
	itf="$1"

	if [ "$itf" = "loopback" ] || [ "$itf" = "tun0" ] ; then
		return 0
	elif [ "$itf" = "shadowsocks" ]; then
		itf="lan"
	fi

	if ! network_is_up "$itf"; then
		return 0
	fi

	network_get_ipaddr SOURCE_IP "$itf"

	if [ "$itf" = "lan" ]; then
		itf="shadowsocks"
		_rule_create
		speedtest_json "${SOURCE_IP}"
		_rule_delete
	else
		speedtest_json "${SOURCE_IP}"
	fi

	JSON=$(echo {} | jq --arg itf "${itf}" --argjson array "${SPEEDTEST}" '.[$itf] += $array')
}

_speedtest() {
	itf="$1"

	if [ "$itf" = "loopback" ] || [ "$itf" = "tun0" ] ; then
		return 0
	elif [ "$itf" = "shadowsocks" ]; then
		itf="lan"
	fi

	if ! network_is_up "$itf"; then
		return 0
	fi

	network_get_ipaddr SOURCE_IP "$itf"

	if [ "$itf" = "lan" ]; then
		itf="shadowsocks"
		_rule_create
		echo "==="
		echo "Launching $itf speedtest : $SOURCE_IP"
		echo "==="
		speedtest "${SOURCE_IP}"
		_rule_delete
	else
		echo "==="
		echo "Launching speedtest on $itf : $SOURCE_IP"
		echo "==="
		speedtest "${SOURCE_IP}"
	fi
}

_usage() {
	echo "otb-action-speedtest, measure TCP bandwidth with librespeed"
	echo
	echo "Syntax: otb-action-speedtest [-i <>|h|j]"
	echo "options:"
	echo "-i     Run speedtest on the selected interface, if not defined run speedtest on every interface"
	echo "-h     Print this help"
	echo "-j     Output in json format"
	echo
	exit
}

while getopts :i:jh flag; do
    case "${flag}" in
        i) itf=${OPTARG};;
        j) mode="json";;
		h) _usage;;
		*) exit;;
    esac
done

if [ ! $mode ]; then
	if [ "$(uci -q get "network.$itf")" = interface ]; then
		_speedtest "$itf"
	else
		config_load network
		config_foreach _speedtest interface
	fi

else
	if [ "$(uci -q get "network.$itf")" = interface ]; then
		_speedtest_json "$itf"
		echo "$JSON" |jq .
	else
		config_load network
		J="{}"
		for section in ${CONFIG_SECTIONS}; do
			if [ "$(uci -q get "network.$section")" = interface ]; then
				_speedtest_json "$section"

				if [ -n "$JSON" ]; then
					R=$(echo $J | jq --argjson result "${JSON}" '. += $result')
					J=$R
				fi
			fi
		done

		echo "$J" | jq .
	fi
fi
