#!/bin/sh
#
# Copyright (C) 2018-2024 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# This script check speed using Speedtest servers

INTERFACE="$1"
sqm_stopped=""

# The host comes as a bare name (speedtest.example.com) or an URL: keep only
# the name, awk -F/ '{print $3}' alone gave nothing for a bare name.
_host_domain() {
	echo "$1" | sed -e 's|^[a-zA-Z]*://||' -e 's|[/:].*$||'
}

# The router's own connections to the test host must not go through the
# transparent proxy: its output chain (ss_rules_local_out, or the xr_/v2r_
# one) lets through what is in the proxy's dst_bypass set, and omr-bypass's
# omr_dst_bypass_all_4/6 when it has one. The ipsets used before don't exist
# with fw4. Only what was added is removed afterwards: an address the user
# already bypasses stays.
_proxy_bypass_added=""
_proxy_bypass_add() {
	local fam="$1" ip set
	shift
	for ip in "$@"; do
		case "$ip" in ""|*[!0-9a-fA-F.:]*) continue ;; esac
		for set in ss_rules${fam}_dst_bypass v2r_rules${fam}_dst_bypass xr_rules${fam}_dst_bypass omr_dst_bypass_all_${fam:-4}; do
			nft get element inet fw4 "$set" "{ $ip }" >/dev/null 2>&1 && continue
			nft add element inet fw4 "$set" "{ $ip }" >/dev/null 2>&1 && _proxy_bypass_added="$_proxy_bypass_added $set,$ip"
		done
	done
}
_proxy_bypass_del() {
	local e
	for e in $_proxy_bypass_added; do
		nft delete element inet fw4 "${e%%,*}" "{ ${e#*,} }" >/dev/null 2>&1
	done
	_proxy_bypass_added=""
}

bypass_host_enable() {
	INTERFACE=$1
	HOST=$2
	if [ -n "$(tc qdisc show dev $INTERFACE | grep ingress)" ]; then
		/etc/init.d/sqm stop $INTERFACE
		sqm_stopped="1"
	fi
	domain=$(_host_domain "$HOST")
	if [ "$IPV6" = true ]; then
		hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		_proxy_bypass_add 6 $hostip
	else
		hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		_proxy_bypass_add "" $hostip
	fi
}


bypass_host_disable() {
	INTERFACE=$1
	HOST=$2
	_proxy_bypass_del
	# Only what the test stopped: SQM may be off on this interface.
	[ "$sqm_stopped" = "1" ] && /etc/init.d/sqm start $INTERFACE
}

if [ -f /usr/bin/v2ray ]; then
	upload_file="/usr/bin/v2ray"
elif [ -f /usr/bin/xray ]; then
	upload_file="/usr/bin/xray"
elif [ -f /boot/vmlinuz ]; then
	upload_file="/boot/vmlinuz"
elif [ -f /bin/bash ]; then
	upload_file="/bin/bash"
else
	upload_file="/bin/busybox"
fi

echo "Download server list..."
wget -q -O /tmp/speedtest.lst https://www.speedtest.net/api/js/servers
bestuploadurl=""
besthost=""
bestpinghost=""
sponsor=""
bestping="999"
echo "Select best server..."
while read line; do
	host=$(echo $line | jsonfilter -e '@.host')
	pinghost=$(echo $host | awk -F: '{print $1}')
	url=$(echo $line | jsonfilter -e '@.url')
	ping=$(ping -c1 -w1 $pinghost | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
	echo -n "."
	if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then
		bestping=$ping
		besturl=$url
		besthost=$host
		bestpinghost=$pinghost
		sponsor=$(echo $line | jsonfilter -q -e '@.sponsor')
	fi
done < <(cat /tmp/speedtest.lst | jsonfilter -e '@[*]')
echo
echo "Done: url: $besturl - host: $besthost - ping: $bestping - sponsor: $sponsor"
echo "Download test:"
if [ -z "$INTERFACE" ]; then
	curl -4 $besthost/speedtest/random7000x7000.jpg >/dev/null || echo
else
	bypass_host_enable $INTERFACE $bestpinghost
	echo "Download:"
	curl -4 --interface $INTERFACE $besthost/speedtest/random7000x7000.jpg >/dev/null || echo
	echo "Upload:"
	curl -4 --interface $INTERFACE -F "file=@$upload_file" $besturl >/dev/null || echo
	bypass_host_disable $INTERFACE $bestpinghost
fi
