#!/bin/bash
# better-cloudflare-ip
function bettercloudflareip (){
declare -i bandwidth
declare -i speed
read -p "请设置期望的带宽大小(默认0,单位 Mbps):" bandwidth
read -p "请设置RTT测试进程数(默认20,最大100):" tasknum
if [ -z "$tasknum" ]
then
	tasknum=20
fi
if [ $tasknum -gt 100 ]
then
	echo 超过最大进程限制,自动设置为100个
	tasknum=100
fi
speed=bandwidth*128*1024
starttime=`date +'%Y-%m-%d %H:%M:%S'`
getip
declare -i realbandwidth
realbandwidth=max/128
endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s)
end_seconds=$(date --date="$endtime" +%s)
clear
curl --$ips --resolve service.anycast.eu.org:443:$anycast --retry 3 -s -X POST -d ''$version-$anycast-$max'' "https://service.anycast.eu.org?asn="$asn"&city="$city"" -o temp.txt
publicip=$(cat temp.txt | grep publicip= | cut -f 2- -d'=')
colo=$(cat temp.txt | grep colo= | cut -f 2- -d'=')
rm -rf temp.txt
echo $anycast>$ips.txt
echo 优选IP $anycast
echo 公网IP $publicip
echo 自治域 AS$asn
echo 经纬度 $longitude,$latitude
echo META城市 $city
echo 设置带宽 $bandwidth Mbps
echo 实测带宽 $realbandwidth Mbps
echo 峰值速度 $max kB/s
echo 往返延迟 $avgms 毫秒
echo 数据中心 $colo
echo 总计用时 $((end_seconds-start_seconds)) 秒
}

function rtt (){
declare -i avgms
declare -i getrtt
t=1
n=1
timeout=1
for ip in `cat rtt/$1.txt`
do
	while true
	do
		if [ $t -le 5 ]
		then
			rttlog=`curl --resolve www.cloudflare.com:443:$ip https://www.cloudflare.com/cdn-cgi/trace -o /dev/null -s --connect-timeout $timeout -w "$ip"_%{time_connect}_%{time_starttransfer}_%{time_total}_"HTTP"%{http_code}"\n"`
			rttstatus=`echo $rttlog | grep HTTP200 | wc -l`
			if [ $rttstatus == 1 ]
			then
				echo $rttlog>>rtt/$1-$n.log
				t=$[$t+1]
			else
				rm -rf rtt/$1-$n.log
				t=1
				break
			fi
		else
			ipaddr=`cat rtt/$1-$n.log | awk 'NR==1' | awk -F_ '{print $1}'`
			avgms=0
			for i in `cat rtt/$1-$n.log | grep HTTP200 | awk -F_ '{printf ("%d\n",$2*1000000)}'`
			do
				avgms=$i+avgms
			done
			avgms=avgms/5000
			echo $avgms $ipaddr>rtt/$1-$n.log
			n=$[$n+1]
			t=1
			break
		fi
	done
done
rm -rf rtt/$1.txt
}

