#!/bin/sh set -eu SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) APP_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd) CONFIG_PATH=${1:-"$APP_DIR/router_local.conf"} if [ ! -r "$CONFIG_PATH" ]; then echo "[router-local] config not found: $CONFIG_PATH" >&2 exit 1 fi # shellcheck disable=SC1090 . "$CONFIG_PATH" CFST_WORK_DIR=${CFST_WORK_DIR:-"$APP_DIR/cfst"} CFST_BIN=${CFST_BIN:-"./cfst"} CFST_IP_FILE=${CFST_IP_FILE:-"ip.txt"} CFST_RESULT_FILE=${CFST_RESULT_FILE:-"result.csv"} CFST_DISPLAY_COUNT=${CFST_DISPLAY_COUNT:-10} CFST_THREADS=${CFST_THREADS:-} CFST_TEST_COUNT=${CFST_TEST_COUNT:-} CFST_DOWNLOAD_COUNT=${CFST_DOWNLOAD_COUNT:-} CFST_DOWNLOAD_TIME=${CFST_DOWNLOAD_TIME:-} CFST_PORT=${CFST_PORT:-443} CFST_URL=${CFST_URL:-} CFST_HTTPING=${CFST_HTTPING:-0} CFST_HTTPING_CODE=${CFST_HTTPING_CODE:-} CFST_CFCOLO=${CFST_CFCOLO:-} CFST_LATENCY_LIMIT=${CFST_LATENCY_LIMIT:-} CFST_LATENCY_LOWER=${CFST_LATENCY_LOWER:-} CFST_LOSS_LIMIT=${CFST_LOSS_LIMIT:-} CFST_SPEED_LIMIT=${CFST_SPEED_LIMIT:-} CFST_DISABLE_DOWNLOAD=${CFST_DISABLE_DOWNLOAD:-0} CFST_ALL_IP=${CFST_ALL_IP:-0} CFST_DEBUG=${CFST_DEBUG:-0} CFST_SKIP_RUN=${CFST_SKIP_RUN:-0} TOP_N=${TOP_N:-3} RUNTIME_DIR=${RUNTIME_DIR:-"$APP_DIR/cfip_runtime"} VALUE_TEXT_FILE=${VALUE_TEXT_FILE:-"current_ip.txt"} VALUE_JSON_FILE=${VALUE_JSON_FILE:-"current_ip.json"} STATE_FILE=${STATE_FILE:-"state.json"} EXPORT_VARS_FILE=${EXPORT_VARS_FILE:-"substore_vars.json"} VALUE_JSON_KEY=${VALUE_JSON_KEY:-ip} STATE_LAST_GOOD_KEY=${STATE_LAST_GOOD_KEY:-last_good_ip} EXPORT_VALUE_KEY=${EXPORT_VALUE_KEY:-AUTO_CFIP} CURRENT_TEXT_PATH="$RUNTIME_DIR/$VALUE_TEXT_FILE" CURRENT_JSON_PATH="$RUNTIME_DIR/$VALUE_JSON_FILE" STATE_PATH="$RUNTIME_DIR/$STATE_FILE" EXPORT_VARS_PATH="$RUNTIME_DIR/$EXPORT_VARS_FILE" RESULT_PATH="$CFST_WORK_DIR/$CFST_RESULT_FILE" UPDATED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ") mkdir -p "$RUNTIME_DIR" json_get_string() { key="$1" file="$2" if [ ! -f "$file" ]; then return 0 fi sed -n "s/.*\"$key\":[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$file" | head -n 1 } json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' } trim_cr() { printf '%s' "$1" | tr -d '\r' } build_top_candidates_json() { awk -F',' -v top_n="$TOP_N" ' function trim(v) { gsub(/\r/, "", v) sub(/^[[:space:]]+/, "", v) sub(/[[:space:]]+$/, "", v) return v } function esc(v) { gsub(/\\/,"\\\\",v) gsub(/"/,"\\\"",v) return v } NR == 1 { next } count >= top_n { exit } NF < 1 { next } { ip = esc(trim($1)) sent = esc(trim($2)) received = esc(trim($3)) loss = esc(trim($4)) latency = esc(trim($5)) speed = esc(trim($6)) region = esc(trim($7)) if (count > 0) { printf(",") } printf("{\"ip\":\"%s\",\"domain\":\"%s\",\"sent\":\"%s\",\"received\":\"%s\",\"loss_rate\":\"%s\",\"avg_latency\":\"%s\",\"download_speed\":\"%s\",\"region\":\"%s\"}", ip, ip, sent, received, loss, latency, speed, region) count++ } END { if (count == 0) { printf("") } } ' "$RESULT_PATH" } write_success_outputs() { selected_ip="$1" top_candidates_json="$2" source_count="$3" escaped_ip=$(json_escape "$selected_ip") printf '%s\n' "$selected_ip" > "$CURRENT_TEXT_PATH" cat > "$CURRENT_JSON_PATH" < "$STATE_PATH" < "$EXPORT_VARS_PATH" < "$CURRENT_TEXT_PATH" cat > "$CURRENT_JSON_PATH" < "$STATE_PATH" < "$EXPORT_VARS_PATH" <&2 exit 1 fi fi if [ ! -s "$RESULT_PATH" ]; then if [ -n "$LAST_GOOD_IP" ]; then write_error_with_fallback "$LAST_GOOD_IP" "cfst result file missing or empty" echo "[router-local] empty result, fallback to last good ip: $LAST_GOOD_IP" exit 0 fi echo "[router-local] result file missing or empty: $RESULT_PATH" >&2 exit 1 fi BEST_LINE=$(sed -n '2p' "$RESULT_PATH" | tr -d '\r') BEST_IP=$(printf '%s' "$BEST_LINE" | cut -d',' -f1 | tr -d ' ') SOURCE_COUNT=$(awk -F',' 'NR > 1 && NF > 0 { count++ } END { print count + 0 }' "$RESULT_PATH") TOP_CANDIDATES_JSON=$(build_top_candidates_json) if [ -z "$BEST_IP" ]; then if [ -n "$LAST_GOOD_IP" ]; then write_error_with_fallback "$LAST_GOOD_IP" "no valid ip found in cfst result" echo "[router-local] no valid ip found, fallback to last good ip: $LAST_GOOD_IP" exit 0 fi echo "[router-local] no valid ip found in result file" >&2 exit 1 fi write_success_outputs "$BEST_IP" "$TOP_CANDIDATES_JSON" "$SOURCE_COUNT" echo "[router-local] selected ip: $BEST_IP"