/,/<\/div>/p'|sed -n '/
/,/<\/pre>/p'|sed 's///'|sed 's/<[^>]*>//g')
while IFS= read -r line;do
[[ -z $line ]]&&continue
if [[ $line == *:* ]];then
if [[ $line =~ ^([^:]+):(.*)$ ]];then
field_name="${BASH_REMATCH[1],,}"
field_value=$(echo "${BASH_REMATCH[2]}"|sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
fi
[[ -z $field_value ]]&&continue
if [[ $field_name == "$last_field_name" ]];then
getbgp["$field_name"]+=", $field_value"
elif [[ -z ${getbgp[$field_name]} ]];then
getbgp["$field_name"]="$field_value"
last_field_name="$field_name"
else
last_field_name=""
fi
fi
done <<<"$CONTENT"
get_bgp
calc_upstream $1 "$RESPONSE"
calc_ix $1
calc_peers "$RESPONSE"
}
db_henet(){
local temp_info="$Font_Cyan$Font_B${sinfo[bgp]}${Font_I}HE.NET $Font_Suffix"
((ibar_step+=4))
show_progress_bar "$temp_info" $((50-7-${sinfo[lbgp]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
getbgp=()
local last_field_name=""
local attempts=0
local max_attempts=5
local RESPONSE=""
local CONTENT=""
while [[ $attempts -lt $max_attempts ]];do
RESPONSE=$(curl $CurlARG -$1 --user-agent "$UA_Browser" --max-time 10 -Ls "https://bgp.he.net/whois/ip/$IP")
if echo "$RESPONSE"|jq empty 2>/dev/null;then
CONTENT=$(echo "$RESPONSE"|jq -r '.data' 2>/dev/null)
if [[ -n $CONTENT ]];then
break
fi
fi
((attempts++))
sleep 3
done
CONTENT=$(echo "$CONTENT"|sed 's/\\n/\n/g'|sed 's/\\t/\t/g')
while IFS= read -r line;do
[[ -z $line ]]&&continue
if [[ $line == *:* ]];then
if [[ $line =~ ^([^:]+):(.*)$ ]];then
field_name="${BASH_REMATCH[1],,}"
field_value=$(echo "${BASH_REMATCH[2]}"|sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
fi
[[ -z $field_value ]]&&continue
if [[ $field_name == "$last_field_name" ]];then
getbgp["$field_name"]+=", $field_value"
elif [[ -z ${getbgp[$field_name]} ]];then
getbgp["$field_name"]="$field_value"
last_field_name="$field_name"
else
last_field_name=""
fi
fi
done <<<"$CONTENT"
bgp[asn]="${bgp[asn]:-${getbgp[origin]:-${getbgp[originas]:-${getbgp[aut-num]}}}}"
[[ ${bgp[asn]} == "N/A" ]]&&bgp[asn]=""
bgp[prefix]="${bgp[prefix]:-${getbgp[route]:-${getbgp[route6]:-${getbgp[cidr]:-${getbgp[inetrev]}}}}}"
if [[ ${bgp[prefix]} == */* ]];then
bgp[ip0]="${bgp[prefix]%%/*}"
bgp[prefixnum]="${bgp[prefix]##*/}"
fi
get_bgp
}
get_neighbor(){
local temp_info="$Font_Cyan$Font_B${sinfo[neighbor]}$Font_Suffix"
((ibar_step+=1))
show_progress_bar "$temp_info" $((50-${sinfo[lneighbor]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
local convert_output
local cidr="${IP%.*}.0/24"
if [[ ${bgp[prefixnum]} != "24" ]];then
bgp[neighbortotal]="256"
convert_output=$(curl -s -m 10 --user-agent "$UA_Browser" "https://bgp.tools/pfximg/$cidr"|convert png:- txt:- 2>/dev/null)
[[ -n $convert_output ]]&&bgp[neighboractive]=$(grep -E -c "#0003FF|#4041BE" <<<"$convert_output")
fi
bgp[iptotal]="$((2**(32-${bgp[prefixnum]})))"
convert_output=$(curl -s -m 10 --user-agent "$UA_Browser" "https://bgp.tools/pfximg/${bgp[prefix]}"|convert png:- txt:- 2>/dev/null)
[[ -n $convert_output ]]&&bgp[ipactive]=$(grep -E -c "#0003FF|#4041BE" <<<"$convert_output")
}
generate_uuidv4(){
local uuid=""
local chars="0123456789abcdef"
for i in {1..36};do
if [[ $i == 9 || $i == 14 || $i == 19 || $i == 24 ]];then
uuid+="-"
elif [[ $i == 15 ]];then
uuid+="4"
elif [[ $i == 20 ]];then
r=$((RANDOM%16))
y=$((r&0x3|0x8))
uuid+=${chars:y:1}
else
r=$((RANDOM%16))
uuid+=${chars:r:1}
fi
done
echo "$uuid"
}
get_nat(){
local temp_info="$Font_Cyan$Font_B${sinfo[nat]}$Font_Suffix"
((ibar_step+=1))
show_progress_bar "$temp_info" $((50-${sinfo[lnat]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
getnat=()
if [[ $rawgithub == *"github.com"* ]];then
local result=$(stun "stun.l.google.com" 2>/dev/null)
else
local result=$(stun "stun.miwifi.com" 2>/dev/null)
fi
getnat[nat]=$(echo "$result"|grep -oE "0x[0-9A-Fa-f]+")
[[ -z ${getnat[nat]} ]]&&return 1
local val=$((${getnat[nat]}))
local portpres=$((val&0x01))
local filtering=$(((val&0x06)>>1))
local mapping=$(((val&0x08)>>3))
local hairpin=$(((val&0x10)>>4))
getnat[m]=$mapping
getnat[f]=$filtering
getnat[p]=$portpres
getnat[h]=$hairpin
local ntype="fail"
getnat[char]=0
if [[ ${getnat[nat]} == "0xFFFFFFFF" || ${getnat[nat]} == "0x0000EE" ]];then
ntype="fail"
elif [[ $mapping -eq 1 && $filtering -eq 1 ]];then
ntype="firewall"
elif [[ $mapping -eq 1 && $filtering -eq 2 ]];then
ntype="block"
elif [[ $mapping -eq 1 && $filtering -eq 3 ]];then
ntype="unknown"
elif [[ $mapping -eq 0 && $filtering -eq 0 ]];then
ntype="open"
elif [[ $mapping -eq 0 && $filtering -eq 1 ]];then
ntype="full"
[[ $hairpin -eq 0 ]]&&slocal[full]="$Back_Green${slocal[full]}"||slocal[full]="$Back_Yellow${slocal[full]}"
getnat[char]=1
elif [[ $mapping -eq 0 && $filtering -eq 2 ]];then
ntype="rest"
getnat[char]=1
elif [[ $mapping -eq 0 && $filtering -eq 3 ]];then
ntype="portrest"
getnat[char]=1
elif [[ $mapping -eq 1 ]];then
ntype="symm"
getnat[char]=1
fi
getnat[type]=$ntype
}
get_tcp(){
local temp_info="$Font_Cyan$Font_B${sinfo[tcp]}$Font_Suffix"
((ibar_step+=1))
show_progress_bar "$temp_info" $((50-${sinfo[ltcp]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
gettcp=()
gettcp[tcpcc]=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null|awk '{$1=$1};1'||echo "N/A")
gettcp[qdisc]=$(sysctl -n net.core.default_qdisc 2>/dev/null|awk '{$1=$1};1'||echo "N/A")
gettcp[rmem]=$(sysctl -n net.ipv4.tcp_rmem 2>/dev/null|awk '{$1=$1};1'||echo "N/A")
gettcp[wmem]=$(sysctl -n net.ipv4.tcp_wmem 2>/dev/null|awk '{$1=$1};1'||echo "N/A")
}
calculate_delay(){
local delay=0x2800
local num1=$1
local num2=$2
if [[ $(echo "$num1 > 0 && $num1 <= 80"|bc) -eq 1 ]];then
delay=$((delay+0x40))
elif [[ $(echo "$num1 > 80 && $num1 <= 160"|bc) -eq 1 ]];then
delay=$((delay+0x44))
elif [[ $(echo "$num1 > 160 && $num1 <= 240"|bc) -eq 1 ]];then
delay=$((delay+0x46))
elif [[ $(echo "$num1 > 200"|bc) -eq 1 ]];then
delay=$((delay+0x47))
fi
if [[ $(echo "$num2 > 0 && $num2 <= 80"|bc) -eq 1 ]];then
delay=$((delay+0x80))
elif [[ $(echo "$num2 > 80 && $num2 <= 160"|bc) -eq 1 ]];then
delay=$((delay+0xA0))
elif [[ $(echo "$num2 > 160 && $num2 <= 240"|bc) -eq 1 ]];then
delay=$((delay+0xB0))
elif [[ $(echo "$num2 > 240"|bc) -eq 1 ]];then
delay=$((delay+0xB8))
fi
local delay_hex=$(printf "%X" "$delay")
local unicode_char=$(echo -e "\u${delay_hex: -4}")
if [[ $(echo "$num1 > 240"|bc) -eq 1 || $(echo "$num2 > 240"|bc) -eq 1 || $(echo "$num1 == 0"|bc) -eq 1 || $(echo "$num2 == 0"|bc) -eq 1 ]];then
echo "$Font_Red$unicode_char"
elif [[ $(echo "$num1 > 150"|bc) -eq 1 || $(echo "$num2 > 150"|bc) -eq 1 ]];then
echo "$Font_Yellow$unicode_char"
elif [[ $(echo "$num1 <= 150"|bc) -eq 1 && $(echo "$num2 <= 150"|bc) -eq 1 ]];then
echo "$Font_Green$unicode_char"
else
echo "$Font_Red$unicode_char"
fi
}
ping_test(){
local domain=$1
local protocol=$2
local psize=$3
local count=$4
local pv=$5
local provider=$6
local ipv=$7
local port=$8
[[ -z $domain || -z $ipv || -z $protocol || -z $psize || -z $count || -z $pv || -z $provider ]]&&return 1
[[ $ipv != "4" && $ipv != "6" ]]&&return 1
[[ $protocol != "ICMP" && $protocol != "TCP" && $protocol != "UDP" ]]&&return 1
[[ -z $port ]]&&port=80
local response
local tmpresu=""
local pingcom=""
if [[ $protocol == "ICMP" ]];then
pingcom="mtr -$ipv -c 1 -f 100 -C -G 1 -s $psize $domain"
elif [[ $protocol == "TCP" ]];then
pingcom="mtr -$ipv --tcp -P $port -c 1 -f 100 -C -G 1 -s $psize $domain"
elif [[ $protocol == "UDP" ]];then
pingcom="mtr -$ipv --udp -P $port -c 1 -f 100 -C -G 1 -s $psize $domain"
fi
response=$($pingcom 2>&1)
tmpresu=$(echo "$response"|tr -d '\n'|awk -F',' '{print $24}')
[[ -z $tmpresu || ! $tmpresu =~ ^[0-9]+(\.[0-9]+)?$ || ${#tmpresu} -gt 6 ]]&&tmpresu=0.00
echo "$pv $provider $ipv $count $tmpresu"
}
process_pingtestresult(){
local testresult=$1
local -A midresu
local tmp_space=""
local ipv
local index
local numbers
local total
local count
local lost
local result
[[ $mode_ping -eq 1 ]]&&tmp_space=" "
IFS=$'\n' read -r -d '' -a lines <<<"$testresult"
for line in "${lines[@]}";do
line=$(echo "$line"|xargs)
[[ -z $line ]]&&continue
IFS=' ' read -ra parts <<<"$line"
index="${parts[0]}${parts[1]}${parts[2]}${parts[3]}"
ipv="${parts[2]}"
pout[$index]="${parts[4]}"
done
for province in $(echo "${!pcode[@]}"|sort -n);do
for j in 1 2 3;do
total=0
count=0
lost=""
for i in $(seq 1 $ping_test_count);do
numbers=${pout[$province$j$ipv$i]}
if [[ $numbers =~ ^0\.0*$ ]];then
lost="$Font_Red"
else
total=$(echo "$total + $numbers"|bc)
((count++))
fi
done
if ((count>0));then
local avg=$(echo "scale=0; $total / $count"|bc)
else
local avg=0
fi
result=""
for ((i=1; i=max_threads));then
wait -n
((current_threads--))
fi
done
done
done
wait)
process_pingtestresult "$tmpresult"
}
show_delay(){
local count=0
local resu_per_line=$(((display_max_len+1)/(ping_test_count*3/2+12)))
if [[ $mode_ping -eq 1 ]];then
resu_per_line=1
echo -ne "\r${sdelay[pingmode]}\n"
else
count=2
echo -ne "\r${sdelay[title]}"
fi
for key in $(echo "${!pcode[@]}"|tr ' ' '\n'|sort -n);do
((count++))
if ((resu_per_line==1));then
echo -ne "\r${presu[$key]}\n"
elif ((count%resu_per_line==0));then
echo -ne "${presu[$key]}\n"
elif ((count%resu_per_line==1));then
echo -ne "\r${presu[$key]} "
else
echo -ne "${presu[$key]} "
fi
done
((count%resu_per_line!=0))&&echo
}
nexttrace_test(){
local domain="$1"
local rmode="$2"
local rnum="$3"
local ipv="$4"
local response
local max_retries=10
local retry_delay=5
local retry_count=0
while [[ $retry_count -lt $max_retries ]];do
response=$(timeout -s SIGKILL 50 nexttrace -p 80 -q 8 -"$ipv" --"$rmode" --raw --psize 1400 "$domain" 2>/dev/null)
[[ $response != *"*please try again later*"* && $response == *"traceroute to"* ]]&&break
retry_count=$((retry_count+1))
[[ $retry_count -lt $max_retries ]]&&sleep "$retry_delay"
done
declare -A ips asns regions orgs
local max_hop=0
local cn_hop=0
local all_asn=""
local tresucn=""
local tresuww="NoData"
while IFS= read -r line;do
if [[ $line != *"|"* ]];then
continue
fi
IFS='|' read -r -a elements <<<"$line"
local hop="${elements[0]}"
local ip="${elements[1]}"
local asn="${elements[4]}"
local region="${elements[5]}"
[[ ${elements[6]} == "香港" || ${elements[6]} == "澳门" || ${elements[6]} == "台湾" ]]&®ion="${elements[6]}"
local org="${elements[9]}"
[[ -n ${ips[$hop]} ]]&&continue
[[ $ip == 59.43.* ]]&&asn="4809"
[[ $org == *CTGNet* ]]&&asn="23764"
[[ $cn_hop == 0 && $region == *中国* ]]&&cn_hop=$hop
[[ -n $asn ]]&&all_asn="${all_asn}AS$asn "
ips["$hop"]="$ip"
asns["$hop"]="$asn"
regions["$hop"]="$region"
orgs["$hop"]="$org"
if ((hop>max_hop));then
max_hop="$hop"
fi
done <<<"$response"
[[ $cn_hop == 0 || $cn_hop == $max_hop ]]&&tresucn="Hidden"
[[ ${asns[$cn_hop]} == "17676" ]]&&cn_hop=$((cn_hop+1))
case "${asns[$cn_hop]}" in
"4134")tresucn="163"
;;
"4837")tresucn="4837"
if ((cn_hop>1));then
[[ ${asns[$((cn_hop-1))]} == "10099" ]]&&tresucn="10099"
fi
;;
"58453")tresucn="CMI"
;;
"58807")tresucn="CMIN2"
;;
"9808")tresucn="CMI"
[[ $all_asn == *AS58807* ]]&&tresucn="CMIN2"
;;
"9929")tresucn="9929"
;;
"10099")tresucn="10099"
[[ $all_asn == *AS9929* ]]&&tresucn="9929"
;;
"4809")tresucn="CN2GIA"
if ((cn_hop>1));then
[[ $all_asn == *AS23764* ]]&&tresucn="CTGGIA"
else
for ((hop=cn_hop; hop<=max_hop; hop++));do
[[ ${asns[$hop]} == "4809" || ${asns[$hop]} == "23764" ]]&&continue
if [[ ${ips[$hop]} == 202.97* ]];then
tresucn="CN2GT"
fi
break
done
fi
;;
"23764")tresucn="CTGGIA"
;;
"4538")tresucn="CERNET"
;;
"7497")tresucn="CSTNET"
;;
*)tresucn="NoData"
if [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
elif [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2"
elif [[ $all_asn == *AS9808* ]];then
tresucn="CMI"
elif [[ $all_asn == *AS4134* ]];then
tresucn="163"
elif [[ $all_asn == *AS4837* ]];then
tresucn="4837"
fi
esac
for ((hop=cn_hop-1; hop>0; hop--));do
if [[ -n ${asns[$hop]} && ${asns[$hop]} != "58453" && ${asns[$hop]} != "58807" && ${asns[$hop]} != "4837" && ${asns[$hop]} != "10099" && ${asns[$hop]} != "9929" && ${asns[$hop]} != "4134" && ${asns[$hop]} != "4809" && ${asns[$hop]} != "4808" && ${asns[$hop]} != "23764" && ${asns[$hop]} != "4538" && ${asns[$hop]} != "7497" ]];then
tresuww="AS${asns[$hop]}"
break
fi
done
if [[ -n $tresuww ]];then
[[ -n ${AS_MAPPING[$tresuww]} ]]&&tresuww="${AS_MAPPING[$tresuww]}"
fi
echo "$rnum $tresuww $tresucn"
}
mtr_test(){
local domain="$1"
local rmode="$2"
local rnum="$3"
local ipv="$4"
declare -A ips
declare -A asns
local max_hop=0
local cn_hop=0
local all_asn=""
local tresucn="NoData"
local tresuww="NoData"
local max_retries=10
local retry_delay=5
local retry_count=0
while [[ $retry_count -lt $max_retries ]];do
response=$(timeout 60 mtr -"$ipv" --"$rmode" --no-dns -y 0 -P 80 -c 8 -C -Z 1 -G 1 -s 1400 "$domain" 2>/dev/null)
[[ $response != *"*mtr:*"* && $response == *"OK,"* ]]&&break
retry_count=$((retry_count+1))
[[ $retry_count -lt $max_retries ]]&&sleep "$retry_delay"
done
while IFS= read -r line;do
[[ $line != *"OK,"* ]]&&continue
IFS=',' read -r -a elements <<<"$line"
local hop="${elements[4]}"
local ip="${elements[5]}"
[[ ${elements[6]} != *"?"* ]]&&local asn="${elements[6]#AS}"
ips["$hop"]="$ip"
asns["$hop"]="$asn"
[[ -n $asn && $asn != *"?"* ]]&&all_asn="$all_asn$asn "
((hop>max_hop))&&max_hop="$hop"
[[ $cn_hop -eq 0 ]]&&[[ $asn =~ ^("58453"|"58807"|"4837"|"10099"|"9929"|"4134"|"4809"|"23764"|"4538"|"7497")$ ]]&&cn_hop="$hop"
done <<<"$response"
[[ $cn_hop == 0 || $cn_hop == $max_hop ]]&&tresucn="Hidden"
[[ ${asns[$cn_hop]} == "17676" ]]&&cn_hop=$((cn_hop+1))
case "${asns[$cn_hop]}" in
"4134")tresucn="163"
if [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS23764* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS4809* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS23764* ]];then
tresucn="CTGGIA"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2GIA"
elif [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
fi
;;
"4837")tresucn="4837"
if [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS23764* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS4809* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS23764* ]];then
tresucn="CTGGIA"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2GIA"
elif [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
fi
;;
"58453")tresucn="CMI"
if [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS23764* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS4809* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS23764* ]];then
tresucn="CTGGIA"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2GIA"
elif [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
fi
;;
"58807")tresucn="CMIN2"
;;
"9808")tresucn="CMI"
if [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS23764* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS4809* && $all_asn == *AS4134* ]];then
tresucn="CN2GT"
elif [[ $all_asn == *AS23764* ]];then
tresucn="CTGGIA"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2GIA"
elif [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
fi
;;
"9929")tresucn="9929"
;;
"10099")tresucn="10099"
[[ $all_asn == *AS9929* ]]&&tresucn="9929"
;;
"4809")tresucn="CN2GIA"
if ((cn_hop>1));then
[[ $all_asn == *AS23764* ]]&&tresucn="CTGGIA"
else
for ((hop=cn_hop; hop<=max_hop; hop++));do
[[ ${asns[$hop]} == "4809" || ${asns[$hop]} == "23764" ]]&&continue
if [[ ${ips[$hop]} == 202.97* ]];then
tresucn="CN2GT"
fi
break
done
fi
;;
"23764")tresucn="CTGGIA"
;;
"4538")tresucn="CERNET"
;;
"7497")tresucn="CSTNET"
;;
*)tresucn="NoData"
if [[ $all_asn == *AS58807* ]];then
tresucn="CMIN2"
elif [[ $all_asn == *AS9929* ]];then
tresucn="9929"
elif [[ $all_asn == *AS10099* ]];then
tresucn="10099"
elif [[ $all_asn == *AS4809* ]];then
tresucn="CN2"
elif [[ $all_asn == *AS9808* ]];then
tresucn="CMI"
elif [[ $all_asn == *AS4134* ]];then
tresucn="163"
elif [[ $all_asn == *AS4837* ]];then
tresucn="4837"
fi
esac
for ((hop=cn_hop-1; hop>0; hop--));do
if [[ -n ${asns[$hop]} && ${asns[$hop]} != "58453" && ${asns[$hop]} != "58807" && ${asns[$hop]} != "4837" && ${asns[$hop]} != "10099" && ${asns[$hop]} != "9929" && ${asns[$hop]} != "4134" && ${asns[$hop]} != "4809" && ${asns[$hop]} != "23764" && ${asns[$hop]} != "4538" && ${asns[$hop]} != "7497" ]];then
tresuww="AS${asns[$hop]}"
break
fi
done
if [[ -n $tresuww ]];then
[[ -n ${AS_MAPPING[$tresuww]} ]]&&tresuww="${AS_MAPPING[$tresuww]}"
fi
echo "$rnum $tresuww $tresucn"
}
get_route(){
ibar_step=19
local temp_info="$Font_Cyan$Font_B${sinfo[route]}$Font_Suffix"
((ibar_step+=1))
show_progress_bar "$temp_info" $((50-${sinfo[lroute]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
local ipv=$1
local rdomain
rdomain[1]="bj-ct-v$ipv.ip.zstaticcdn.com"
rdomain[2]="bj-cu-v$ipv.ip.zstaticcdn.com"
rdomain[3]="bj-cm-v$ipv.ip.zstaticcdn.com"
rdomain[4]="sh-ct-v$ipv.ip.zstaticcdn.com"
rdomain[5]="sh-cu-v$ipv.ip.zstaticcdn.com"
rdomain[6]="sh-cm-v$ipv.ip.zstaticcdn.com"
rdomain[7]="gd-ct-v$ipv.ip.zstaticcdn.com"
rdomain[8]="gd-cu-v$ipv.ip.zstaticcdn.com"
rdomain[9]="gd-cm-v$ipv.ip.zstaticcdn.com"
local max_threads=18
local available_memory=1024
[[ "$(uname)" != "Darwin" ]]&&available_memory=$(free -m|awk '/Mem:/ {print $7}')
local max_threads_by_memory=$(echo "$available_memory / 28"|bc)
((max_threads_by_memory=max_threads));then
wait -n
((current_threads--))
else
sleep 2
fi
done
wait)
while IFS= read -r line;do
[[ -z $line ]]&&continue
read -r index rww_value rcn_value <<<"$line"
[[ $rcn_value == *GIA ]]&&rgia=1
done <<<"$tmpresult"
while IFS= read -r line;do
[[ -z $line ]]&&continue
read -r index rww_value rcn_value <<<"$line"
rww["$index"]="$rww_value"
rcn["$index"]="$rcn_value"
[[ ${rcn["$index"]} == "CN2GT" && $rgia -eq 1 ]]&&rcn["$index"]="CN2GIA"
printf -v spaceww "%$((8-${#rww_value}))s" ""
printf -v spacecn "%$((6-${#rcn_value}))s" ""
case "$rww_value" in
"Hidden")colorww="$Back_Red$Font_White$Font_U$Font_B";;
"NoData")colorww="$Back_Yellow$Font_White$Font_U$Font_B";;
*)colorww="$Back_Blue$Font_White$Font_U$Font_B"
esac
case "$rcn_value" in
"Hidden")colorcn="$Back_Red$Font_White$Font_U$Font_B";;
"NoData")colorcn="$Back_Yellow$Font_White$Font_U$Font_B";;
*)colorcn="$Back_Green$Font_White$Font_U$Font_B"
esac
routww["$index"]="$spaceww$colorww$rww_value$Font_Suffix"
routcn["$index"]="$colorcn$rcn_value$Font_Suffix$spacecn"
done <<<"$tmpresult"
}
function colorize_latency(){
local latency_ms=$1
local total_length=${2:-2}
local value
local pure_text
local padding
local colored_result
if [[ ! $latency_ms =~ ^[0-9]+(\.[0-9]+)?ms$ ]];then
echo ""
return 1
fi
value=$(echo "$latency_ms"|sed 's/ms//')
if (($(echo "$value <= 150"|bc -l)));then
colored_result="$Font_Green$latency_ms"
elif (($(echo "$value <= 240"|bc -l)));then
colored_result="$Font_Yellow$latency_ms"
else
colored_result="$Font_Red$latency_ms"
fi
pure_text="$latency_ms"
pure_length=${#pure_text}
if ((pure_length$Font_Suffix${routcn[1]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[3]}$Font_Green->$Font_Suffix${routcn[3]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[5]}$Font_Green->$Font_Suffix${routcn[5]}\n"
echo -ne "\r$Font_Cyan北京UDP:$Font_Green电信 $Font_Suffix${routww[2]}$Font_Green->$Font_Suffix${routcn[2]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[4]}$Font_Green->$Font_Suffix${routcn[4]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[6]}$Font_Green->$Font_Suffix${routcn[6]}\n"
echo -ne "\r$Font_Cyan上海TCP:$Font_Green电信 $Font_Suffix${routww[7]}$Font_Green->$Font_Suffix${routcn[7]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[9]}$Font_Green->$Font_Suffix${routcn[9]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[11]}$Font_Green->$Font_Suffix${routcn[11]}\n"
echo -ne "\r$Font_Cyan上海UDP:$Font_Green电信 $Font_Suffix${routww[8]}$Font_Green->$Font_Suffix${routcn[8]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[10]}$Font_Green->$Font_Suffix${routcn[10]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[12]}$Font_Green->$Font_Suffix${routcn[12]}\n"
echo -ne "\r$Font_Cyan广州TCP:$Font_Green电信 $Font_Suffix${routww[13]}$Font_Green->$Font_Suffix${routcn[13]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[15]}$Font_Green->$Font_Suffix${routcn[15]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[17]}$Font_Green->$Font_Suffix${routcn[17]}\n"
echo -ne "\r$Font_Cyan广州UDP:$Font_Green电信 $Font_Suffix${routww[14]}$Font_Green->$Font_Suffix${routcn[14]} || $Font_Green联通$Font_Suffix $Font_Suffix${routww[16]}$Font_Green->$Font_Suffix${routcn[16]} || $Font_Green移动$Font_Suffix $Font_Suffix${routww[18]}$Font_Green->$Font_Suffix${routcn[18]}\n"
else
local tmppv=""
local tmpfont=""
local tmpback=""
local tmpdelay=""
for ((i=1; i<=rmtestnum; i++));do
ii=$(printf "%02d" "$i")
case $((i%3)) in
1)tmppv="电信"
tmpfont="$Font_Cyan"
tmpback="$Back_Cyan"
;;
2)tmppv="联通"
tmpfont="$Font_Green"
tmpback="$Back_Green"
;;
0)tmppv="移动"
tmpfont="$Font_Purple"
tmpback="$Back_Purple"
esac
echo -ne "\r$tmpback$Font_White$Font_B ${pname[${rmcode[$i]}]} $tmppv $Font_Suffix$Back_White$tmpfont$Font_B ${rmww[$ii]} -> ${rmcn[$ii]} $Font_Suffix\n"
echo -ne "\r$Back_Blue$Font_White地理路径:${rmallgeo[$ii]} 自治系统路径:${rmallasn[$ii]} $Font_Suffix\n"
local varb="${rmmaxhop[$ii]:-0}"
varb=${varb#0}
local mergejump=" "
for ((j=1; j<=varb; j++));do
jj=$(printf "%02d" "$j")
mergeroute=0
mergejump=" "
if [[ -n ${rmresu[$ii${jj}2]} ]];then
local compA="${rmresu[$ii${jj}5]#"${rmresu[$ii${jj}5]%%[![:space:]\*]*}"}"
compA=$(awk '{print $1 " " $2}' <<<"$compA")
for ((k=j+1; k0; k--));do
kk=$(printf "%02d" "$k")
local compB="${rmresu[$ii${kk}5]#"${rmresu[$ii${kk}5]%%[![:space:]\*]*}"}"
compB=$(awk '{print $1 " " $2}' <<<"$compB")
if [[ -n ${rmresu[$ii${kk}2]} &&
${rmresu[$ii${jj}3]} == "${rmresu[$ii${kk}3]}" &&
${rmresu[$ii${jj}4]} == "${rmresu[$ii${kk}4]}" ]]&&[[ $compA == *"$compB"* ||
$compB == *"$compA"* ]];then
continue 2
fi
done
fi
tmpdelay=$(colorize_latency "${rmresu[$ii${jj}1]}" 9)
if [[ $1 -eq 4 ]];then
echo -ne "\r$Font_B$(printf '%2s' "$j")$mergejump$Font_Suffix $tmpdelay $(printf '%-13s' "${rmresu[$ii${jj}2]}")$Font_B$(printf '%-10s' "${rmresu[$ii${jj}3]}")$(printf '%-18s' "${rmresu[$ii${jj}4]}")$Font_Suffix${rmresu[$ii${jj}5]}\n"
else
echo -ne "\r$Font_B$(printf '%2s' "$j")$mergejump$Font_Suffix $tmpdelay $(printf '%-27s' "${rmresu[$ii${jj}2]}")$Font_B$(printf '%-10s' "${rmresu[$ii${jj}3]}")$Font_Suffix${rmresu[$ii${jj}5]}\n"
fi
fi
done
done
fi
}
function mask_ip(){
local ip=$1
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]];then
echo "$ip"|awk -F. '{print $1"."$2".*.*"}'
elif [[ $ip =~ ^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$ ]];then
echo "$ip"|awk -F: '{
# 计算需要保留的段数(总段数8减去要掩码的5段)
keep = 8 - 5;
for(i=1; i<=NF; i++) {
if(i <= keep) {
printf "%s", $i;
} else {
printf "*";
}
if(i < 8) printf ":";
}
# 处理压缩形式的IPv6(::)
if(NF < 8) {
for(i=NF+1; i<=8; i++) {
if(i <= keep) {
printf "0";
} else {
printf "*";
}
if(i < 8) printf ":";
}
}
}'
else
return 1
fi
}
function extract_region(){
local input=$1
IFS=' ' read -ra parts <<<"$input"
local discard_patterns=("*" "中国" "电信" "联通" "移动")
local suffixes=("省" "市" "县" "维吾尔自治区" "回族自治区" "壮族自治区" "自治区" "特别行政区")
for part in "${parts[@]}";do
if [[ -z $part || $part =~ ^[[:punct:]]+$ || $part == *"."* || $part == *"RFC"* || $part == *"rfc"* || $part == *"Private"* || $part == *"Local"* || $part == *"DOD"* || $part == *"Anycast"* || $part == *"ASAPI"* || $part == *"网络故障"* ]];then
continue
fi
for pattern in "${discard_patterns[@]}";do
[[ $part == "$pattern" ]]&&continue 2
done
for suffix in "${suffixes[@]}";do
if [[ $part == *"$suffix" ]];then
part="${part%"$suffix"}"
break
fi
done
echo "$part"
return
done
echo ""
}
nexttrace_route(){
local domain="$1"
local rmode="$2"
local rnum="$3"
local ipv="$4"
local tmode
case "$rmode" in
1)tmode="--tcp";;
2)tmode="--udp"
esac
local output
local max_retries=10
local retry_delay=5
local retry_count=0
while [[ $retry_count -lt $max_retries ]];do
output=$(timeout -s SIGKILL 50 nexttrace -p 80 -q 8 -"$ipv" "$tmode" --psize 1400 "$domain" 2>/dev/null)
[[ $output != *"*please try again later*"* && $output == *"traceroute to"* ]]&&break
retry_count=$((retry_count+1))
[[ $retry_count -lt $max_retries ]]&&sleep "$retry_delay"
done
output=$(echo "$output"|sed 's/\x1b\[[0-9;]*m//g')
echo "$output"|awk -v rnum="$rnum" '
{
if ($1 ~ /^[0-9]+$/) {
hop = $1
ip = $2
if (ip != "*") {
as = ""
bracket = ""
desc = ""
ms = ""
# Extract AS information
for (i = 3; i <= NF; i++) {
if ($i ~ /^AS[0-9]+/) {
as = $i
} else if ($i ~ /^\[.*\]$/) {
bracket = $i
} else {
desc = desc " " $i
}
}
# 去除 desc 开头的空格
sub(/^ /, "", desc)
# Get the first millisecond value from the next line
getline next_line
if (next_line ~ /[0-9]+\.[0-9]+ ms/) {
match(next_line, /[0-9]+\.[0-9]+ ms/)
ms = substr(next_line, RSTART, RLENGTH)
gsub(/ /, "", ms)
}
# Print the formatted result
printf "|%s|%s|%s|%s|%s|%s|%s|\n", rnum, hop, ms, ip, as, bracket, desc
}
}
}'
}
get_route_mode(){
ibar_step=19
local temp_info="$Font_Cyan$Font_B${sinfo[moderoute]}$Font_Suffix"
((ibar_step+=1))
show_progress_bar "$temp_info" $((50-${sinfo[lmoderoute]}))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
local ipv=$1
local rdomain
rmresu=()
rmcode[0]=31
if [[ -z $mode_route_pv ]];then
rmtestnum=9
rmcode[1]=11
rmcode[2]=11
rmcode[3]=11
rmcode[4]=31
rmcode[5]=31
rmcode[6]=31
rmcode[7]=44
rmcode[8]=44
rmcode[9]=44
rdomain[0]="sh-ct-v$ipv.ip.zstaticcdn.com"
rdomain[1]="bj-ct-v$ipv.ip.zstaticcdn.com"
rdomain[2]="bj-cu-v$ipv.ip.zstaticcdn.com"
rdomain[3]="bj-cm-v$ipv.ip.zstaticcdn.com"
rdomain[4]="sh-ct-v$ipv.ip.zstaticcdn.com"
rdomain[5]="sh-cu-v$ipv.ip.zstaticcdn.com"
rdomain[6]="sh-cm-v$ipv.ip.zstaticcdn.com"
rdomain[7]="gd-ct-v$ipv.ip.zstaticcdn.com"
rdomain[8]="gd-cu-v$ipv.ip.zstaticcdn.com"
rdomain[9]="gd-cm-v$ipv.ip.zstaticcdn.com"
else
rmtestnum=3
rmcode[1]="$mode_route_pv"
rmcode[2]="$mode_route_pv"
rmcode[3]="$mode_route_pv"
rdomain[0]="sh-ct-v$ipv.ip.zstaticcdn.com"
rdomain[1]="${pcode[$mode_route_pv]}-ct-v$ipv.ip.zstaticcdn.com"
rdomain[2]="${pcode[$mode_route_pv]}-cu-v$ipv.ip.zstaticcdn.com"
rdomain[3]="${pcode[$mode_route_pv]}-cm-v$ipv.ip.zstaticcdn.com"
fi
local max_threads=18
local available_memory=1024
[[ "$(uname)" != "Darwin" ]]&&available_memory=$(free -m|awk '/Mem:/ {print $7}')
local max_threads_by_memory=$(echo "$available_memory / 28"|bc)
((max_threads_by_memory=max_threads));then
wait -n
((current_threads--))
else
sleep 2
fi
done
wait)
rmmaxhop=()
rmcnhop=()
rmallasn=()
rmallgeo=()
while IFS= read -r line;do
[[ -z $line ]]&&continue
IFS='|' read -ra fields <<<"$line"
i1=$(printf "%02d" "${fields[1]}")
i2=$(printf "%02d" "${fields[2]}")
rmresu["$i1${i2}1"]="${fields[3]}"
rmresu["$i1${i2}2"]=$(mask_ip "${fields[4]}")
rmresu["$i1${i2}3"]="${fields[5]}"
rmresu["$i1${i2}4"]="${fields[6]}"
rmresu["$i1${i2}5"]="${fields[7]}"
rmresu["$i1${i2}6"]=$(extract_region "${rmresu[$i1${i2}5]}")
[[ ${rmresu["$i1${i2}2"]} == 59.43.* ]]&&rmresu["$i1${i2}3"]="AS4809"
[[ ${rmresu["$i1${i2}5"]} == *CTGNet* ]]&&rmresu["$i1${i2}3"]="AS23764"
if [[ -z ${rmcnhop["$i1"]} ]]&&[[ ${rmresu["$i1${i2}5"]} == *中国* ]]&&[[ ${rmresu["$i1${i2}5"]} != *香港* ]]&&[[ ${rmresu["$i1${i2}5"]} != *澳门* ]]&&[[ ${rmresu["$i1${i2}5"]} != *台湾* ]];then
rmcnhop["$i1"]="$i2"
fi
if [[ -n ${rmresu[$i1${i2}6]} ]];then
if [[ ${rmallgeo[$i1]} == *"${rmresu[$i1${i2}6]}"* ]];then
rmallgeo[$i1]="${rmallgeo[$i1]%${rmresu[$i1${i2}6]}*}${rmresu[$i1${i2}6]}"
else
[[ -n ${rmallgeo[$i1]} ]]&&rmallgeo[$i1]="${rmallgeo[$i1]} -> "
rmallgeo[$i1]="${rmallgeo[$i1]}${rmresu[$i1${i2}6]}"
fi
fi
if [[ ${rmallgeo[$i1]} != *"${rmresu[$i1${i2}6]}" ]];then
[[ -n ${rmallgeo[$i1]} ]]&&rmallgeo[$i1]="${rmallgeo[$i1]} -> "
rmallgeo[$i1]="${rmallgeo[$i1]}${rmresu[$i1${i2}6]}"
fi
if [[ -n ${rmresu["$i1${i2}3"]} && ${rmallasn[$i1]} != *"${rmresu[$i1${i2}3]}" ]];then
[[ -n ${rmallasn["$i1"]} ]]&&rmallasn["$i1"]="${rmallasn["$i1"]} -> "
rmallasn["$i1"]="${rmallasn["$i1"]}${rmresu[$i1${i2}3]}"
fi
local vara=${i2#0}
local varb="${rmmaxhop["$i1"]:-0}"
varb=${varb#0}
if ((vara>varb));then
rmmaxhop["$i1"]="$i2"
fi
done <<<"$tmpresult"
rmcn=()
rmww=()
for i in $(seq 0 $rmtestnum);do
ii=$(printf "%02d" "$i")
rmcn[$ii]="Unknown"
rmww[$ii]="Unknown"
[[ ${rmcnhop[$ii]} == 0 || ${rmcnhop[$ii]} == ${rmmaxhop[$ii]} ]]&&rmcn[$ii]="Hidden"
local vara="${rmcnhop[$ii]:-0}"
vara=${vara#0}
[[ ${rmresu[$ii${rmcnhop[$ii]}3]} == "AS17676" ]]&&rmcnhop[$ii]=$(printf "%02d" "$((vara+1))")
case "${rmresu[$ii${rmcnhop[$ii]}3]}" in
"AS4134")rmcn[$ii]="163"
;;
"AS4837")rmcn[$ii]="4837"
local vara="${rmcnhop[$ii]:-0}"
vara=${vara#0}
if ((vara>1));then
varb=$(printf "%02d" "$((vara-1))")
[[ ${rmresu[$ii${varb}3]} == "AS10099" ]]&&rmcn[$ii]="10099"
fi
;;
"AS58453")rmcn[$ii]="CMI"
;;
"AS58807")rmcn[$ii]="CMIN2"
;;
"AS9808")rmcn[$ii]="CMI"
[[ ${rmallasn[$ii]} == *AS58807* ]]&&rmcn[$ii]="CMIN2"
;;
"AS9929")rmcn[$ii]="9929"
;;
"AS10099")rmcn[$ii]="10099"
[[ ${rmallasn[$ii]} == *AS9929* ]]&&rmcn[$ii]="9929"
;;
"AS4809")rmcn[$ii]="CN2GIA"
local vara="${rmcnhop[$ii]:-0}"
local varb="${rmmaxhop[$ii]:-0}"
vara=${vara#0}
varb=${varb#0}
if ((vara>1));then
[[ ${rmallasn[$ii]} == *AS23764* ]]&&rmcn[$ii]="CTGGIA"
fi
if [[ $rmgia -ne 1 ]];then
for ((thop=vara; thop<=varb; thop++));do
hop=$(printf "%02d" "$thop")
[[ ${rmresu[$ii${hop}3]} == "AS4809" || ${rmresu[$ii${hop}3]} == "AS23764" ]]&&continue
if [[ ${rmresu[$ii${hop}2]} == 202.97* ]];then
rmcn[$ii]="CN2GT"
fi
break
done
fi
;;
"AS23764")rmcn[$ii]="CTGGIA"
if [[ $rmgia -ne 1 ]];then
local vara="${rmcnhop[$ii]:-0}"
local varb="${rmmaxhop[$ii]:-0}"
vara=${vara#0}
varb=${varb#0}
for ((thop=vara; thop<=varb; thop++));do
hop=$(printf "%02d" "$thop")
[[ ${rmresu[$ii${hop}3]} == "AS4809" || ${rmresu[$ii${hop}3]} == "AS23764" ]]&&continue
if [[ ${rmresu[$ii${hop}2]} == 202.97* ]];then
rmcn[$ii]="CN2GT"
fi
break
done
fi
;;
"AS4538")rmcn[$ii]="CERNET"
;;
"AS7497")rmcn[$ii]="CSTNET"
;;
*)rmcn[$ii]="NoData"
if [[ ${rmallasn[$ii]} == *AS58807* ]];then
rmcn[$ii]="CMIN2"
elif [[ ${rmallasn[$ii]} == *AS9929* ]];then
rmcn[$ii]="9929"
elif [[ ${rmallasn[$ii]} == *AS10099* ]];then
rmcn[$ii]="10099"
elif [[ ${rmallasn[$ii]} == *AS4809* ]];then
rmcn[$ii]="CN2"
elif [[ ${rmallasn[$ii]} == *AS9808* ]];then
rmcn[$ii]="CMI"
elif [[ ${rmallasn[$ii]} == *AS4134* ]];then
rmcn[$ii]="163"
elif [[ ${rmallasn[$ii]} == *AS4837* ]];then
rmcn[$ii]="4837"
fi
esac
[[ ${rmcn[$ii]} == *GIA ]]&&rmgia=1
local vara="${rmcnhop[$ii]:-0}"
vara=${vara#0}
for ((thop=vara-1; thop>0; thop--));do
hop=$(printf "%02d" "$thop")
if [[ -n ${rmresu[$ii${hop}3]} && ${rmresu[$ii${hop}3]} != "AS58453" && ${rmresu[$ii${hop}3]} != "AS58807" && ${rmresu[$ii${hop}3]} != "AS4837" && ${rmresu[$ii${hop}3]} != "AS10099" && ${rmresu[$ii${hop}3]} != "AS9929" && ${rmresu[$ii${hop}3]} != "AS4134" && ${rmresu[$ii${hop}3]} != "AS4809" && ${rmresu[$ii${hop}3]} != "AS4808" && ${rmresu[$ii${hop}3]} != "AS23764" && ${rmresu[$ii${hop}3]} != "AS4538" && ${rmresu[$ii${hop}3]} != "AS7497" ]];then
rmww[$ii]="${rmresu[$ii${hop}3]}"
break
fi
done
if [[ -n ${rmww[$ii]} ]];then
[[ -n ${AS_MAPPING[${rmww[$ii]}]} ]]&&rmww[$ii]="${AS_MAPPING[${rmww[$ii]}]}"
fi
done
}
parse_iperf3_result(){
local server=$1
local portl=$2
local portu=$3
local ipv="-4"
[[ $4 -eq 6 ]]&&ipv="-6"
local sendrecv=""
[[ $5 -eq 1 ]]&&sendrecv=" -R"
local maxtry=5
local port=0
iperfresu[s]=-1
iperfresu[r]=-1
local infolen
if [[ $YY == "cn" ]];then
infolen=$((${#6}*2))
else
infolen=${#6}
fi
local temp_info="$Font_Cyan$Font_B${sinfo[iperf]}$6$Font_Suffix"
((ibar_step+=2))
show_progress_bar "$temp_info" $((50-${sinfo[liperf]}-infolen))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
for ((i=1; i<=maxtry; i++));do
port=$((RANDOM%(portu-portl+1)+portl))
local response=$(timeout 20 iperf3 $ipv$sendrecv -J -t 6 -c "$server" -p "$port" 2>&1)
if [[ -n $response && $response != *"iperf3: error"* && $response != *"\"error\":"* ]];then
local bits_per_second=$(echo "$response"|jq -r '.end.sum_received.bits_per_second')
local retransmits=$(echo "$response"|jq -r '.end.sum_sent.retransmits')
if [[ -n $bits_per_second && $bits_per_second != "null" && -n $retransmits && $retransmits != "null" ]];then
iperfresu[s]=$bits_per_second
iperfresu[r]=$retransmits
return 0
fi
fi
done
return 1
}
convert_b2m(){
local bps=$1
local mbps
local color
if (($(echo "$bps < 0"|bc -l)));then
echo -e "$Font_Red E$Font_Suffix"
return
else
mbps=$(echo "$bps / 1000000"|bc)
fi
if [ "$mbps" -gt 99999 ];then
echo -e "$Font_Green ${Font_U}100G+$Font_Suffix"
return
fi
if [ "$mbps" -lt 50 ];then
color=$Font_Red
elif [ "$mbps" -ge 50 ]&&[ "$mbps" -lt 200 ];then
color=$Font_Yellow
elif [ "$mbps" -ge 200 ];then
color=$Font_Green
else
color=$Font_Red
fi
local tmp_space=$((6-${#mbps}))
echo "$color$(printf "%${tmp_space}s\n")$Font_U$mbps$Font_Suffix"
}
convert_retr(){
local num=$1
local color
local result
if [ "$num" -lt 0 ];then
echo -e "${Font_Red}RROR$Font_Suffix"
return
fi
if [[ $num -eq 0 ]];then
color=$Font_Green
elif [[ $num -ge 1 && $num -le 99 ]];then
color=$Font_Yellow
elif [[ $num -gt 99 ]];then
color=$Font_Red
else
color=$Font_Red
fi
if [[ $num -lt 1000 ]];then
result=$num
elif [[ $num -ge 1000 && $num -lt 10000 ]];then
result="${num:0:1}k"
elif [[ $num -ge 10000 && $num -lt 100000 ]];then
result="${num:0:2}k"
elif [[ $num -ge 100000 && $num -lt 1000000 ]];then
result=".${num:0:1}m"
else
result="1m+"
fi
echo "$color$(printf '%4s' "$result")$Font_Suffix"
}
process_wwpingtestresult(){
local testresult=$1
local -A midresu
local -A midresu2
local tmp_space
local ipv
local index
local numbers
local total
local count
local lost
local result
IFS=$'\n' read -r -d '' -a lines <<<"$testresult"
for line in "${lines[@]}";do
line=$(echo "$line"|xargs)
[[ -z $line ]]&&continue
IFS=' ' read -ra parts <<<"$line"
index="${parts[1]}${parts[2]}${parts[3]}"
ipv="${parts[2]}"
ipout[$index]="${parts[4]}"
done
local keys=($(echo "${!icity[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
total=0
count=0
lost=""
for i in $(seq 1 $pingww_test_count);do
numbers=${ipout[$key$ipv$i]}
if [[ $numbers =~ ^0\.0*$ ]];then
lost="$Font_Red"
else
total=$(echo "$total + $numbers"|bc)
((count++))
fi
done
if ((count>0));then
local avg=$(echo "scale=0; $total / $count"|bc)
else
local avg=0
fi
result=""
for ((i=1; i=max_threads));then
wait -n
((current_threads--))
fi
done
done
wait)
process_wwpingtestresult "$tmpresult"
}
show_iperf(){
echo -ne "\r${siperf[title]}\n"
local count=0
local keys=($(echo "${!icity[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
((count++))
if ((count%2==0));then
echo -ne "${iresu[$key]}\n"
else
echo -ne "\r${iresu[$key]}||"
fi
done
((count%2!=0))&&echo
}
parse_speedtest_result(){
local tid="$1"
local tcode="$2"
local infolen
if [[ $YY == "cn" ]];then
infolen=$((${#scity[$tcode]}*2+${#spv[$tcode]}*2))
infotxt="${scity[$tcode]}${spv[$tcode]}"
else
infolen=$((${#scity[$tcode]}+${#spv[$tcode]}+1))
infotxt="${scity[$tcode]} ${spv[$tcode]}"
fi
local temp_info="$Font_Cyan$Font_B${sinfo[speedtest]}$infotxt$Font_Suffix"
((ibar_step+=2))
show_progress_bar "$temp_info" $((50-${sinfo[lspeedtest]}-infolen))&
bar_pid="$!"&&disown "$bar_pid"
trap "kill_progress_bar" RETURN
local maxtry=1
sout["${tcode}1"]=-1
sout["${tcode}2"]=-1
sout["${tcode}3"]=-1
sout["${tcode}4"]=-1
local i
for ((i=1; i<=maxtry; i++));do
local response=$(speedtest --accept-gdpr --accept-license -f json -s "$tid" 2>&1)
response=$(echo "$response"|sed -n '/^{/,/^}/p')
if [[ -n $response && $response != *"[error]"* && $response != *"\"error\""* ]];then
local download_bandwidth=$(echo "$response"|jq '.download.bandwidth')
sout["${tcode}3"]=$((download_bandwidth*8))
local upload_bandwidth=$(echo "$response"|jq '.upload.bandwidth')
sout["${tcode}1"]=$((upload_bandwidth*8))
local download_latency_iqm=$(echo "$response"|jq '.download.latency.iqm')
sout["${tcode}4"]=${download_latency_iqm%.*}
local upload_latency_iqm=$(echo "$response"|jq '.upload.latency.iqm')
sout["${tcode}2"]=${upload_latency_iqm%.*}
return 0
fi
done
return 1
}
convert_delay(){
local num=$1
local color
local result
if [[ ! $num =~ ^-?[0-9]+$ ]];then
echo -e "$Font_Red -$Font_Suffix"
return
fi
if [ "$num" -lt 0 ];then
echo -e "${Font_Red}RROR $Font_Suffix"
return
fi
if [[ $num -eq 0 ]];then
color=$Font_Red
elif [[ $num -ge 1 && $num -le 150 ]];then
color=$Font_Green
elif [[ $num -ge 151 && $num -le 240 ]];then
color=$Font_Yellow
else
color=$Font_Red
fi
if [[ $num -lt 1000 ]];then
result=$num
elif [[ $num -ge 1000 && $num -lt 10000 ]];then
result="${num:0:1}k"
elif [[ $num -ge 10000 && $num -lt 100000 ]];then
result="${num:0:2}k"
elif [[ $num -ge 100000 && $num -lt 1000000 ]];then
result=".${num:0:1}m"
else
result="1m+"
fi
echo "$color$(printf '%6s' "$result")$Font_Suffix"
}
speedtest_test(){
ibar_step=36
local json_data=$(curl -sL "${rawgithub}main/ref/speedtest_cn.json")
declare -A codemax
codemax[1]=0
codemax[2]=0
codemax[3]=0
codemax[4]=0
while IFS=" " read -r code id city cityzh provider providerzh;do
if [[ $YY == "cn" ]];then
scity["$code"]="$cityzh"
spv["$code"]="$providerzh"
else
scity["$code"]="$city"
spv["$code"]="$provider"
fi
sid["$code"]="$id"
ten_digit="${code:0:1}"
one_digit="${code:1}"
if [[ $one_digit -gt ${codemax[$ten_digit]} ]];then
codemax["$ten_digit"]="$one_digit"
fi
done < <(echo "$json_data"|jq -r '.[] | "\(.code) \(.id) \(.city) \(.cityzh) \(.provider) \(.providerzh)"')
local skip
local key
local pvi
local pvj
for ((pvi=1; pvi<=3; pvi++));do
skip=0
for ((pvj=1; pvj<=2; pvj++));do
for ((try=1; codemax[$pvi]-3+pvj-skip>0; try++));do
key=$((pvj+skip))
parse_speedtest_result "${sid[$pvi$key]}" "$pvi$key"
if [[ sout[$pvi${key}1] -eq -1 && sout[$pvi${key}2] -eq -1 && sout[$pvi${key}3] -eq -1 && sout[$pvi${key}4] -eq -1 ]];then
((skip++))
((ibar_step-=2))
else
break
fi
done
if [[ $YY == "cn" ]];then
tmp_space=$((13-${#scity[$pvi$key]}*2-${#spv[$pvi$key]}*2))
sresu[$pvi$pvj]="$Font_Cyan${scity[$pvi$key]}${spv[$pvi$key]}$(printf "%${tmp_space}s\n")"
else
tmp_space=$((10-${#scity[$pvi$key]}))
sresu[$pvi$pvj]="$Font_Cyan${scity[$pvi$key]}$(printf "%${tmp_space}s\n")${spv[$pvi$key]} $Font_Suffix"
fi
sresu[$pvi$pvj]+="$(convert_b2m ${sout[$pvi${key}1]})$(convert_delay ${sout[$pvi${key}2]}) $(convert_b2m ${sout[$pvi${key}3]})$(convert_delay ${sout[$pvi${key}4]})"
done
done
}
show_speedtest(){
echo -ne "\r${sspeedtest[title]}\n"
local count=0
local keys=($(echo "${!sresu[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
((count++))
if ((count%2==0));then
echo -ne "${sresu[$key]}\n"
else
echo -ne "\r${sresu[$key]}||"
fi
done
((count%2!=0))&&echo
}
show_head(){
echo -ne "\r$(printf '%80s'|tr ' ' '*')\n"
if [ $fullIP -eq 1 ];then
calc_padding "$(printf '%*s' "${shead[ltitle]}" '')$IP" 80
echo -ne "\r$PADDING$Font_B${shead[title]}$Font_Cyan$IP$Font_Suffix\n"
else
calc_padding "$(printf '%*s' "${shead[ltitle]}" '')$IPhide" 80
echo -ne "\r$PADDING$Font_B${shead[title]}$Font_Cyan$IPhide$Font_Suffix\n"
fi
calc_padding "${shead[git]}" 80
echo -ne "\r$PADDING$Font_U${shead[git]}$Font_Suffix\n"
calc_padding "${shead[bash]}" 80
echo -ne "\r$PADDING${shead[bash]}\n"
echo -ne "\r${shead[ptime]}${shead[time]} ${shead[ver]}\n"
echo -ne "\r$(printf '%80s'|tr ' ' '*')\n"
}
show_bgp(){
echo -ne "\r${sbgp[title]}\n"
if [[ -n ${bgp[asn]} && ${bgp[asn]} != "null" || -n ${bgp[org]} && ${bgp[org]} != "null" || -n ${bgp[prefixnum]} && ${bgp[prefixnum]} != "null" || -n ${bgp[rir]} && ${bgp[rir]} != "null" ]];then
local tmpstr=""
local tmpinfo=""
[[ -n ${bgp[rir]} && ${bgp[rir]} != "null" ]]&&tmpinfo="${bgp[rir]}"&&tmpstr=", "
[[ -n ${bgp[asn]} && ${bgp[asn]} != "null" ]]&&tmpinfo="$tmpinfo$tmpstr${bgp[asn]}"&&tmpstr=" "
[[ -n ${bgp[org]} && ${bgp[org]} != "null" ]]&&tmpinfo="$tmpinfo$tmpstr${bgp[org]}"&&tmpstr=", "
[[ $tmpstr == " " ]]&&tmpstr=", "
[[ -n ${bgp[prefixnum]} && ${bgp[prefixnum]} != "null" ]]&&tmpinfo="$tmpinfo${tmpstr}Prefix/${bgp[prefixnum]}"
echo -ne "\r$Font_Cyan${sbgp[ipinfo]}$Font_Green$(wrap_text 20 "$tmpinfo")$Font_Suffix\n"
fi
if [[ -n ${bgp[regdate]} && -n ${bgp[moddate]} ]];then
echo -ne "\r$Font_Cyan${sbgp[date]}$Font_Green${bgp[regdate]} / ${bgp[moddate]}$Font_Suffix\n"
elif [[ -n ${bgp[regdate]} && -z ${bgp[moddate]} ]];then
echo -ne "\r$Font_Cyan${sbgp[date]}$Font_Green${bgp[regdate]} / NoRecord$Font_Suffix\n"
elif [[ -z ${bgp[regdate]} && -n ${bgp[moddate]} ]];then
echo -ne "\r$Font_Cyan${sbgp[date]}${Font_Green}NoRecord / ${bgp[moddate]}$Font_Suffix\n"
fi
if [[ -n ${bgp[countrycode]} && ${bgp[countrycode]} != "null" ]];then
local fullcountry="[${bgp[countrycode]}]"
[[ -n ${bgp[country]} ]]&&fullcountry="$fullcountry${bgp[country]}"
if [[ -n ${bgp[intermediateregion]} ]];then
fullcountry="$fullcountry, ${bgp[intermediateregion]}"
elif [[ -n ${bgp[subregion]} ]];then
fullcountry="$fullcountry, ${bgp[subregion]}"
fi
[[ -n ${bgp[region]} ]]&&fullcountry="$fullcountry, ${bgp[region]}"
fi
[[ -n $fullcountry && $fullcountry != "null" ]]&&echo -ne "\r$Font_Cyan${sbgp[country]}$Font_Green$(wrap_text 20 "$fullcountry")$Font_Suffix\n"
[[ -n ${bgp[address]} && ${bgp[address]} != "null" ]]&&echo -ne "\r$Font_Cyan${sbgp[address]}$Font_Green$(wrap_text 20 "${bgp[address]}")$Font_Suffix\n"
[[ -n ${bgp[geofeed]} && ${bgp[geofeed]} != "null" ]]&&echo -ne "\r$Font_Cyan${sbgp[geofeed]}$Font_Green${bgp[geofeed]}$Font_Suffix\n"
local neighborresu=""
if [[ ${bgp[neighbortotal]} -gt 0 && -n ${bgp[neighboractive]} ]];then
neighbor_ratio=$(echo "scale=2; ${bgp[neighboractive]}/${bgp[neighbortotal]}"|bc)
if (($(echo "$neighbor_ratio < 0.5"|bc -l)));then
neighbor_bg=$Back_Green
elif (($(echo "$neighbor_ratio >= 0.5"|bc -l)))&&(($(echo "$neighbor_ratio < 0.8"|bc -l)));then
neighbor_bg=$Back_Yellow
elif (($(echo "$neighbor_ratio >= 0.8"|bc -l)));then
neighbor_bg=$Back_Red
else
neighbor_bg=$Back_Green
fi
neighborresu="${Font_Green}Subnet/24 $neighbor_bg$Font_B$Font_White ${bgp[neighboractive]} / ${bgp[neighbortotal]} $Font_Suffix "
fi
if [[ ${bgp[iptotal]} -gt 0 && -n ${bgp[ipactive]} ]];then
ip_ratio=$(echo "scale=2; ${bgp[ipactive]}/${bgp[iptotal]}"|bc)
if (($(echo "$ip_ratio < 0.5"|bc -l)));then
ip_bg=$Back_Green
elif (($(echo "$ip_ratio >= 0.5"|bc -l)))&&(($(echo "$ip_ratio < 0.8"|bc -l)));then
ip_bg=$Back_Yellow
elif (($(echo "$ip_ratio >= 0.8"|bc -l)));then
ip_bg=$Back_Red
else
ip_bg=$Back_Green
fi
neighborresu+="${Font_Green}Prefix/${bgp[prefixnum]} $ip_bg$Font_B$Font_White ${bgp[ipactive]} / ${bgp[iptotal]} $Font_Suffix"
fi
[[ -n $neighborresu ]]&&echo -ne "\r$Font_Cyan${sbgp[neighbor]}$neighborresu$Font_Suffix\n"
}
show_local(){
echo -ne "\r${slocal[title]}\n"
[[ -n ${getnat[type]} ]]&&echo -ne "\r$Font_Cyan${slocal[nat]}${slocal[${getnat[type]}]}$Font_Suffix\n"
if [[ ${getnat[char]} -eq 1 ]];then
echo -ne "\r$Font_Cyan${slocal[mapping]}${slocal[m${getnat[m]}]}$Font_Suffix$Font_Cyan${slocal[filter]}${slocal[f${getnat[f]}]}$Font_Suffix$Font_Cyan${slocal[port]}${slocal[p${getnat[p]}]}$Font_Suffix$Font_Cyan${slocal[hairpin]}${slocal[h${getnat[h]}]}$Font_Suffix\n"
fi
echo -ne "\r$Font_Cyan${slocal[tcpcc]}$Font_Green$(printf '%-13s' "${gettcp[tcpcc]}")$Font_Cyan${slocal[rmem]}$Font_Green${gettcp[rmem]}$Font_Suffix\n"
echo -ne "\r$Font_Cyan${slocal[qdisc]}$Font_Green$(printf '%-13s' "${gettcp[qdisc]}")$Font_Cyan${slocal[wmem]}$Font_Green${gettcp[wmem]}$Font_Suffix\n"
}
show_conn(){
echo -ne "\r${sconn[title]}\n"
if [[ ${conn[ix]} -eq 99 ]];then
echo -ne "\r$Font_Cyan${sconn[ix]}$Font_Green$(printf '%-10s' "${conn[ix]}+")"
elif [[ ${conn[ix]} -eq -1 ]];then
echo -ne "\r$Font_Cyan${sconn[ix]}$Font_Green$(printf '%-10s' "-")"
else
echo -ne "\r$Font_Cyan${sconn[ix]}$Font_Green$(printf '%-10s' "${conn[ix]}")"
fi
if [[ ${conn[upstreams]} -eq -2 ]];then
echo -ne "$Font_Cyan${sconn[upstreams]}${Font_Green}Transit-Free \n"
elif [[ ${conn[upstreams]} -eq -1 ]];then
echo -ne "$Font_Cyan${sconn[upstreams]}$Font_Green$(printf '%-10s' "-")"
else
echo -ne "$Font_Cyan${sconn[upstreams]}$Font_Green$(printf '%-10s' "${conn[upstreams]}")"
fi
if [[ ${conn[peers]} -eq -1 ]];then
echo -ne "$Font_Cyan${sconn[peers]}$Font_Green-$Font_Suffix\n"
else
echo -ne "$Font_Cyan${sconn[peers]}$Font_Green${conn[peers]}$Font_Suffix\n"
fi
local clenth=0
conn[asn]=""
conn[org]=""
for id in $(echo "${!casn[@]}"|tr ' ' '\n'|sort -n);do
local raw_as_number="AS${casn[$id]}"
local raw_as_name="${corg[$id]}"
if [[ ${casn[$id]} -eq 0 || ${ctarget[$id]} == "true" ]];then
continue
fi
local len_as_number=${#raw_as_number}
local len_as_name=${#raw_as_name}
local max_len=$((len_as_number>len_as_name?len_as_number:len_as_name))
if ((len_as_number81));then
clenth=$((max_len+1))
echo -ne "\r${conn[asn]}\n\r${conn[org]}\n"
conn[asn]="$as_number "
conn[org]="$as_name "
else
conn[asn]="${conn[asn]}$as_number "
conn[org]="${conn[org]}$as_name "
fi
done
[[ -n ${conn[asn]} ]]&&echo -ne "\r${conn[asn]}\n"
[[ -n ${conn[org]} ]]&&echo -ne "\r${conn[org]}\n"
}
show_tail(){
echo -ne "\r$(printf '%80s'|tr ' ' '=')\n"
echo -ne "\r$Font_I${stail[stoday]}${stail[today]}${stail[stotal]}${stail[total]}${stail[thanks]} $Font_Suffix\n"
echo -e ""
}
get_opts(){
local args=()
while [[ $# -gt 0 ]];do
case "$1" in
-[loSR])args+=("$1")
if [[ $# -gt 1 && $2 != -* ]];then
args+=("$2")
shift
fi
shift
;;
-[loSR]*)ERRORcode=1
shift
;;
-[46fhjnpyELMP]*)local opt="$1"
shift
for ((i=1; i<${#opt}; i++));do
args+=("-${opt:i:1}")
done
;;
--*|-*[!-]*)args+=("$1")
shift
;;
-*)ERRORcode=1
shift
;;
*)shift
esac
done
set -- "${args[@]}"
while [[ $# -gt 0 ]];do
case "$1" in
-4)if
[[ IPV4check -ne 0 ]]
then
IPV6check=0
else
ERRORcode=4
fi
shift
;;
-6)if
[[ IPV6check -ne 0 ]]
then
IPV4check=0
else
ERRORcode=6
fi
shift
;;
-f)fullIP=1
shift
;;
-h)show_help
shift
;;
-j)mode_json=1
shift
;;
-l)shift
[[ $1 == -* ]]&&ERRORcode=1&&break
YY=$(echo "$1"|tr '[:upper:]' '[:lower:]')
shift
;;
-n)mode_no=1
shift
;;
-o)shift
[[ $1 == -* ]]&&{
ERRORcode=1
break
}
mode_output=1
outputfile="$1"
[[ -z $outputfile ]]&&{
ERRORcode=1
break
}
[[ -e $outputfile ]]&&{
ERRORcode=10
break
}
touch "$outputfile" 2>/dev/null||{
ERRORcode=11
break
}
shift
;;
-p)mode_privacy=1
shift
;;
-y)mode_yes=1
shift
;;
-E)YY="en"
shift
;;
-L)mode_low=1
shift
;;
-M)mode_menu=1
shift
;;
-P)mode_ping=1
shift
;;
-R)mode_route=1
shift
if [[ $# -gt 0 && $1 != -* ]];then
mode_route_pv=$(echo "$1"|tr '[:upper:]' '[:lower:]'|sed 's/省//g; s/市//g; s/县//g; s/维吾尔//g; s/回族//g; s/壮族//g; s/自治区//g; s/特别行政区//g')
shift
fi
;;
-S)shift
if [[ $# -gt 0 ]];then
mode_skip="$1"
shift
else
ERRORcode=1
fi
;;
-*)ERRORcode=1
shift
;;
*)shift
esac
done
if [[ $mode_menu -eq 1 ]];then
if [[ $YY == "cn" ]];then
eval "bash <(curl -sL https://Check.Place) -N"
else
eval "bash <(curl -sL https://Check.Place) -EN"
fi
exit 0
fi
[[ $mode_ping -eq 1 ]]&&mode_skip+="567"
[[ $mode_low -eq 1 ]]&&mode_skip+="6"
[[ $mode_route -eq 1 ]]&&mode_skip+="467"
[[ $mode_ping -eq 1 && $mode_skip == *"4"* ]]&&ERRORcode=9
[[ $mode_route -eq 1 && $mode_skip == *"5"* ]]&&ERRORcode=9
[[ $mode_skip == *"1"* && $mode_skip == *"2"* && $mode_skip == *"3"* && $mode_skip == *"4"* && $mode_skip == *"5"* && $mode_skip == *"6"* && $mode_skip == *"7"* ]]&&ERRORcode=9
[[ $IPV4check -eq 1 && $IPV6check -eq 0 && $IPV4work -eq 0 ]]&&ERRORcode=40
[[ $IPV4check -eq 0 && $IPV6check -eq 1 && $IPV6work -eq 0 ]]&&ERRORcode=60
CurlARG="$useNIC$usePROXY"
}
show_help(){
echo -ne "\r$shelp\n"
exit 0
}
show_ad(){
RANDOM=$(date +%s)
local -a ads=()
local i=1
while :;do
local content
content=$(curl -fsL --max-time 5 "${rawgithub}main/ref/ad$i.ans")||break
ads+=("$content")
((i++))
done
local adCount=${#ads[@]}
local -a indices=()
for ((i=1; i<=adCount; i++));do indices+=("$i");done
for ((i=adCount-1; i>0; i--));do
local j=$((RANDOM%(i+1)))
local tmp=${indices[i]}
indices[i]=${indices[j]}
indices[j]=$tmp
done
local -a aad
aad[0]=$(curl -sL --max-time 5 "${rawgithub}main/ref/sponsor.ans")
for ((i=0; i/dev/null);then cols=0;fi
ADLines=0
print_pair(){
local left="$1" right="$2"
local -a L R
mapfile -t L <<<"$left"
mapfile -t R <<<"$right"
local i
for ((i=0; i<12; i++));do
printf "%-72s$Font_Suffix %-72s\n" "${L[i]}" "${R[i]}" 1>&2
done
ADLines=$((ADLines+12))
}
print_block(){
echo "$1" 1>&2
ADLines=$((ADLines+12))
}
if [[ $cols -ge 150 ]];then
if ((adCount==0));then
print_block "${aad[0]}"
elif ((adCount%2==1));then
print_pair "${aad[0]}" "${aad[1]}"
local k
for ((k=2; k<=adCount; k+=2));do
print_pair "${aad[$k]}" "${aad[$((k+1))]}"
done
else
print_block "${aad[0]}"
local k
for ((k=1; k<=adCount; k+=2));do
print_pair "${aad[$k]}" "${aad[$((k+1))]}"
done
fi
else
echo "${aad[0]}" 1>&2
for ((i=1; i<=adCount; i++));do
echo "${aad[$i]}" 1>&2
done
ADLines=$(((adCount+1)*12))
fi
}
read_ref(){
ISO3166=$(curl -sL -m 10 "${rawgithub}main/ref/iso3166.json")
RESPONSE=$(curl -sL -m 10 "${rawgithub}main/ref/province.json")
while IFS=" " read -r province code short name;do
pcode[$province]=$code
pshort[$province]=$short
pname[$province]=$(echo "$name"|sed -E 's/(省|市|自治区|维吾尔|壮族|回族)//g')
pcode_lower=$(echo "$code"|tr '[:upper:]' '[:lower:]')
pdm[${province}14]="$pcode_lower-ct-v4.ip.zstaticcdn.com"
pdm[${province}24]="$pcode_lower-cu-v4.ip.zstaticcdn.com"
pdm[${province}34]="$pcode_lower-cm-v4.ip.zstaticcdn.com"
pdm[${province}16]="$pcode_lower-ct-v6.ip.zstaticcdn.com"
pdm[${province}26]="$pcode_lower-cu-v6.ip.zstaticcdn.com"
pdm[${province}36]="$pcode_lower-cm-v6.ip.zstaticcdn.com"
done < <(echo "$RESPONSE"|jq -r '.[] | select(.province < 70) | "\(.province) \(.code) \(.short) \(.name)"')
if [[ -n $mode_route_pv ]];then
lower_optarg="$mode_route_pv"
mode_route_pv=""
for province in "${!pcode[@]}";do
lower_pcode=$(echo "${pcode[$province]}"|tr '[:upper:]' '[:lower:]')
if [[ $lower_optarg == "$lower_pcode" || $lower_optarg == "${pshort[$province]}" || $lower_optarg == "${pname[$province]}" ]];then
mode_route_pv="$province"
break
fi
done
[[ -z $mode_route_pv ]]&&ERRORcode=21
fi
while read -r as name;do
AS_MAPPING["$as"]="$name"
done < <(curl -sL "${rawgithub}main/ref/AS_Mapping.txt")
}
save_json(){
local head_updates=""
local bgp_updates=""
local local_updates=""
local connectivity_updates=""
if [ $fullIP -eq 1 ];then
head_updates+=".Head |= map(. + { IP: \"${IP:-null}\" }) | "
else
head_updates+=".Head |= map(. + { IP: \"${IPhide:-null}\" }) | "
fi
head_updates+=".Head |= map(. + { Command: \"${shead[bash]:-null}\" }) | "
head_updates+=".Head |= map(. + { GitHub: \"${shead[git]:-null}\" }) | "
head_updates+=".Head |= map(. + { Time: \"${shead[time]:-null}\" }) | "
head_updates+=".Head |= map(. + { Version: \"${shead[ver]:-null}\" }) | "
local first_asn=$(echo "${bgp[asn]}"|awk -F',' '{print $1}'|sed 's/^AS//')
first_asn=${first_asn:-null}
bgp_updates+=".BGP |= map(. + { ASN: \"$first_asn\" }) | "
bgp_updates+=".BGP |= map(. + { Organization: \"${bgp[org]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { Prefix: ${bgp[prefixnum]:-null} }) | "
bgp_updates+=".BGP |= map(. + { RIR: \"${bgp[rir]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { RegDate: \"${bgp[regdate]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { ModDate: \"${bgp[moddate]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { Country: \"${bgp[country]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { IntermediateRegion: \"${bgp[intermediateregion]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { SubRegion: \"${bgp[subregion]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { Region: \"${bgp[region]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { Address: \"${bgp[address]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { GeoFeed: \"${bgp[geofeed]:-null}\" }) | "
if [[ -n ${bgp[iptotal]} && -n ${bgp[ipactive]} ]];then
bgp_updates+=".BGP |= map(. + { IPinTotal: ${bgp[iptotal]:-null} }) | "
bgp_updates+=".BGP |= map(. + { IPActive: ${bgp[ipactive]:-null} }) | "
bgp_updates+=".BGP |= map(. + { NeighborinTotal: ${bgp[neighbortotal]:-null} }) | "
bgp_updates+=".BGP |= map(. + { NeighborActive: ${bgp[neighboractive]:-null} }) | "
elif [[ -n ${bgp[neighbortotal]} && -n ${bgp[neighboractive]} ]];then
bgp_updates+=".BGP |= map(. + { IPinTotal: ${bgp[neighbortotal]:-null} }) | "
bgp_updates+=".BGP |= map(. + { IPActive: ${bgp[neighboractive]:-null} }) | "
bgp_updates+=".BGP |= map(. + { NeighborinTotal: ${bgp[neighbortotal]:-null} }) | "
bgp_updates+=".BGP |= map(. + { NeighborActive: ${bgp[neighboractive]:-null} }) | "
else
bgp_updates+=".BGP |= map(. + { IPinTotal: null }) | "
bgp_updates+=".BGP |= map(. + { IPActive: null }) | "
bgp_updates+=".BGP |= map(. + { NeighborinTotal: null }) | "
bgp_updates+=".BGP |= map(. + { NeighborActive: null }) | "
fi
local_updates+=".Local |= map(. + { NAT: \"${getnat[nat]:-null}\" }) | "
local_updates+=".Local |= map(. + { NATDescribe: \"$(echo -e "${slocal[${getnat[type]}]:-null}"|sed -E 's/\x1B\[[0-9;]*[a-zA-Z]//g'|xargs)\" }) | "
local_updates+=".Local |= map(. + { Mapping: \"$(echo -e "${slocal[m${getnat[m]}]:-null}"|sed -E 's/\x1B\[[0-9;]*[a-zA-Z]//g'|xargs)\" }) | "
local_updates+=".Local |= map(. + { Filter: \"$(echo -e "${slocal[f${getnat[f]}]:-null}"|sed -E 's/\x1B\[[0-9;]*[a-zA-Z]//g'|xargs)\" }) | "
local_updates+=".Local |= map(. + { Port: \"$(echo -e "${slocal[p${getnat[p]}]:-null}"|sed -E 's/\x1B\[[0-9;]*[a-zA-Z]//g'|xargs)\" }) | "
local_updates+=".Local |= map(. + { Hairpin: \"$(echo -e "${slocal[h${getnat[h]}]:-null}"|sed -E 's/\x1B\[[0-9;]*[a-zA-Z]//g'|xargs)\" }) | "
local_updates+=".Local |= map(. + { TCPCongestionControl: \"${gettcp[tcpcc]:-null}\" }) | "
local_updates+=".Local |= map(. + { QueueDiscipline: \"${gettcp[qdisc]:-null}\" }) | "
local_updates+=".Local |= map(. + { TCPReceiveBuffer: \"${gettcp[rmem]:-null}\" }) | "
local_updates+=".Local |= map(. + { TCPSendBuffer: \"${gettcp[wmem]:-null}\" }) | "
bgp_updates+=".BGP |= map(. + { IXCount: ${conn[ix]:-null} }) | "
bgp_updates+=".BGP |= map(. + { UpstreamsCount: ${conn[upstreams]:-null} }) | "
bgp_updates+=".BGP |= map(. + { PeersCount: ${conn[peers]:-null} }) | "
for id in $(echo "${!casn[@]}"|tr ' ' '\n'|sort -n);do
if [[ -z ${casn[$id]} ]];then
continue
fi
connectivity_updates+=".Connectivity += [{\"ID\": $id, \"ASN\": ${casn[$id]:-null}, \"Org\": \"${corg[$id]:-null}\", \"IsTarget\": $([[ ${ctarget[$id]} == "true" ]]&&echo true||echo false), \"IsTier1\": $([[ ${ctier1[$id]} == "true" ]]&&echo true||echo false), \"IsUpstream\": $([[ ${cupstream[$id]} == "true" ]]&&echo true||echo false)}] | "
done
netdata=$(echo "$netdata"|jq "$head_updates$bgp_updates$local_updates$connectivity_updates.")
local delay_objects=()
local keys=($(echo "${!pcode[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
delay_object="{
\"Code\": \"${pcode[$key]:-null}\",
\"Name\": \"${pshort[$key]:-null}\",
\"CT\": {
\"Average\": \"${pavg[${key}1$1]:-null}\""
for ((resu=1; resu<=ping_test_count; resu++));do
delay_object+=", \"$resu\": \"${pout[${key}1$1$resu]:-null}\""
done
delay_object+="},
\"CU\": {
\"Average\": \"${pavg[${key}2$1]:-null}\""
for ((resu=1; resu<=ping_test_count; resu++));do
delay_object+=", \"$resu\": \"${pout[${key}2$1$resu]:-null}\""
done
delay_object+="},
\"CM\": {
\"Average\": \"${pavg[${key}3$1]:-null}\""
for ((resu=1; resu<=ping_test_count; resu++));do
delay_object+=", \"$resu\": \"${pout[${key}3$1$resu]:-null}\""
done
delay_object+="}}"
delay_objects+=("$delay_object")
done
delay_array=$(printf '%s\n' "${delay_objects[@]}"|jq -s .)
netdata=$(echo "$netdata"|jq --argjson delay_array "$delay_array" '.Delay = $delay_array')
local transfer_object=()
local keys=($(echo "${!icity[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
transfer_object="{
\"City\": \"${icity[$key]:-null}\",
\"SendSpeed\": \"${isout[$key$11]:-null}\",
\"SendRetransmits\": \"${isout[$key$12]:-null}\",
\"ReceiveSpeed\": \"${isout[$key$13]:-null}\",
\"ReceiveRetransmits\": \"${isout[$key$14]:-null}\",
\"Delay\": {
\"Average\": \"${iavg[$key]:-null}\""
for ((resu=1; resu<=10; resu++));do
transfer_object+=", \"$resu\": \"${ipout[$key$1$resu]:-null}\""
done
transfer_object+="}}"
netdata=$(echo "$netdata"|jq --argjson transfer_object "$transfer_object" '.Transfer += [$transfer_object]')
done
local speedtest_object=()
local keys=($(echo "${!scity[@]}"|tr ' ' '\n'|sort -n))
for key in "${keys[@]}";do
if [[ ${sout[${key}1]} -gt 0 || ${sout[${key}2]} -gt 0 || ${sout[${key}3]} -gt 0 || ${sout[${key}4]} -gt 0 ]];then
speedtest_object="{
\"City\": \"${scity[$key]:-null}\",
\"Provider\": \"${spv[$key]:-null}\",
\"ID\": \"${sid[$key]:-null}\",
\"SendSpeed\": \"${sout[${key}1]:-null}\",
\"SendDelay\": \"${sout[${key}2]:-null}\",
\"ReceiveSpeed\": \"${sout[${key}3]:-null}\",
\"ReceiveDelay\": \"${sout[${key}4]:-null}\"
}"
netdata=$(echo "$netdata"|jq --argjson speedtest_object "$speedtest_object" '.Speedtest += [$speedtest_object]')
fi
done
}
check_Net(){
IP=$1
ibar_step=0
netdata='{
"Head": [{}],
"BGP": [{}],
"Local": [{}],
"Connectivity": [],
"Delay": [],
"Speedtest": [],
"Transfer": []
}'
[[ $2 -eq 4 ]]&&hide_ipv4 $IP
[[ $2 -eq 6 ]]&&hide_ipv6 $IP
countRunTimes
[[ $mode_skip != *"1"* || $mode_skip != *"3"* ]]&&db_bgptools $2
[[ $mode_skip != *"1"* ]]&&db_henet $2
[[ $mode_skip != *"1"* && $2 -eq 4 && -n ${bgp[prefixnum]} ]]&&get_neighbor
getnat=()
[[ $mode_skip != *"2"* && $2 -eq 4 ]]&&get_nat
[[ $mode_skip != *"2"* ]]&&get_tcp
[[ $mode_skip != *"4"* ]]&&get_delay $2
[[ $mode_skip != *"5"* && $mode_route -eq 0 ]]&&get_route $2
[[ $mode_skip != *"5"* && $mode_route -eq 1 ]]&&get_route_mode $2
[[ $mode_skip != *"6"* && $2 -eq 4 ]]&&speedtest_test
[[ $mode_skip != *"7"* ]]&&iperf_test $2
echo -ne "$Font_LineClear" 1>&2
if [ $2 -eq 4 ]||[[ $IPV4work -eq 0 || $IPV4check -eq 0 ]];then
for ((i=0; i&2
echo -ne "$Font_LineClear" 1>&2
done
fi
local net_report=$(show_head
[[ $mode_skip != *"1"* ]]&&show_bgp
[[ $mode_skip != *"2"* ]]&&show_local
[[ $mode_skip != *"3"* ]]&&show_conn
[[ $mode_skip != *"4"* ]]&&show_delay
[[ $mode_skip != *"5"* ]]&&show_route $2
[[ $mode_skip != *"6"* && $2 -eq 4 ]]&&show_speedtest
[[ $mode_skip != *"7"* ]]&&show_iperf
show_tail)
[[ mode_json -eq 1 || mode_output -eq 1 || mode_privacy -eq 0 ]]&&save_json $2
[[ mode_privacy -eq 0 ]]&&report_link=$(curl -$2 -s -X POST https://upload.check.place -d "type=net" --data-urlencode "json=$netdata" --data-urlencode "content=$net_report")
[[ mode_json -eq 0 ]]&&echo -ne "\r$net_report\n"
[[ mode_json -eq 0 && mode_privacy -eq 0 && $report_link == *"https://Report.Check.Place/"* ]]&&echo -ne "\r${stail[link]}$report_link$Font_Suffix\n"
[[ mode_json -eq 1 ]]&&echo -ne "\r$netdata\n"
echo -ne "\r\n"
if [[ mode_output -eq 1 ]];then
case "$outputfile" in
*.[aA][nN][sS][iI])echo "$net_report" >>"$outputfile" 2>/dev/null
;;
*.[jJ][sS][oO][nN])echo "$netdata" >>"$outputfile" 2>/dev/null
;;
*)echo -e "$net_report"|sed 's/\x1b\[[0-9;]*[mGKHF]//g' >>"$outputfile" 2>/dev/null
esac
fi
}
generate_random_user_agent
export LC_CTYPE=en_US.UTF-8 2>/dev/null
check_connectivity
get_ipv4
get_ipv6
is_valid_ipv4 $IPV4
is_valid_ipv6 $IPV6
get_opts "$@"
[[ mode_no -eq 0 ]]&&install_dependencies
set_language
read_ref
if [[ $ERRORcode -ne 0 ]];then
echo -ne "\r$Font_B$Font_Red${swarn[$ERRORcode]}$Font_Suffix\n"
exit $ERRORcode
fi
clear
show_ad
[[ $IPV4work -ne 0 && $IPV4check -ne 0 ]]&&check_Net "$IPV4" 4
[[ $IPV6work -ne 0 && $IPV6check -ne 0 ]]&&check_Net "$IPV6" 6