#!/bin/bash
# =============================================================================
# BBRv3 智能多场景终极调优脚本 v3.9.3
# 特性：BBRv3 版本检测 + 智能多节点测速 + 动态 BDP 计算 + Cloudflare 风格 patch
# 更新：2026-04-20 v3.9.3（优化内存上限、rmem中间值、netdev_max_backlog）
# =============================================================================
set -euo pipefail

# --- 颜色与日志 ---
RED='\033[31m'; GREEN='\033[32m'; YELLOW='\033[33m'; CYAN='\033[96m'; RESET='\033[0m'
SYSCTL_CONF="/etc/sysctl.d/99-bbrv3-tune.conf"

log_msg() { echo -e "${GREEN}[✓] $1${RESET}"; }
log_warn() { echo -e "${YELLOW}[!] $1${RESET}"; }
log_err() { echo -e "${RED}[✗] $1${RESET}"; exit 1; }

# --- 前置检查 ---
[ "$EUID" -ne 0 ] && log_err "请使用 root 权限运行此脚本！"

# --- BBRv3 版本检测 ---
check_bbrv3() {
    if ! modinfo tcp_bbr >/dev/null 2>&1; then
        log_warn "未检测到 tcp_bbr 模块！请先加载模块或安装支持 BBRv3 的内核。"
        return 1
    fi
    BBR_VER=$(modinfo tcp_bbr 2>/dev/null | grep -oP 'version:\s*\K\d+' || echo "unknown")
    if [ "$BBR_VER" = "3" ]; then
        log_msg "✅ 检测到 BBRv3（version: 3），继续优化！"
    else
        log_warn "当前 BBR 版本为 v${BBR_VER}（非 v3）！强烈建议升级到 Google BBRv3 内核。"
    fi
}

# --- 系统基础信息探测 ---
TOTAL_MEM_MB=$(free -m | awk 'NR==2{print $2}')
MAX_BUFFER_MB=$(( TOTAL_MEM_MB * 20 / 100 ))
[ "$MAX_BUFFER_MB" -lt 16 ] && MAX_BUFFER_MB=16
[ "$MAX_BUFFER_MB" -gt 1024 ] && MAX_BUFFER_MB=1024

# 动态 fs.file-max 计算（推荐版）
if [ "$TOTAL_MEM_MB" -le 512 ]; then
    FILE_MAX=393216          # 512MB 及以下
elif [ "$TOTAL_MEM_MB" -le 1024 ]; then
    FILE_MAX=786432          # 512MB ~ 1GB（更均衡）
elif [ "$TOTAL_MEM_MB" -le 2048 ]; then
    FILE_MAX=1048576
elif [ "$TOTAL_MEM_MB" -le 4096 ]; then
    FILE_MAX=1572864
else
    FILE_MAX=2097152
fi

# --- 多节点自动带宽测速 ---
auto_detect_bandwidth() {
    echo -e "\n${CYAN}====================================================${RESET}" >&2
    echo -e "${CYAN}>>> 开始测速（优先：美西 LAX/SJC → 新加坡 → 东京）...${RESET}" >&2
    echo -e "${CYAN}策略：测得 3 个 >500Mbps 节点或单个 >2500Mbps 节点即跳出${RESET}" >&2
    echo -e "${CYAN}====================================================${RESET}" >&2

    local TEST_URLS=(
        "https://lax-ca-us-ping.vultr.com/vultr.com.100MB.bin"
        "https://speedtest-sfo3.digitalocean.com/100mb.test"
        "https://speedtest.fremont.linode.com/100MB-fremont.bin"
        "https://hil-speed.hetzner.com/100MB.bin"
        "https://speedtest.singapore.linode.com/100MB-singapore.bin"
        "https://sin-speed.hetzner.com/100MB.bin"
        "https://hnd-jp-ping.vultr.com/vultr.com.100MB.bin"
        "https://fsn1-speed.hetzner.com/100MB.bin"
    )

    local max_mbps=0
    local best_url=""
    local results=()
    local fast_node_count=0

    set +e
    for url in "${TEST_URLS[@]}"; do
        echo -e "${CYAN}→ 测试节点: ${url}${RESET}" >&2
        local speed_bytes=$(curl -4 --max-time 25 -s -w "%{speed_download}" -o /dev/null "$url" 2>/dev/null || echo "0")

        if [ "$speed_bytes" != "0" ] && [ -n "$speed_bytes" ]; then
            local mbps=$(awk "BEGIN {printf \"%.0f\", ($speed_bytes * 8) / 1000000 }")
            echo -e " └─ ✅ 测得 ${GREEN}${mbps} Mbps${RESET}" >&2
            results+=("${url##*/} → ${mbps} Mbps")

            if [ "$mbps" -gt "$max_mbps" ]; then
                max_mbps=$mbps
                best_url=$url
            fi

            if [ "$mbps" -ge 500 ]; then
                ((fast_node_count++))
            fi
            if [ "$fast_node_count" -ge 3 ] || [ "$max_mbps" -ge 2500 ]; then
                echo -e "${YELLOW}提示: 已满足高速节点条件，为节省时间停止后续测试。${RESET}" >&2
                break
            fi
        else
            echo -e " └─ ❌ 失败或超时" >&2
            results+=("${url##*/} → 失败")
        fi
    done
    set -e

    echo -e "\n${CYAN}=== 测速结果汇总 ===${RESET}" >&2
    for res in "${results[@]}"; do
        echo -e " ${res}" >&2
    done
    echo -e "${CYAN}=====================${RESET}" >&2

    if [ "$max_mbps" -gt 10 ]; then
        echo -e "${GREEN}✅ 最终采用最高下行带宽: ${max_mbps} Mbps（${best_url}）${RESET}" >&2
        echo "$max_mbps"
        return 0
    else
        echo -e "${YELLOW}所有节点测速失败，切换为手动输入${RESET}" >&2
        return 1
    fi
}

