#!/bin/bash
# @desc: TCP & UDP 回显服务端(配合 udping_client)
# @usage: wcl udping_server [端口]
#   例: wcl udping_server 9000
# ==============================================================================
# Script Name: TCP & UDP Echo Server (Final Complete)
# Author:      LULU
# Description: 双协议(TCP/UDP)服务端。
#              集成完整的环境检测、端口复用修复、后台进程管理及安装指南。
# ==============================================================================

PORT=${1:-9999}

# --- [核心功能] 帮助与安装指南 (绝不省略) ---
show_help() {
    echo "=================================================================="
    echo "   TCP & UDP Echo Server - 使用手册"
    echo "=================================================================="
    echo "用法: $0 [端口号]"
    echo "示例: $0 10022"
    echo ""
    echo "功能说明:"
    echo "  本脚本会自动在后台同时启动 TCP 和 UDP 的监听服务。"
    echo "  收到任何数据都会原样回传 (Echo)，用于配合客户端测试延迟。"
    echo ""
    echo "支持的工具 (脚本会自动检测并优先使用):"
    echo "  1. Python3 (推荐, 日志清晰, 多线程)"
    echo "  2. Socat   (推荐, 高性能, 稳定)"
    echo "  3. Ncat    (Nmap组件)"
    echo "  4. Netcat  (仅作为最后兜底方案)"
    echo ""
    echo "------------------------------------------------------------------"
    echo "   各平台工具安装指南 (缺失工具时请执行)"
    echo "------------------------------------------------------------------"
    echo "[OpenWrt / 嵌入式Linux]"
    echo "  opkg update"
    echo "  opkg install python3-light  # (首选推荐)"
    echo "  opkg install socat          # (备选推荐)"
    echo "  opkg install netcat         # (兜底)"
    echo ""
    echo "[Ubuntu / Debian / Kali]"
    echo "  sudo apt update"
    echo "  sudo apt install python3 socat"
    echo ""
    echo "[CentOS / RHEL / Fedora]"
    echo "  sudo yum install python3 socat"
    echo ""
    echo "[Alpine Linux (Docker)]"
    echo "  apk add python3 socat"
    echo "=================================================================="
}

# 检查参数
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
    show_help
    exit 0
fi

# --- 进程清理函数 (防止僵尸进程) ---
cleanup() {
    echo ""
    echo "[Info] 正在停止所有后台服务..."
    kill $(jobs -p) 2>/dev/null
    exit
}
trap cleanup SIGINT SIGTERM

echo "=============================================="
echo "   Dual Protocol Server | Port: $PORT"
echo "   (TCP & UDP Listening... Ctrl+C to stop)"
echo "=============================================="

# --- 方案 1: Python3 (最佳, 修复变量作用域与端口复用) ---
if command -v python3 >/dev/null 2>&1; then
    echo "[Mode] 使用 Python3 (Native)"
    
    # 将 Bash 变量 PORT 传递给 Python
    python3 -u -c "
import socket, threading, sys, time

PORT = $PORT

def udp_server():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 端口复用，防止重启脚本时报 Address already in use
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('0.0.0.0', PORT))
        print(f'[UDP] Listening on {PORT}...')
        while True:
            data, addr = s.recvfrom(2048)
            # print(f'[UDP] Recv {len(data)}B from {addr[0]}')
            s.sendto(data, addr)
    except Exception as e:
        print(f'[UDP Error] {e}')

def tcp_server():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('0.0.0.0', PORT))
        s.listen(5)
        print(f'[TCP] Listening on {PORT}...')
        while True:
            conn, addr = s.accept()
            # print(f'[TCP] Connect from {addr[0]}')
            t = threading.Thread(target=handle_tcp, args=(conn,))
            t.daemon = True
            t.start()
    except Exception as e:
        print(f'[TCP Error] {e}')

def handle_tcp(conn):
    try:
        while True:
            data = conn.recv(2048)
            if not data: break
            conn.send(data)
    except: pass
    finally: conn.close()

# 启动 UDP 线程
t_udp = threading.Thread(target=udp_server)
t_udp.daemon = True
t_udp.start()

# 主线程运行 TCP
tcp_server()
"
    exit 0
fi

# --- 方案 2: Socat (高性能) ---
if command -v socat >/dev/null 2>&1; then
    echo "[Mode] 使用 Socat (Background Jobs)"
    # TCP 监听
    socat TCP-LISTEN:$PORT,fork,reuseaddr EXEC:/bin/cat &
    
    # UDP 监听 (过滤掉 Connection refused 杂音)
    socat -v UDP-LISTEN:$PORT,fork,reuseaddr EXEC:/bin/cat 2>&1 | grep -v "Connection refused" &
    
    wait
    exit 0
fi

# --- 方案 3: Ncat (Nmap组件) ---
if command -v ncat >/dev/null 2>&1; then
    echo "[Mode] 使用 Ncat"
    ncat -l -p $PORT -k -c cat -v &
    ncat -u -l -p $PORT -k -c cat -v &
    wait
    exit 0
fi

# --- 方案 4: Netcat (通用兜底) ---
if command -v nc >/dev/null 2>&1; then
    echo "[Mode] 使用 Netcat (NC)"
    
    # 检测是否支持 -e (Busybox特性)
    if nc -h 2>&1 | grep -q "\-e"; then
        while true; do nc -l -p $PORT -e cat; done &
        # Busybox UDP 监听需用管道
        rm -f /tmp/udp_pipe
        mkfifo /tmp/udp_pipe
        cat /tmp/udp_pipe | nc -u -l -p $PORT > /tmp/udp_pipe &
    else
        # 普通 Linux nc
        if nc -h 2>&1 | grep -q "\-k"; then
            nc -l -k -p $PORT -c cat &
            nc -u -l -k -p $PORT -c cat &
        else
             echo "[Error] 你的 nc 版本过低，不支持并发服务端。"
             echo "请运行 $0 --help 查看如何安装 python3 或 socat。"
             exit 1
        fi
    fi
    wait
    exit 0
fi

echo "[Error] 未找到可用工具 (Python/Socat/Ncat/Nc)。"
echo "请运行 $0 --help 查看安装指南。"
exit 1