function speedtest (){
curl --resolve $domain:443:$1 https://$domain/$file -o /dev/null --connect-timeout 5 --max-time 10 > log.txt 2>&1
cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep -v 'k\|M' >> speed.txt
for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep k | sed 's/k//g'`
do
	declare -i k
	k=$i
	k=k*1024
	echo $k >> speed.txt
done
for i in `cat log.txt | tr '\r' '\n' | awk '{print $NF}' | sed '1,3d;$d' | grep M | sed 's/M//g'`
do
	i=$(echo | awk '{print '$i'*10 }')
	declare -i M
	M=$i
	M=M*1024*1024/10
	echo $M >> speed.txt
done
declare -i max
max=0
for i in `cat speed.txt`
do
	if [ $i -ge $max ]
	then
		max=$i
	fi
done
rm -rf log.txt speed.txt
echo $max
}

function getip (){
while true
do
	while true
	do
		declare -i ipnum
		declare -i iplist
		declare -i n
		rm -rf rtt data.txt meta.txt log.txt anycast.txt temp.txt speed.txt
		mkdir rtt
		while true
		do
			if [ -f "$ips.txt" ]
			then
				echo 指向解析获取CF节点IP
				resolveip=$(cat $ips.txt)
				while true
				do
					if [ ! -f "meta.txt" ]
					then
						curl --$ips --resolve speed.cloudflare.com:443:$resolveip --retry 3 -s https://speed.cloudflare.com/meta | sed -e 's/{//g' -e 's/}//g' -e 's/"//g' -e 's/,/\n/g'>meta.txt
					else
						asn=$(cat meta.txt | grep asn: | awk -F: '{print $2}')
						city=$(cat meta.txt | grep city: | awk -F: '{print $2}' | sed -e 's/ //g')
						latitude=$(cat meta.txt | grep latitude: | awk -F: '{print $2}')
						longitude=$(cat meta.txt | grep longitude: | awk -F: '{print $2}')
						curl --$ips --resolve service.anycast.eu.org:443:$resolveip --retry 3 "https://service.anycast.eu.org?asn="$asn"&city="$city"" -o data.txt -#
						break
					fi
				done
			else
				echo DNS解析获取CF节点IP
				while true
				do
					if [ ! -f "meta.txt" ]
					then
						curl --$ips --retry 3 -s https://speed.cloudflare.com/meta | sed -e 's/{//g' -e 's/}//g' -e 's/"//g' -e 's/,/\n/g'>meta.txt
					else
						asn=$(cat meta.txt | grep asn: | awk -F: '{print $2}')
						city=$(cat meta.txt | grep city: | awk -F: '{print $2}' | sed -e 's/ //g')
						latitude=$(cat meta.txt | grep latitude: | awk -F: '{print $2}')
						longitude=$(cat meta.txt | grep longitude: | awk -F: '{print $2}')
						curl --$ips --retry 3 "https://service.anycast.eu.org?asn="$asn"&city="$city"" -o data.txt -#
						break
					fi
				done
			fi
			if [ -f "data.txt" ]
			then
				break
			fi
		done
		domain=$(cat data.txt | grep domain= | cut -f 2- -d'=')
		file=$(cat data.txt | grep file= | cut -f 2- -d'=')
		url=$(cat data.txt | grep url= | cut -f 2- -d'=')
		app=$(cat data.txt | grep app= | cut -f 2- -d'=')
		if [ "$app" != "$version" ]
		then
			echo 发现新版本程序: $app
			echo 更新地址: $url
			echo 更新后才可以使用
			exit
		fi
		if [ $selfmode == 1 ]
		then
			rm -rf data.txt
			n=0
			while true
			do
				if [ $n == 256 ]
				then
					break
				else
					echo 正在生成自定义IP $selfip.$n
					echo $selfip.$n>>anycast.txt
					n=n+1
				fi
			done
		else
			for i in `cat data.txt | sed '1,4d'`
			do
				echo $i>>anycast.txt
			done
		fi
		rm -rf meta.txt data.txt
		ipnum=$(cat anycast.txt | wc -l)
		iplist=ipnum/tasknum
		declare -i a=1
		declare -i b=1
		for i in `cat anycast.txt`
		do
			echo $i>>rtt/$b.txt
			if [ $a == $iplist ]
			then
				a=1
				b=b+1
			else
				a=a+1
			fi
		done
		rm -rf anycast.txt
		if [ $a != 1 ]
		then
			a=1
			b=b+1
		fi
		while true
		do
			if [ $a == $b ]
			then
				break				
			else
				rtt $a &
			fi
			a=a+1
		done
		while true
		do
			sleep 2
			n=$(ps | grep curl | grep -v "grep" | wc -l)
			if [ $n -ne 0 ]
			then
				echo 等待RTT测试结束,剩余进程数 $n
			else
				echo RTT测试完成
				sleep 1
				break
			fi
		done
		n=$(ls rtt | wc -l)
		if [ $n -ge 3 ]
		then
			cat rtt/*.log | sort -n | awk '{print $1"_"$2}'>ip.txt
			echo 待测速的IP地址
			echo $(sed -n '1p' ip.txt | awk -F_ '{print " 第1个 IP "$2" 往返延迟 "$1}')
			echo $(sed -n '2p' ip.txt | awk -F_ '{print " 第2个 IP "$2" 往返延迟 "$1}')
			echo $(sed -n '3p' ip.txt | awk -F_ '{print " 第3个 IP "$2" 往返延迟 "$1}')
			n=0
			for ip in `cat ip.txt`
			do
				if [ $n == 3 ]
				then
					echo 没有满足速度要求的IP
					break
				else
					n=n+1
				fi
				avgms=`echo $ip | awk -F_ '{print $1}'`
				ip=`echo $ip | awk -F_ '{print $2}'`
				echo 正在测试 $ip
				max=`speedtest $ip`
				if [ $max -ge $speed ]
				then
					anycast=$ip
					max=$[$max/1024]
					echo $ip 峰值速度 $max kB/s
					break
				else
				max=$[$max/1024]
				echo $ip 峰值速度 $max kB/s
				curl --$ips --resolve service.anycast.eu.org:443:$ip --retry 3 -s -X POST -d ''$version-$ip-$max'' "https://service.anycast.eu.org?asn="$asn"&city="$city"" -o /dev/null --connect-timeout 5 --max-time 10
				fi
			done
			rm -rf rtt ip.txt
			if [ $n != 3 ]
			then
				break
			fi
		else
			echo 当前IP存在RTT丢包
			echo RTT超时时间调整为2秒
			timeout=2
		fi
	done
		break
done
}

function singletest (){
read -p "请输入需要测速的IP: " testip
curl --resolve update.anycast.eu.org:443:$testip https://update.anycast.eu.org -o temp.txt -#
domain=$(cat temp.txt | grep domain= | cut -f 2- -d'=')
file=$(cat temp.txt | grep file= | cut -f 2- -d'=')
curl --resolve $domain:443:$testip https://$domain/$file -o /dev/null
}

version=20210903
declare -i mode
while true
do
	echo 1. IPV4优选
	echo 2. IPV6优选
	echo 3. 自定义IPV4段
	echo 4. 单IP测速
	echo 5. 清空缓存
	echo 0. 退出
	read -p "请输入需要进入的模式: " mode
	if [ $mode -ge 0 ] && [ $mode -le 5 ]
	then
		case $mode in
				1)
				ips=ipv4
				selfmode=0
				bettercloudflareip
				break
				;;
				2)
				ips=ipv6
				selfmode=0
				bettercloudflareip
				break
				;;
				3)
				ips=ipv4
				selfmode=1
				read -p "请输入C类自定义IPV4(格式 1.1.1):" selfip
				bettercloudflareip
				break
				;;
				4)
				singletest
				;;
				5)
				rm -rf ipv4.txt ipv6.txt rtt data.txt meta.txt log.txt anycast.txt temp.txt speed.txt
				clear
				echo 缓存已经清空
				;;
				0)
				clear
				echo 退出成功
				break
				;;
		esac
	else
		echo 输入不正确,重新输入对应的模式
	fi
done