# --- BDP 计算 ---
calculate_bdp() {
    echo -e "\n${CYAN}>>> 步骤 1: 带宽获取${RESET}"
    read -r -p "是否自动测速带宽？(推荐) [Y/n]: " AUTO_CHOICE
    if [[ "${AUTO_CHOICE:-y}" =~ ^[Yy]$ ]]; then
        echo -e "${YELLOW}正在启动自动测速...${RESET}"
        BW=$(auto_detect_bandwidth)
        if [ -z "$BW" ]; then
            read -r -p "请输入此服务器的【实际可用最大下行带宽】(单位: Mbps, 默认: 1000): " INPUT_BW
            BW=${INPUT_BW:-1000}
        fi
    else
        read -r -p "请输入此服务器的【实际可用最大下行带宽】(单位: Mbps, 默认: 1000): " INPUT_BW
        BW=${INPUT_BW:-1000}
    fi

    echo -e "\n${CYAN}>>> 步骤 2: 目标用户网络环境${RESET}"
    echo "1. 本地/同大洲互联 (延迟 ~50ms)"
    echo "2. 跨国/跨境互联 (延迟 ~150ms) [代理、出海业务推荐]"
    echo "3. 极端恶劣网络 (延迟 ~250ms)"
    read -r -p "请选择您的主要用户群体 [默认: 2]: " RTT_CHOICE
    case "${RTT_CHOICE:-2}" in
        1) RTT_MS=50 ;;
        3) RTT_MS=250 ;;
        *) RTT_MS=150 ;;
    esac

    BDP_MB=$(awk "BEGIN {print ($BW * $RTT_MS / 8 / 1000) * 2.5}")
    BDP_MB=$(printf "%.0f" "$BDP_MB")

    if [ "$BDP_MB" -gt "$MAX_BUFFER_MB" ]; then
        log_warn "计算所得 BDP (${BDP_MB}MB) 超出安全阈值，已限制为物理内存的20% (${MAX_BUFFER_MB}MB)"
        BDP_MB=$MAX_BUFFER_MB
    elif [ "$BDP_MB" -lt 16 ]; then
        BDP_MB=16
    fi
}

