#!/bin/sh
#
# Copyright (C) 2018-2025 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 test global or interface speed
#

FORCEVPS=false
FASTTEST=false
if [ "$1" = "forcevps" ]; then
	FORCEVPS=true
fi
if [ "$1" = "fasttest" ]; then
	FASTTEST=true
fi
for i in $@; do :; done
INTERFACE="$i"
[ "$INTERFACE" = "forcevps" ] || [ "$INTERFACE" = "fasttest" ] && INTERFACE=""

IPV6=false
if [ "$(basename $0)" = "omr-test-speedv6" ]; then
	IPV6=true
fi

[ -n "$INTERFACE" ] && [ ! -d "/sys/class/net/$INTERFACE" ] && {
	echo "You must use a real interface. You wan find them using 'ip a' for example (not $INTERFACE)"
	exit 0
}

HOSTLST="http://scaleway.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso https://rbx.proof.ovh.net/files/10Gb.dat https://gra.proof.ovh.net/files/10Gb.dat https://sbg.proof.ovh.net/files/10Gb.dat https://bhs.proof.ovh.ca/files/10Gb.dat https://vin.proof.ovh.us/files/10Gb.dat https://hil.proof.ovh.us/files/10Gb.dat http://speedtest.tele2.net/10GB.zip https://la.speedtest.clouvider.net/10g.bin https://atl.speedtest.clouvider.net/10g.bin https://nyc.speedtest.clouvider.net/10g.bin https://lon.speedtest.clouvider.net/10g.bin https://man.speedtest.clouvider.net/10g.bin https://ams.speedtest.clouvider.net/10g.bin https://fra.speedtest.clouvider.net/10g.bin https://dal.speedtest.clouvider.net/10g.bin https://ash.speedtest.clouvider.net/10g.bin https://phx.speedtest.clouvider.net/10g.bin https://chi.speedtest.clouvider.net/10g.bin"
HOSTLST6="http://scaleway.testdebit.info/10G.iso http://appliwave.testdebit.info/10G/10G.iso http://speedtest.frankfurt.linode.com/garbage.php?ckSize=10000 http://speedtest.tokyo2.linode.com/garbage.php?ckSize=10000 http://speedtest.singapore.linode.com/garbage.php?ckSize=10000 http://speedtest.newark.linode.com/garbage.php?ckSize=10000 http://speedtest.atlanta.linode.com/garbage.php?ckSize=10000 http://speedtest.dallas.linode.com/garbage.php?ckSize=10000 http://speedtest.fremont.linode.com/garbage.php?ckSize=10000 http://par.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://ams.download.datapacket.com/10000mb.bin http://fra.download.datapacket.com/10000mb.bin http://lon.download.datapacket.com/10000mb.bin http://mad.download.datapacket.com/10000mb.bin http://prg.download.datapacket.com/10000mb.bin http://sto.download.datapacket.com/10000mb.bin http://vie.download.datapacket.com/10000mb.bin http://war.download.datapacket.com/10000mb.bin http://atl.download.datapacket.com/10000mb.bin http://chi.download.datapacket.com/10000mb.bin http://lax.download.datapacket.com/10000mb.bin http://mia.download.datapacket.com/10000mb.bin http://nyc.download.datapacket.com/10000mb.bin http://speedtest.milkywan.fr/files/10G.iso https://rbx.proof.ovh.net/files/10Gb.dat https://gra.proof.ovh.net/files/10Gb.dat https://sbg.proof.ovh.net/files/10Gb.dat https://bhs.proof.ovh.ca/files/10Gb.dat https://vin.proof.ovh.us/files/10Gb.dat https://hil.proof.ovh.us/files/10Gb.dat http://speedtest.tele2.net/10GB.zip https://la.speedtest.clouvider.net/10g.bin https://atl.speedtest.clouvider.net/10g.bin https://nyc.speedtest.clouvider.net/10g.bin https://lon.speedtest.clouvider.net/10g.bin https://man.speedtest.clouvider.net/10g.bin https://ams.speedtest.clouvider.net/10g.bin https://fra.speedtest.clouvider.net/10g.bin https://dal.speedtest.clouvider.net/10g.bin https://ash.speedtest.clouvider.net/10g.bin https://phx.speedtest.clouvider.net/10g.bin https://chi.speedtest.clouvider.net/10g.bin"

