#!/bin/bash
################################################################################
# 网络连接检测模块
# 功能: 检测TCP连接状态、网络接口、端口连接、网络错误等
# 作者: Claude Code
# 日期: 2026-05-09
################################################################################

# 获取脚本所在目录并加载依赖
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LIB_DIR="${LIB_DIR:-/tmp/check_modules}"

# 加载配置文件和通用函数库
if [ -f "$LIB_DIR/lib/config.sh" ]; then
    source "$LIB_DIR/lib/config.sh"
else
    echo "ERROR: 配置文件不存在: $LIB_DIR/lib/config.sh"
    exit 1
fi

if [ -f "$LIB_DIR/lib/common.sh" ]; then
    source "$LIB_DIR/lib/common.sh"
else
    echo "ERROR: 通用函数库不存在: $LIB_DIR/lib/common.sh"
    exit 1
fi

# ==================== 检测函数 ====================

# 检测TCP连接状态统计
check_tcp_connections() {
    local established=0 time_wait=0 close_wait=0
    local tw_status cw_status

    # 从 /proc/net/tcp 读取TCP连接状态
    if [ -f /proc/net/tcp ]; then
        # TCP状态码: 01=ESTABLISHED, 06=TIME_WAIT, 08=CLOSE_WAIT
        local tcp_stats=$(cat /proc/net/tcp | awk '{print $4}' | sort | uniq -c | sort -rn)

        established=$(echo "$tcp_stats" | grep "01" | awk '{sum+=$1} END {print sum+0}')
        time_wait=$(echo "$tcp_stats" | grep "06" | awk '{sum+=$1} END {print sum+0}')
        close_wait=$(echo "$tcp_stats" | grep "08" | awk '{sum+=$1} END {print sum+0}')
    fi

    output_result "TCP_ESTABLISHED" "$established"

    # TIME_WAIT状态判断
    if [ "$time_wait" -ge 5000 ]; then
        tw_status="严重"
    elif [ "$time_wait" -ge 500 ]; then
        tw_status="警告"
    else
        tw_status="正常"
    fi

    output_result "TCP_TIME_WAIT" "$time_wait"
    output_result "TCP_TIME_WAIT_STATUS" "$tw_status"

    if [ "$tw_status" != "正常" ]; then
        echo "ERROR:TIME_WAIT连接过多: ${time_wait}"
    fi

    # CLOSE_WAIT状态判断
    if [ "$close_wait" -ge 500 ]; then
        cw_status="严重"
    elif [ "$close_wait" -ge 100 ]; then
        cw_status="警告"
    else
        cw_status="正常"
    fi

    output_result "TCP_CLOSE_WAIT" "$close_wait"
    output_result "TCP_CLOSE_WAIT_STATUS" "$cw_status"

    if [ "$cw_status" != "正常" ]; then
        echo "ERROR:CLOSE_WAIT连接过多: ${close_wait}"
    fi
}

# 检测网络接口状态
check_network_interfaces() {
    local up_count=0
    local total_count=0

    # 使用 ip 命令获取网络接口状态
    if command -v ip &> /dev/null; then
        up_count=$(ip link show 2>/dev/null | grep -c "state UP" || echo "0")
        total_count=$(ip link show 2>/dev/null | grep -c "^[0-9]" || echo "0")
    elif [ -f /proc/net/dev ]; then
        # 备用方案：从 /proc/net/dev 统计
        total_count=$(tail -n +3 /proc/net/dev | wc -l)
    fi

    output_result "NET_INTERFACE_UP" "$up_count"
    output_result "NET_INTERFACE_TOTAL" "$total_count"

    if [ "$up_count" -eq 0 ]; then
        output_result "NET_INTERFACE_STATUS" "严重"
        echo "ERROR:没有活跃的网络接口"
    else
        output_result "NET_INTERFACE_STATUS" "正常"
    fi
}

# 检测关键端口连接数
check_port_connections() {
    local ports=("8306:MySQL" "6379:Redis" "1883:EMQX_MQTT" "8883:EMQX_SSL" "3306:MySQL_Default" "80:HTTP" "443:HTTPS")

    for port_info in "${ports[@]}"; do
        local port=$(echo "$port_info" | cut -d: -f1)
        local name=$(echo "$port_info" | cut -d: -f2)

        local conn_count=0

        # 使用 ss 或 netstat 统计端口连接数
        if command -v ss &> /dev/null; then
            conn_count=$(ss -tnp 2>/dev/null | grep ":$port " | grep ESTAB | wc -l)
        elif command -v netstat &> /dev/null; then
            conn_count=$(netstat -tn 2>/dev/null | grep ":$port " | grep ESTABLISHED | wc -l)
        fi

        local key_name="PORT_${name}"
        output_result "${key_name}_CONNECTIONS" "$conn_count"
    done
}