# --- 生成 Sysctl 配置 ---
generate_config() {
    local mode_name=$1
    local buffer_mb=$2
    local lowat=$3
    local backlog=$4
    local buffer_bytes=$(( buffer_mb * 1024 * 1024 ))

    if [ "$mode_name" = "大吞吐模式 (Throughput)" ]; then
        lowat=4294967295
    fi

    local collapse_line=""
    if [ -f /proc/sys/net/ipv4/tcp_collapse_max_bytes ]; then
        collapse_line="net.ipv4.tcp_collapse_max_bytes = 6291456"
    else
        log_warn "当前内核不支持 tcp_collapse_max_bytes（需 XanMod 或 Cloudflare patch），已跳过该参数。"
    fi

    cat > "$SYSCTL_CONF" << EOF
# =========================================================
# BBRv3 调优配置 - 模式: $mode_name
# 生成时间: $(date) | 物理内存: ${TOTAL_MEM_MB}MB | BBR版本: ${BBR_VER:-detected}
# =========================================================
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.core.rmem_max = $buffer_bytes
net.core.wmem_max = $buffer_bytes
net.ipv4.tcp_rmem = 4096 131072 $buffer_bytes
net.ipv4.tcp_wmem = 4096 131072 $buffer_bytes
net.ipv4.tcp_adv_win_scale = -2
net.ipv4.tcp_notsent_lowat = $lowat
$collapse_line
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_mtu_probing = 2
net.core.somaxconn = $backlog
net.ipv4.tcp_max_syn_backlog = $backlog
net.core.netdev_max_backlog = 30000
fs.file-max = ${FILE_MAX}
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_tw_buckets = $(( backlog * 2 ))
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_local_port_range = 20000 65535
vm.swappiness = 5
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
EOF

    sysctl -p "$SYSCTL_CONF" >/dev/null 2>&1

    echo -e "\n${CYAN}====================================================${RESET}"
    log_msg "配置已成功应用！当前模式: ${mode_name} (缓冲区: ${buffer_mb}MB)"
    echo -e "${CYAN}>>> 配置详情总结 <<<${RESET}"
    echo -e "✅ 写入配置文件：${SYSCTL_CONF}"
    echo -e "✅ 主要修改内容："
    echo -e "   • 拥塞控制：BBRv3 + fq 队列"
    echo -e "   • 缓冲区：rmem_max/wmem_max = ${buffer_mb}MB"
    echo -e "   • tcp_rmem / tcp_wmem 中间值设置为 131072（均衡模式推荐值）"
    echo -e "   • tcp_adv_win_scale = -2（精确窗口控制）"
    echo -e "   • tcp_notsent_lowat = $lowat（低延迟/高吞吐优化）"
    echo -e "   • tcp_collapse_max_bytes = 6291456（${collapse_line:+已启用}${collapse_line:-已跳过}）"
    echo -e "   • tcp_no_metrics_save=1、tcp_mtu_probing=2 等生产参数"
    echo -e "   • 高并发：somaxconn / syn_backlog / 端口范围等"
    echo -e "${CYAN}====================================================${RESET}"
}

# --- 主菜单 ---
clear
echo -e "${CYAN}====================================================${RESET}"
echo -e " BBRv3 智能网络调优系统 (v3.9.3)"
echo -e " 当前系统内存: ${TOTAL_MEM_MB} MB "
echo -e "${CYAN}====================================================${RESET}"

check_bbrv3

# --- 新增：启动时智能检测配置文件（按您的要求实现）---
if [ -f "$SYSCTL_CONF" ]; then
    echo -e "${YELLOW}⚠️ 检测到已存在的调优配置文件: $SYSCTL_CONF${RESET}"
    read -r -p "是否先卸载当前配置？(Y/n，默认 n): " UNINSTALL_CHOICE
    if [[ "${UNINSTALL_CHOICE:-n}" =~ ^[Yy]$ ]]; then
        rm -f "$SYSCTL_CONF"
        sysctl --system >/dev/null 2>&1
        log_msg "已卸载自定义 TCP 配置并恢复内核默认。"
        echo -e "${GREEN}脚本已退出。您可以重新运行脚本来进行新的配置。${RESET}"
        exit 0
    else
        log_msg "保留现有配置，继续进入模式选择菜单..."
    fi
else
    log_msg "未检测到现有调优配置文件，直接进入安装流程..."
fi

echo "请选择适合您业务的优化模式："
echo ""
echo " 1) ⚖️ 综合均衡模式 (推荐)"
echo " 2) 🚀 大吞吐 / 视频流模式 (高带宽)"
echo " 3) ⚡ 低延迟 / 代理转发模式 (抗拥塞)"
echo " 4) 🗑️ 清除调优配置 (恢复系统默认)"
echo " 0) ❌ 退出脚本"
echo -e "${CYAN}====================================================${RESET}"

read -r -p "请输入序号 [1-4]: " MENU_CHOICE

case "$MENU_CHOICE" in
    1)
        calculate_bdp
        generate_config "均衡模式 (Balanced)" "$BDP_MB" "131072" "8192"
        ;;
    2)
        calculate_bdp
        THROUGHPUT_BDP=$(( BDP_MB * 15 / 10 ))
        [ "$THROUGHPUT_BDP" -gt "$MAX_BUFFER_MB" ] && THROUGHPUT_BDP=$MAX_BUFFER_MB
        generate_config "大吞吐模式 (Throughput)" "$THROUGHPUT_BDP" "4294967295" "16384"
        ;;
    3)
        calculate_bdp
        generate_config "低延迟代理模式 (Low-Latency)" "$BDP_MB" "16384" "8192"
        ;;
    4)
        rm -f "$SYSCTL_CONF"
        sysctl --system >/dev/null 2>&1
        log_msg "已清理自定义 TCP 配置，恢复内核默认。"
        ;;
    0)
        exit 0
        ;;
    *)
        log_err "输入无效，已退出。"
        ;;
esac

echo -e "\n${YELLOW}[!] 提示: 建议重启服务器确保 FQ 队列完全生效。${RESET}"
echo -e "${GREEN}脚本执行完毕！如需压测可使用 iperf3 / wrk / ss -m / tc -s qdisc 观察。${RESET}"

