#!/bin/bash

# ==================== 🛠 多中转服务配置区 ====================
# 格式: "本地端口:目标IP:目标端口" (可以无限添加，用空格隔开)
PROXY_LIST=(
    "8888:120.25.75.194:30063"
    "7777:120.25.75.194:11883"
)

LOG_FILE="/var/log/socat-proxy.log"
TIMEOUT="15" 
# ==========================================================

# 检查权限
if [ "$EUID" -ne 0 ]; then
    echo "❌ 请使用 root 权限运行此脚本"
    exit 1
fi

# 精准获取某个本地端口对应的 socat 主 PID
get_pid() {
    local l_port=$1
    ss -tlnp "sport = :${l_port}" 2>/dev/null | grep -oP 'pid=\K\d+' | head -n1
}

start_proxy() {
    echo "🚀 正在检查并启动所有中转服务..."
    echo "------------------------------------------------"
    
    for item in "${PROXY_LIST[@]}"; do
        # 解析参数
        IFS=":" read -r LOCAL_PORT TARGET_IP TARGET_PORT <<< "$item"
        
        local pid=$(get_pid "$LOCAL_PORT")
        if [ -n "$pid" ]; then
            echo "⚠️  端口 [:$LOCAL_PORT] 已经在运行中 (PID: $pid)，跳过。"
            continue
        fi

        echo "正在启动: 监听 :$LOCAL_PORT -> 转发至 $TARGET_IP:$TARGET_PORT"
        
        # 启动 socat 并将特征带入进程名，方便 pkill 精准捕获
        nohup socat  -t ${TIMEOUT} TCP-LISTEN:${LOCAL_PORT},fork,reuseaddr TCP:${TARGET_IP}:${TARGET_PORT} >> ${LOG_FILE} 2>&1 &
        
        sleep 0.5
        
        # 检测端口是否成功监听
        if ss -tln | grep -q ":${LOCAL_PORT}\b"; then
            local s_pid=$(get_pid "$LOCAL_PORT")
            echo "  ✓ 启动成功！(PID: ${s_pid:-后台托管})"
        else
            echo "  ✗ 端口 :$LOCAL_PORT 监听失败，请检查端口是否被占用或查看日志。"
        fi
    done
    echo "------------------------------------------------"
}

stop_proxy() {
    echo "🛑 正在停止所有 socat 中转服务..."
    echo "------------------------------------------------"
    
    for item in "${PROXY_LIST[@]}"; do
        IFS=":" read -r LOCAL_PORT TARGET_IP TARGET_PORT <<< "$item"
        
        local pid=$(get_pid "$LOCAL_PORT")
        
        echo "正在清理端口 [:$LOCAL_PORT] 的所有关联进程..."
        
        # 1. 尝试结束主进程
        if [ -n "$pid" ]; then
            kill "$pid" 2>/dev/null
        fi

        # 2. 精准清理带此配置特征的 socat 主/子/孤儿进程
        pkill -f "socat.*TCP-LISTEN:${LOCAL_PORT}.*TCP:${TARGET_IP}:${TARGET_PORT}" 2>/dev/null
        
        sleep 0.5

        # 3. 强力清场：如果端口还顽固被占，精准强杀残留
        local residual_pids=$(ss -tlnp "sport = :${LOCAL_PORT}" 2>/dev/null | grep -oP 'pid=\K\d+')
        if [ -n "$residual_pids" ]; then
            echo "  发现 :$LOCAL_PORT 残留子进程，正在强行终止..."
            echo "$residual_pids" | xargs kill -9 2>/dev/null
        fi
        echo "  ✓ 端口 :$LOCAL_PORT 已完全释放。"
    done
    echo "------------------------------------------------"
}

status_proxy() {
    echo "📊 全局中转服务运行状态:"
    echo "------------------------------------------------"
    printf "%-10s %-25s %-8s %-10s\n" "本地端口" "目标地址" "状态" "进程数(含子)"
    
    local active_count=0
    
    for item in "${PROXY_LIST[@]}"; do
        IFS=":" read -r LOCAL_PORT TARGET_IP TARGET_PORT <<< "$item"
        
        # 统计当前配置特征下的 socat 独立进程数
        local total_procs=$(pgrep -f "socat.*TCP-LISTEN:${LOCAL_PORT}.*TCP:${TARGET_IP}:${TARGET_PORT}" | wc -l)
        
        if [ "$total_procs" -gt 0 ]; then
            printf "\e[32m%-10s\e[0m %-25s \e[32m%-8s\e[0m %-10s\n" ":$LOCAL_PORT" "$TARGET_IP:$TARGET_PORT" "RUNNING" "$total_procs"
            ((active_count++))
        else
            printf "\e[31m%-10s\e[0m %-25s \e[31m%-8s\e[0m %-10s\n" ":$LOCAL_PORT" "$TARGET_IP:$TARGET_PORT" "STOPPED" "0"
        fi
    done
    echo "------------------------------------------------"
    echo "统计: 配置总数 ${#PROXY_LIST[@]} | 正在运行 $active_count"
}

case "$1" in
    start) start_proxy ;;
    stop) stop_proxy ;;
    restart) stop_proxy; sleep 1; start_proxy ;;
    status) status_proxy ;;
    *)
        if [ -z "$1" ]; then
            start_proxy
        else
            echo "用法: $0 {start|stop|restart|status}"
            exit 1
        fi
        ;;
esac