select_server() {
	[ "$FASTTEST" = true ] || echo "Select best test server..."
	bestping="9999"
	if [ "$IPV6" = true ]; then
		for pinghost in $HOSTLST6; do
			domain=$(echo $pinghost | awk -F/ '{print $3}')
			if [ -z "$INTERFACE" ] || [ "$FORCEVPS" = true ]; then
				ping=$(ping -6 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
			else
				ping=$(ping -6 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
			fi
			[ "$FASTTEST" = true ] || echo "host: $domain - ping: $ping"
			if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then
				bestping=$ping
				HOST=$pinghost
			fi
		done
	else
		for pinghost in $HOSTLST; do
			domain=$(echo $pinghost | awk -F/ '{print $3}')
			if [ -z "$INTERFACE" ] || [ "$FORCEVPS" = true ]; then
				ping=$(ping -4 -c1 -w2 $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
			else
				ping=$(ping -4 -c1 -w2 -I $INTERFACE -B $domain | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
			fi
			[ "$FASTTEST" = true ] || echo "host: $domain - ping: $ping"
			if [ -n "$ping" ] && [ "$ping" -lt "$bestping" ]; then
				bestping=$ping
				HOST=$pinghost
			fi
		done
	fi
}

get_speed_global() {
	HOST=$1
	if [ "$IPV6" = true ]; then
		curl -6 -o /dev/null $HOST || echo
	else
		curl -4 -o /dev/null $HOST || echo
	fi
}

get_speed_global_fast() {
	HOST=$1
	if [ "$IPV6" = true ]; then
		avg_speed=$(curl -6 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' $HOST 2>/dev/null)
	else
		avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' $HOST 2>/dev/null)
	fi
	echo "$avg_speed"
}

bypass_host_enable() {
	INTERFACE=$1
	HOST=$2
	[ -n "$(tc qdisc show dev $INTERFACE | grep ingress)" ] && /etc/init.d/sqm stop $INTERFACE
	domain=$(echo $HOST | awk -F/ '{print $3}')
	if [ "$IPV6" = true ]; then
		hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		if [ -n "$(ipset list 2>/dev/null | grep ss_rules6)" ]; then
			for ip in $hostip; do
				ipset add ss_rules6_dst_bypass_all $ip
			done
		fi
		if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_6 2>/dev/null)" ]; then
			for ip in $hostip; do
				nft add element inet fw4 omr_dst_bypass_all_6 { $ip } >/dev/null 2>&1
			done
		fi
	else
		hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then
			for ip in $hostip; do
				ipset add ss_rules_dst_bypass_all $ip
			done
		fi
		if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_4 2>/dev/null)" ]; then
			for ip in $hostip; do
				nft add element inet fw4 omr_dst_bypass_all_4 { $ip } >/dev/null 2>&1
			done
		fi
	fi
}


bypass_host_disable() {
	INTERFACE=$1
	HOST=$2
	domain=$(echo $HOST | awk -F/ '{print $3}')
	if [ "$IPV6" = true ]; then
		hostip=$(dig +nocmd +noall +answer AAAA $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		if [ -n "$(ipset list 2>/dev/null | grep ss_rules6)" ]; then
			for ip in $hostip; do
				ipset del ss_rules6_dst_bypass_all $ip
			done
		fi
		if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_6 2>/dev/null)" ]; then
			for ip in $hostip; do
				nft delete element inet fw4 omr_dst_bypass_all_6 { $ip } >/dev/null 2>&1
			done
		fi
	else
		hostip=$(dig +nocmd +noall +answer A $domain | grep -v CNAME | awk '{print $5}' | tr '\n' ' ')
		if [ -n "$(ipset list 2>/dev/null | grep ss_rules)" ]; then
			for ip in $hostip; do
				ipset del ss_rules_dst_bypass_all $ip
			done
		fi
		if [ -n "$(nft list set inet fw4 omr_dst_bypass_all_4 2>/dev/null)" ]; then
			for ip in $hostip; do
				nft delete element inet fw4 omr_dst_bypass_all_4 { $ip } >/dev/null 2>&1
			done
		fi
	fi
	/etc/init.d/sqm start $INTERFACE
}

get_speed_interface() {
	INTERFACE=$1
	HOST=$2
	bypass_host_enable $INTERFACE $HOST
	if [ "$IPV6" = true ]; then
		curl -6 -o /dev/null --interface $INTERFACE $HOST || echo
	else
		curl -4 -o /dev/null --interface $INTERFACE $HOST || echo
	fi
	bypass_host_disable $INTERFACE $HOST
}

get_speed_interface_fast() {
	INTERFACE=$1
	HOST=$2
	bypass_host_enable $INTERFACE $HOST
	if [ "$IPV6" = true ]; then
		avg_speed=$(curl -6 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null)
	else
		avg_speed=$(curl -4 --max-time 10 -o /dev/null -qfsS -w '%{speed_download}' --interface $INTERFACE $HOST 2>/dev/null)
	fi
	echo "$avg_speed"
	bypass_host_disable $INTERFACE $HOST
}

response="000"
try=0
while [ "$response" = "000" ] && [ "$try" -le 3 ]; do
	select_server
	if [ "$IPV6" = true ]; then
		response=$(curl -6 --write-out '%{http_code}' --silent --head --insecure -IL  --connect-timeout 5 --output /dev/null $HOST)
		HOSTLST6=$(echo $HOSTLST6 | tr ' ' '\n' | grep -v "$HOST" | xargs)
	else
		response=$(curl -4 --write-out '%{http_code}' --silent --head --insecure -IL  --connect-timeout 5 --output /dev/null $HOST)
		HOSTLST=$(echo $HOSTLST | tr ' ' '\n' | grep -v "$HOST" | xargs)
	fi
	try=$((try+1))
	if [ "$response" = "000" ] && [ "$FASTTEST" != true ]; then
		echo "No answer from $HOST, retry..."
	fi
done

[ -z "$HOST" ] && HOST="http://speedtest.milkywan.fr/files/10G.iso"

[ "$FASTTEST" = true ] || echo "Best server is $HOST, running test:"
trap : HUP INT TERM
if [ -z "$INTERFACE" ]; then
	if [ "$FASTTEST" = true ]; then 
		get_speed_global_fast $HOST
	else
		get_speed_global $HOST
	fi
else
	if [ "$FASTTEST" = true ]; then 
		get_speed_interface_fast $INTERFACE $HOST
	else
		get_speed_interface $INTERFACE $HOST
	fi
fi