# 检测网络错误统计
check_network_errors() {
    local has_errors=0

    # 使用 ip 命令获取网络错误统计
    if command -v ip &> /dev/null; then
        local error_output
        error_output=$(ip -s link show 2>/dev/null | grep -E "errors|dropped")

        if [ -n "$error_output" ]; then
            # 检查是否有错误
            if echo "$error_output" | grep -q "[1-9]"; then
                has_errors=1
            fi
        fi
    fi

    if [ "$has_errors" -eq 1 ]; then
        output_result "NET_ERRORS" "存在"
        output_result "NET_ERRORS_STATUS" "警告"
    else
        output_result "NET_ERRORS" "无"
        output_result "NET_ERRORS_STATUS" "正常"
    fi
}

# 检测网络流量统计
check_network_traffic() {
    # 从 /proc/net/dev 获取网络流量
    if [ -f /proc/net/dev ]; then
        # 获取主要网络接口的流量统计
        local traffic_info=$(tail -n +3 /proc/net/dev | head -5)

        if [ -n "$traffic_info" ]; then
            output_result "NET_TRAFFIC" "已获取"
        else
            output_result "NET_TRAFFIC" "获取失败"
        fi
    fi
}

# 检测DNS解析
check_dns_resolution() {
    local dns_status="正常"
    local test_domain="www.baidu.com"

    if command -v nslookup &> /dev/null; then
        if ! nslookup "$test_domain" &> /dev/null; then
            dns_status="警告"
        fi
    elif command -v host &> /dev/null; then
        if ! host "$test_domain" &> /dev/null; then
            dns_status="警告"
        fi
    elif command -v getent &> /dev/null; then
        if ! getent hosts "$test_domain" &> /dev/null; then
            dns_status="警告"
        fi
    fi

    output_result "DNS_RESOLUTION" "$dns_status"

    if [ "$dns_status" != "正常" ]; then
        echo "ERROR:DNS解析可能存在问题"
    fi
}

# 检测网络配置
check_network_config() {
    local hostname gateway

    # 获取主机名
    hostname=$(hostname -f 2>/dev/null || hostname)
    output_result "NET_HOSTNAME" "$hostname"

    # 获取默认网关
    if command -v ip &> /dev/null; then
        gateway=$(ip route | grep default | awk '{print $3}' | head -1)
    elif command -v route &> /dev/null; then
        gateway=$(route -n | grep "^0.0.0.0" | awk '{print $2}' | head -1)
    fi

    if [ -n "$gateway" ]; then
        output_result "NET_GATEWAY" "$gateway"
        output_result "NET_GATEWAY_STATUS" "正常"
    else
        output_result "NET_GATEWAY" "未配置"
        output_result "NET_GATEWAY_STATUS" "警告"
    fi
}

# 检测TCP参数配置
check_tcp_params() {
    # 检查关键TCP参数
    local tcp_tw_reuse=""
    local tcp_tw_recycle=""
    local tcp_fin_timeout=""

    if [ -f /proc/sys/net/ipv4/tcp_tw_reuse ]; then
        tcp_tw_reuse=$(cat /proc/sys/net/ipv4/tcp_tw_reuse 2>/dev/null)
    fi
    if [ -f /proc/sys/net/ipv4/tcp_tw_recycle ]; then
        tcp_tw_recycle=$(cat /proc/sys/net/ipv4/tcp_tw_recycle 2>/dev/null)
    fi
    if [ -f /proc/sys/net/ipv4/tcp_fin_timeout ]; then
        tcp_fin_timeout=$(cat /proc/sys/net/ipv4/tcp_fin_timeout 2>/dev/null)
    fi

    [ -n "$tcp_tw_reuse" ] && output_result "TCP_TW_REUSE" "$tcp_tw_reuse"
    [ -n "$tcp_tw_recycle" ] && output_result "TCP_TW_RECYCLE" "$tcp_tw_recycle"
    [ -n "$tcp_fin_timeout" ] && output_result "TCP_FIN_TIMEOUT_PARAM" "$tcp_fin_timeout"
}

