/,/<\/div>/p'|sed -n '/
/,/<\/pre>/p'|sed 's///'|sed 's/<[^>]*>//g')
+while IFS= read -r line;do
+[[ -z $line ]]&&continue
+if [[ $line == *:* ]];then
+field_name=$(awk -F: '{gsub(/^ +| +$/, "", $1); print tolower($1)}' <<<"$line"|sed 's/^ *//;s/ *$//')
+field_value=$(awk -F: '{gsub(/^ +| +$/, "", $2); print substr($0, index($0, $2))}' <<<"$line"|sed 's/^ *//;s/ *$//')
+[[ -z $field_value ]]&&continue
+if [[ $field_name == "$last_field_name" ]];then
+getbgp["$field_name"]+=", $field_value"
+last_field_name="$field_name"
+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
+field_name=$(awk -F: '{gsub(/^ +| +$/, "", $1); print tolower($1)}' <<<"$line"|sed 's/^ *//;s/ *$//')
+field_value=$(awk -F: '{gsub(/^ +| +$/, "", $2); print substr($0, index($0, $2))}' <<<"$line"|sed 's/^ *//;s/ *$//')
+[[ -z $field_value ]]&&continue
+if [[ $field_name == "$last_field_name" ]];then
+getbgp["$field_name"]+=", $field_value"
+last_field_name="$field_name"
+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
+}
+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 cidr="${IP%.*}.0/24"
+if [[ ${bgp[prefixnum]} != "24" ]];then
+bgp[neighbortotal]="256"
+bgp[neighboractive]=$(curl -s -m 10 --user-agent "$UA_Browser" "https://bgp.tools/pfximg/$cidr"|convert png:- txt:-|grep -c "#0003FF")
+fi
+bgp[iptotal]="$((2**(32-${bgp[prefixnum]})))"
+bgp[ipactive]=$(curl -s -m 10 --user-agent "$UA_Browser" "https://bgp.tools/pfximg/${bgp[prefix]}"|convert png:- txt:-|grep -c "#0003FF")
+}
+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=()
+local result=$(stun "stun.l.google.com" 2>/dev/null)
+getnat[nat]=$(echo "$result"|grep -oE "0x[0-9A-Fa-f]+")
+if [[ -z ${getnat[nat]} ]];then
+getnat[natresu]="${slocal[error]}"
+else
+getnat[natresu]="${slocal[${getnat[nat]}]}"
+fi
+}
+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")
+}
+test_pcn(){
+RESPONSE=$(curl -s https://cdn.jsdelivr.net/gh/xykt/NetQuality@main/ref/province.json)
+while IFS=" " read -r province code short;do
+pcode[$province]=$code
+pshort[$province]=$short
+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)"')
+}
+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
+echo -en "${presu[$key]}"
+((count++))
+if ((count%resu_per_line==0));then
+echo
+else
+echo -en " "
+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=$(nexttrace -p 80 -q 10 -"$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"
+fi
+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
+;;
+"23764")tresucn="CTGGIA"
+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
+;;
+"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=$(mtr -"$ipv" --"$rmode" --no-dns -y 0 -P 80 -c 10 -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"
+fi
+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
+;;
+"23764")tresucn="CTGGIA"
+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
+;;
+"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
+if [[ $ipv == "4" ]];then
+rdomain=("" "219.141.136.10" "114.249.128.1" "112.34.111.194" "202.96.199.133" "211.95.1.97" "211.136.112.50" "113.111.211.22" "211.95.193.97" "120.241.242.225")
+else
+rdomain=("" "2400:89c0:1053:3::69" "2400:89c0:1013:3::54" "2409:8c00:8421:1303::55" "240e:e1:aa00:4000::24" "2408:80f1:21:5003::a" "2409:8c1e:75b0:3003::26" "240e:97c:2f:3000::44" "2408:8756:f50:1001::c" "2409:8c54:871:1001::12")
+fi
+local max_threads=18
+local 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"
+rww["$index"]="$rww_value"
+rcn["$index"]="$rcn_value"
+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"
+}
+show_route(){
+echo -ne "\r${sroute[title]}\n"
+echo -ne "\r$Font_Cyan${sroute[bj]}${sroute[tcp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[1]}$Font_Green->$Font_Suffix${routcn[1]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[3]}$Font_Green->$Font_Suffix${routcn[3]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[5]}$Font_Green->$Font_Suffix${routcn[5]}\n"
+echo -ne "\r$Font_Cyan${sroute[bj]}${sroute[udp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[2]}$Font_Green->$Font_Suffix${routcn[2]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[4]}$Font_Green->$Font_Suffix${routcn[4]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[6]}$Font_Green->$Font_Suffix${routcn[6]}\n"
+echo -ne "\r$Font_Cyan${sroute[sh]}${sroute[tcp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[7]}$Font_Green->$Font_Suffix${routcn[7]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[9]}$Font_Green->$Font_Suffix${routcn[9]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[11]}$Font_Green->$Font_Suffix${routcn[11]}\n"
+echo -ne "\r$Font_Cyan${sroute[sh]}${sroute[udp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[8]}$Font_Green->$Font_Suffix${routcn[8]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[10]}$Font_Green->$Font_Suffix${routcn[10]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[12]}$Font_Green->$Font_Suffix${routcn[12]}\n"
+echo -ne "\r$Font_Cyan${sroute[gz]}${sroute[tcp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[13]}$Font_Green->$Font_Suffix${routcn[13]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[15]}$Font_Green->$Font_Suffix${routcn[15]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[17]}$Font_Green->$Font_Suffix${routcn[17]}\n"
+echo -ne "\r$Font_Cyan${sroute[gz]}${sroute[udp]}$Font_Green${sroute[ct]}$Font_Suffix ${routww[14]}$Font_Green->$Font_Suffix${routcn[14]} || $Font_Green${sroute[cu]}$Font_Suffix $Font_Suffix${routww[16]}$Font_Green->$Font_Suffix${routcn[16]} || $Font_Green${sroute[cm]}$Font_Suffix $Font_Suffix${routww[18]}$Font_Green->$Font_Suffix${routcn[18]}\n"
+}
+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 [[ $LANG == "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 -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
+echo -ne "${iresu[$key]}"
+((count++))
+if ((count%2==0));then
+echo
+else
+echo -en "||"
+fi
+done
+((count%2!=0))&&echo
+}
+parse_speedtest_result(){
+local tid="$1"
+local tcode="$2"
+local infolen
+if [[ $LANG == "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 -s https://raw.githubusercontent.com/xykt/NetQuality/refs/heads/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 [[ $LANG == "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 [[ $LANG == "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
+echo -ne "${sresu[$key]}"
+((count++))
+if ((count%2==0));then
+echo
+else
+echo -en "||"
+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[bash]}" 80
+echo -ne "\r$PADDING${shead[bash]}\n"
+calc_padding "${shead[git]}" 80
+echo -ne "\r$PADDING$Font_U${shead[git]}$Font_Suffix\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=", "
+[[ -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"
+if [[ -z ${bgp[neighbortotal]} || ${bgp[neighbortotal]} == 0 ]];then
+neighbor_ratio=0
+else
+neighbor_ratio=$(echo "scale=2; ${bgp[neighboractive]}/${bgp[neighbortotal]}"|bc)
+fi
+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
+if [[ -z ${bgp[iptotal]} || ${bgp[iptotal]} == 0 ]];then
+ip_ratio=0
+else
+ip_ratio=$(echo "scale=2; ${bgp[ipactive]}/${bgp[iptotal]}"|bc)
+fi
+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
+local neighborresu=""
+[[ -n ${bgp[neighboractive]} ]]&&neighborresu="${Font_Green}Subnet/24 $neighbor_bg$Font_B$Font_White ${bgp[neighboractive]} / ${bgp[neighbortotal]} $Font_Suffix "
+[[ -n ${bgp[ipactive]} ]]&&neighborresu+="${Font_Green}Prefix/${bgp[prefixnum]} $ip_bg$Font_B$Font_White ${bgp[ipactive]} / ${bgp[iptotal]} $Font_Suffix"
+[[ -n $neighborresu ]]&&echo -ne "\r$Font_Cyan${sbgp[neighbor]}$neighborresu$Font_Suffix\n"
+}
+show_local(){
+echo -ne "\r${slocal[title]}\n"
+[[ -n ${getnat[natresu]} ]]&&echo -ne "\r$Font_Cyan${slocal[nat]}$Font_Green${getnat[natresu]}$Font_Suffix\n"
+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]}+")"
+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 $Font_Cyan${sconn[peers]}$Font_Green${conn[peers]}$Font_Suffix\n"
+else
+echo -ne "$Font_Cyan${sconn[upstreams]}$Font_Green$(printf '%-10s' "${conn[upstreams]}")$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 -e "${conn[asn]}\n${conn[org]}"
+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 -e "${conn[asn]}"
+[[ -n ${conn[org]} ]]&&echo -e "${conn[org]}"
+}
+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(){
+while getopts "l:S:fhjyLP46" opt;do
+case $opt in
+4)if
+[[ IPV4check -ne 0 ]]
+then
+IPV6check=0
+else
+ERRORcode=4
+fi
+;;
+6)if
+[[ IPV6check -ne 0 ]]
+then
+IPV4check=0
+else
+ERRORcode=6
+fi
+;;
+f)fullIP=1
+;;
+h)show_help
+;;
+j)mode_json=1
+;;
+l)LANG=$OPTARG
+;;
+y)mode_yes=1
+;;
+L)mode_low=1
+;;
+P)mode_ping=1
+;;
+S)mode_skip="$OPTARG"
+;;
+\?)ERRORcode=1
+esac
+done
+[[ $mode_skip == *"1"* && $mode_skip == *"2"* && $mode_skip == *"3"* && $mode_skip == *"4"* && ($mode_ping -eq 1 || $mode_skip == *"5"*) && ($mode_ping -eq 1 || $mode_low -eq 1 || $mode_skip == *"6"*) && ($mode_ping -eq 1 || $mode_low -eq 1 || $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(){
+asponsor=$(curl -sL --max-time 5 "https://cdn.jsdelivr.net/gh/xykt/IPQuality@main/ref/sponsor.ans")
+aad1=$(curl -sL --max-time 5 "https://cdn.jsdelivr.net/gh/xykt/IPQuality@main/ref/ad1.ans")
+echo -e "$asponsor"
+echo -e "$aad1"
+}
+read_ref(){
+ISO3166=$(curl -sL -m 10 "https://cdn.jsdelivr.net/gh/xykt/NetQuality@main/ref/iso3166.json")
+RESPONSE=$(curl -s "https://cdn.jsdelivr.net/gh/xykt/NetQuality@main/ref/province.json")
+while IFS=" " read -r province code short;do
+pcode[$province]=$code
+pshort[$province]=$short
+pcode_lower=$(echo "$code"|tr '[:upper:]' '[:lower:]')
+pct[${province}4]="$pcode_lower-ct-v4.ip.zstaticcdn.com"
+pcu[${province}4]="$pcode_lower-cu-v4.ip.zstaticcdn.com"
+pcm[${province}4]="$pcode_lower-cm-v4.ip.zstaticcdn.com"
+pct[${province}6]="$pcode_lower-ct-v6.ip.zstaticcdn.com"
+pcu[${province}6]="$pcode_lower-cu-v6.ip.zstaticcdn.com"
+pcm[${province}6]="$pcode_lower-cm-v6.ip.zstaticcdn.com"
+done < <(echo "$RESPONSE"|jq -r '.[] | select(.province < 70) | "\(.province) \(.code) \(.short)"')
+while read -r as name;do
+AS_MAPPING["$as"]="$name"
+done < <(curl -s "https://raw.githubusercontent.com/xykt/NetQuality/refs/heads/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 "${getnat[natresu]:-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_ping -eq 0 && $mode_skip != *"5"* ]]&&get_route $2
+[[ $mode_ping -eq 0 && $mode_low -eq 0 && $mode_skip != *"6"* && $2 -eq 4 ]]&&speedtest_test
+[[ $mode_ping -eq 0 && $mode_low -eq 0 && $mode_skip != *"7"* ]]&&iperf_test $2
+echo -ne "$Font_LineClear"
+if [ $2 -eq 4 ]||[[ $IPV4work -eq 0 || $IPV4check -eq 0 ]];then
+for ((i=0; i