# 检测TCP扩展统计
check_tcp_extended_stats() {
    if [ -f /proc/net/snmp ]; then
        # 获取TCP扩展统计
        local tcp_stats=""
        tcp_stats=$(cat /proc/net/snmp 2>/dev/null | grep "^Tcp:" | head -1)
        if [ -n "$tcp_stats" ]; then
            output_result "TCP_EXT_STATS" "$(echo "$tcp_stats" | cut -c1-200)"  # 截取前200字符
        fi
    fi
}

# 检测ARP表
check_arp_table() {
    local arp_count=""
    local arp_entries=""

    if command -v ip &> /dev/null; then
        arp_entries=$(ip neigh show 2>/dev/null | grep -v "FAILED" | head -10 | tr '\n' ',' | sed 's/,$//')
        arp_count=$(ip neigh show 2>/dev/null | grep -v "FAILED" | wc -l)
    fi

    [ -n "$arp_entries" ] && output_result "ARP_ENTRIES" "$arp_entries"
    [ -n "$arp_count" ] && output_result "ARP_COUNT" "$arp_count"
}

# 检测路由表
check_routing_table() {
    if command -v ip &> /dev/null; then
        local route_count=""
        route_count=$(ip route show 2>/dev/null | wc -l)
        output_result "ROUTES_COUNT" "$route_count"
    fi
}

# 检测Socket统计
check_socket_stats() {
    if [ -f /proc/net/sockstat ]; then
        local sockstat
        sockstat=$(cat /proc/net/sockstat 2>/dev/null | tr '\n' ',' | sed 's/,$//')
        if [ -n "$sockstat" ]; then
            output_result "SOCKET_STATS" "$sockstat"
        fi
    fi
}

# 检测网络带宽统计详情
check_network_bandwidth() {
    if [ -f /proc/net/dev ]; then
        # 获取主要网络接口的带宽统计
        local bandwidth_info=""
        bandwidth_info=$(tail -n +3 /proc/net/dev | head -3 | awk '{print $1":"$2":"$10}' | tr '\n' ',' | sed 's/,$//')

        if [ -n "$bandwidth_info" ]; then
            output_result "NET_BANDWIDTH_DETAIL" "$bandwidth_info"
        fi
    fi
}

# 检测监听队列积压
check_listen_queue() {
    if command -v ss &> /dev/null; then
        # 检查监听队列积压情况
        local queue_full=""
        queue_full=$(ss -lnt 2>/dev/null | awk '{print $6}' | grep -v "0" | head -5)

        if [ -n "$queue_full" ]; then
            output_result "LISTEN_QUEUE_BACKLOG" "$queue_full"
        else
            output_result "LISTEN_QUEUE_BACKLOG" "正常"
        fi
    else
        output_result "LISTEN_QUEUE_BACKLOG" "ss不可用"
    fi
}

# 检测网关连通性
check_gateway_connectivity() {
    local gateway=""
    local ping_status="未测试"

    # 获取默认网关
    if command -v ip &> /dev/null; then
        gateway=$(ip route | grep default | awk '{print $3}' | head -1)
    elif command -v route &> /dev/null; then
        gateway=$(route -n | grep "^0.0.0.0" | awk '{print $2}' | head -1)
    fi

    if [ -n "$gateway" ] && command -v ping &> /dev/null; then
        # ping网关3次，每次超时1秒
        if ping -c 3 -W 1 "$gateway" &>/dev/null; then
            ping_status="正常"
        else
            ping_status="异常"
        fi
    fi

    output_result "GATEWAY_PING_STATUS" "$ping_status"
}

# 检测容器间网络连通性
check_container_network() {
    # 检查Docker容器间网络连通性
    if command -v docker &> /dev/null; then
        # ping uemqx容器
        local uemqx_ip=""
        uemqx_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' uemqx 2>/dev/null | head -1)

        if [ -n "$uemqx_ip" ] && command -v ping &> /dev/null; then
            if ping -c 1 -W 1 "$uemqx_ip" &>/dev/null; then
                output_result "CONTAINER_NETWORK_TO_EMQX" "正常"
            else
                output_result "CONTAINER_NETWORK_TO_EMQX" "异常"
            fi
        fi
    fi
}

# ==================== 主检测流程 ====================
main() {
    log_info "开始网络连接检测..."

    # 执行各项检测
    check_tcp_connections
    check_network_interfaces
    check_port_connections
    check_network_errors
    check_network_traffic
    check_dns_resolution
    check_network_config
    check_tcp_params
    check_tcp_extended_stats
    check_arp_table
    check_routing_table
    check_socket_stats
    check_network_bandwidth
    check_listen_queue
    check_gateway_connectivity
    check_container_network

    log_info "网络连接检测完成"
}

# 执行主函数
main
