/*
 * 模块名称：Network Socket Core
 * 模块功能：BSD Socket API 核心实现，包含 Socket 管理、状态机、消息队列（线程安全）、事件处理、数据收发等功能，底层调用 CH395F 驱动
 * 适用平台：STM32F407ZGTx + CH395F 以太网芯片
 * 作者：王建锋
 * 创建日期：2026-07-18
 * 修改记录：
 *     2026-07-18  王建锋  创建初始版本
 *     2026-07-19  王建锋  添加消息队列线程安全机制，替换 xQueueCreate 为 CubeMX osMessageQueue
 */

#include <string.h>
#include <stdio.h>

#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"

#include "net_socket.h"
#include "ch395f.h"
#include "main.h"

/*
 * 调试输出配置
 */
#define DBG_TAG "[NET]"
#include "dbg_log.h"

/*
 * 私有宏定义区
 */
#define NET_PHY_CHECK_INTERVAL_MS   5000U  /* PHY 状态定期检查间隔（ms） */

/*
 * 全局变量定义区 - 尽量避免使用全局变量
 */
static net_sock_t s_net_socks[NET_MAX_SOCKETS];   /* Socket 控制块数组 */
static int s_net_errno = 0;                       /* 最后错误码 */
static uint8_t s_net_initialized = 0;             /* 初始化标志 */
static uint8_t s_local_ip[4];                     /* 本机 IP 缓存（网络序，net_getsockname 用） */
static uint16_t s_dynamic_port = 49152;            /* 动态端口分配起始值 */

/*
 * 消息队列 - 线程安全核心
 * 外部任务通过 net_send/net_recv/net_close 等 API 将请求放入队列，
 * netTask 调用 net_process_messages() 串行处理所有 CH395F 操作
 * 由 CubeMX 在 MX_FREERTOS_Init()（osKernelInitialize 之后）中创建
 */
extern osMessageQueueId_t netMsgQueueHandle;         /* CubeMX 生成的消息队列句柄 */



/*
 * 私有函数声明区
 */

static int alloc_socket(void);
static void handle_connect_event(net_sock_t *p_sock);
static void handle_disconnect_event(net_sock_t *p_sock);
static void handle_recv_event(net_sock_t *p_sock);
static void handle_send_event(net_sock_t *p_sock);
static void handle_timeout_event(net_sock_t *p_sock);
static void fire_event(net_sock_t *p_sock, net_event_t event);
static void parse_ip_string(const char *str, uint8_t *ip_arr);
static int net_send_locked(net_sock_t *p_sock, const void *buf, int len);
static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags);
static int net_close_locked(net_sock_t *p_sock);
static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen);

/*
 * 函数功能：网络子系统初始化（配置 CH395F + 启用多连接模式）
 * 入口参数：ip       - IP 地址字符串 "192.168.1.100"，NULL 使用 DHCP 自动获取  const char *
 *           mask     - 子网掩码字符串 "255.255.255.0"，NULL 使用默认值          const char *
 *           gateway  - 网关地址字符串 "192.168.1.1"，NULL 使用默认值            const char *
 * 返回值：0 - 初始化成功  int
 *         -1 - 初始化失败（芯片检测/复位/协议栈初始化失败）                      int
 * 限定条件：SPI2 已正确初始化；netTask 尚未启动
 * 函数说明：1. 检查 CH395F 芯片是否存在并复位
 *           2. 启用 TCP Server 多连接模式（bit1=1），设置 TCP MSS、重传参数、KeepAlive 参数
 *           3. 配置 IP/网关/子网掩码，或启用 DHCP
 *           4. 初始化 CH395F 协议栈并使能 PING 响应
 */
int net_init(const char *ip, const char *mask, const char *gateway) {
    ch395f_status_t ret;

    DBG_INFO("net_init: start");

    /* 清零 Socket 控制块 */
    memset(s_net_socks, 0, sizeof(s_net_socks));
    s_net_errno = 0;
    s_net_initialized = 0;

    DBG_INFO("net_init: queue=%p", (void *)netMsgQueueHandle);

    DBG_INFO("net_init: check_exist...");
    /* 检查 CH395F 芯片 */
    if (ch395f_check_exist() != CH395F_STATUS_OK) {
        DBG_ERROR("net_init: ch395f_check_exist FAILED");
        s_net_errno = NET_ERR;
        return -1;
    }
    DBG_INFO("net_init: reset...");
    /* 复位芯片 */
    ch395f_reset();
    DBG_INFO("net_init: set_fun_para...");

    /* 启用单连接模式 + 手动关闭 Socket（bit3=1, bit1=0）
     * bit3=1: DISCONNECT/TIMEOUT 时不自动清空缓冲区，由软件排空数据后手动关闭 */
    ch395f_set_fun_para(0x08);
    DBG_INFO("net_init: set_tcp_mss...");

    /* 设置 TCP MSS */
    ch395f_set_tcp_mss(1460);

    /* 设置 TCP 重传参数（必须在 INIT_CH395 之前调用*/
    ch395f_set_retrans_count(8);        /* 重传 8 次*/
    ch395f_set_retrans_period(500);     /* 每次间隔 500ms，总计 4s 重传窗口 */

    /* 设置 TCP KeepAlive 参数（必须在 INIT_CH395 之前，单位 ms，必须为 500 的倍数，IDLE > INTVL�?*/
    ch395f_set_keepalive_idle(60000);    /* 空闲 60 秒后开始探测*/
    ch395f_set_keepalive_intvl(5000);    /* 5 秒探测一次*/
    ch395f_set_keepalive_cnt(3);         /* 最多探 3 次*/

    /* 设置网络参数（必须在 INIT_CH395 之前调用 */
    if (NULL != ip) {
        uint8_t ip_arr[4];
        uint8_t mask_arr[4];
        uint8_t gw_arr[4];

        parse_ip_string(ip, ip_arr);
        parse_ip_string(mask, mask_arr);
        parse_ip_string(gateway, gw_arr);

        memcpy(s_local_ip, ip_arr, 4);

        ch395f_set_ip_addr(ip_arr);
        ch395f_set_gwip_addr(gw_arr);
        ch395f_set_mask_addr(mask_arr);
    } else {
        /* 启用 DHCP */
        ch395f_set_dhcp(1);
    }

    /* 初始化 CH395F 协议栈（先不配置 buffer，测试默认值是否工作） */
    ret = ch395f_init();
    if (ret != CH395F_STATUS_OK) {
        s_net_errno = NET_ERR;
        return -1;
    }

    /* 使能 PING 响应 */
    ch395f_ping_enable(1);

    s_net_initialized = 1;

    return 0;
}

/*
 * 函数功能：轮询 CH395F 中断状态，更新 Socket 连接状态并处理事件
 * 返回值：本次轮询中发生事件的 Socket 数量  int >= 0
 * 限定条件：s_net_initialized == 1；必须在 netTask 上下文中调用
 * 函数说明：1. GPIO 轮询 CH395F INT# 引脚电平（低电平有效），无需 EXTI 中断
 *           2. 读取 GET_GLOB_INT_STATUS_ALL（2 字节版）获取所有 Socket 的中断状态
 *           3. 处理连接/断开/数据接收/发送完成/超时等事件，更新 Socket 状态机
 *           4. RECV 中断为电平触发，每次 net_poll() 只处理一批中断，避免主循环饿死
 */
int net_poll(void) {
    /* 本次轮询累计发生的事件数（连接/断开/接收/发送/超时各计 1） */
    int event_count = 0;
    /* 全局中断状态寄存器值（CH395F GET_GLOB_INT_STATUS_ALL 为 16 位） */
    uint16_t int_status;

    /* 防御性检查：尚未初始化则不处理任何中断，直接返回 */
    if (!s_net_initialized) {
        return 0;
    }

    /*
     * 采用 do-while(0) 实现“单次批处理”：
     * 本函数每被调用一次只读取并处理一批中断，处理完立即返回，不循环等待，
     * 避免 RECV 电平中断导致主循环（如 echo）饿死。
     * 循环体内部用 break 提前退出（INT# 无效或无中断时）。
     */
    do
    {
        /*
         * GPIO 轮询 INT# 引脚：低电平有效（有中断待处理）。
         * 采用 GPIO 轮询而非 EXTI 边沿中断，仅当 INT# 为低电平时才读取状态，减少不必要 SPI 事务。
         * 若 INT# 为高（无效），直接退出本次轮询。
         */
        if (HAL_GPIO_ReadPin(CH395_INT_GPIO_Port, CH395_INT_Pin) == GPIO_PIN_SET) {
            break;
        }

        /* 读取全局中断状态（2 字节）：读操作本身会清除 CH395F 中断并使其拉高 INT#，
         * 若此后仍有新中断，CH395F 会再次拉低 INT#，由下一次 net_poll() 处理 */
        int_status = ch395f_get_glob_int_status_all();

        /* 无有效中断（读到的状态为 0），提前退出 */
        if (int_status == 0) {
            break;
        }

        /* 遍历所有 Socket，处理各自的中断 */
        for (int i = 0; i < NET_MAX_SOCKETS; i++) {
            /* 取本 Socket 控制块（直接用数组下标，无需 net_get_sock 的越界判断） */
            net_sock_t *p_sock = &s_net_socks[i];

            /* 全局中断状态 bit4~bit11 分别对应 socket0~socket7 的中断标志，
             * 对应位为 0 说明该 Socket 无中断，跳过以节省时间 */
            if (!(int_status & (1U << (i + 4)))) {
                continue;
            }

            /* 读取该 Socket 的中断状态寄存器（SINT） */
            uint8_t sock_int = ch395f_get_sock_int_status(i);

            /* 连接建立事件：交给状态机处理（监听态/客户端/数据 Socket 分别处理） */
            if (sock_int & CH395F_SINT_STAT_CONNECT) {
                handle_connect_event(p_sock);
                event_count++;
            }

            /* 连接断开事件：更新状态机并触发断开回调 */
            if (sock_int & CH395F_SINT_STAT_DISCONNECT) {
                handle_disconnect_event(p_sock);
                event_count++;
            }

            /* 接收数据就绪事件：仅通知上层，实际数据由 net_recv_locked 读出（避免重复读 recv_len） */
            if (sock_int & CH395F_SINT_STAT_RECV_OK) {
                handle_recv_event(p_sock);
                event_count++;
            }

            /* 发送完成事件：通知上层发送缓冲已空，可继续发送 */
            if (sock_int & CH395F_SINT_STAT_SEND_OK) {
                handle_send_event(p_sock);
                event_count++;
            }

            /* 发送缓冲区空闲：置 send_ready 标志，唤醒等待发送的逻辑 */
            if (sock_int & CH395F_SINT_STAT_SENBUF_FREE) {
                p_sock->send_ready = 1;
            }

            /* 超时事件：连接超时或收发超时，更新状态机 */
            if (sock_int & CH395F_SINT_STAT_SOCK_TIMEOUT) {
                handle_timeout_event(p_sock);
                event_count++;
            }
        }

        /*
         * 处理完本批中断后退出 do-while(0)：
         * CH395F 的 RECV 中断为电平触发，只要接收缓冲区仍有数据就保持 INT# 低电平，
         * 若此处继续循环会反复处理 RECV 中断，导致主循环中的应用代码（如 echo 回显）得不到执行。
         * 因此每次 net_poll() 只处理“一批”，剩余数据由主循环/recv 逻辑在后续轮询中读取。
         */
    } while (0);

    /* 返回本次累计发生的事件数量（0 表示无事件） */
    return event_count;
}

/*
 * 函数功能：处理消息队列中的请求
 * 限定条件：必须在 netTask 上下文中调用（独占 CH395F 和 s_net_socks 访问权）
 * 函数说明：每次调用处理一条消息。处理 send/recv 时内部会调用 net_poll()
 *          等待操作完成。处理完毕后通知调用方任务。
 */
void net_process_messages(void) {
    net_msg_t msg;

    if (NULL == netMsgQueueHandle) {
        return;
    }

    while (osMessageQueueGet(netMsgQueueHandle, &msg, NULL, 0) == osOK) {
        switch (msg.type) {
        case NET_MSG_SEND: {
            net_sock_t *p_sock = net_get_sock(msg.sockfd);
            if (NULL == p_sock || p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
                msg.result = -1;
            } else {
                msg.result = net_send_locked(p_sock, msg.buf, msg.len);
            }
            break;
        }
        case NET_MSG_RECV: {
            net_sock_t *p_sock = net_get_sock(msg.sockfd);
            if (NULL == p_sock) {
                msg.result = -1;
            } else {
                msg.result = net_recv_locked(p_sock, msg.buf, msg.len, msg.flags);
            }
            break;
        }
        case NET_MSG_CLOSE: {
            net_sock_t *p_sock = net_get_sock(msg.sockfd);
            if (NULL == p_sock) {
                msg.result = -1;
            } else {
                msg.result = net_close_locked(p_sock);
            }
            break;
        }
        case NET_MSG_CONNECT: {
            msg.result = net_connect(msg.sockfd,
                                     (const struct net_sockaddr *)&msg.addr,
                                     msg.addrlen);
            break;
        }
        case NET_MSG_LISTEN: {
            msg.result = net_listen_locked(msg.sockfd);
            break;
        }
        case NET_MSG_ACCEPT: {
            struct net_sockaddr *p_addr = (struct net_sockaddr *)msg.buf;
            int addrlen = msg.len;
            int *p_addrlen = (NULL != p_addr && addrlen > 0) ? &addrlen : NULL;
            msg.result = net_accept_locked(msg.sockfd, p_addr, p_addrlen);
            break;
        }
        default:
            msg.result = -1;
            break;
        }

        xTaskNotify(msg.caller, (uint32_t)msg.result, eSetValueWithOverwrite);
    }
}

/*
 * 函数功能：创建 Socket，分配空闲 Socket 控制块并初始化状态
 * 入口参数：domain   - 地址族，仅支持 NET_AF_INET                              int
 *           type     - SOCK_STREAM(TCP) 或 SOCK_DGRAM(UDP)                      int
 *           protocol - 通常为 0                                                int
 * 返回值：Socket 描述符 (0~7)，失败返回 -1                                     int
 * 限定条件：net_init() 已调用成功；s_net_initialized == 1
 * 函数说明：自动分配一个空闲的 Socket 控制块（in_use=0），初始化为 CREATED 状态
 */
int net_socket(int domain, int type, int protocol) {
    int sockfd;
    net_sock_t *p_sock;

    /* 参数检查*/
    if (domain != NET_AF_INET) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    /* 分配空闲 Socket */
    sockfd = alloc_socket();
    if (sockfd < 0) {
        s_net_errno = NET_ERR_NOMEM;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    p_sock->ch395_sock = (uint8_t)sockfd;
    p_sock->type = (uint8_t)type;
    p_sock->state = NET_SOCK_STATE_CREATED;
    p_sock->in_use = 1;
    p_sock->send_ready = 1;

    return sockfd;
}

/*
 * 函数功能：绑定 Socket 到本地 IP 地址和端口号
 * 入口参数：sockfd   - Socket 描述符 (0~7)                                       int
 *           addr     - 本地地址结构体指针                                        const struct net_sockaddr *
 *           addrlen  - 地址结构体长度                                            int >= sizeof(struct net_sockaddr_in)
 * 返回值：0 - 绑定成功                                                          int
 *         -1 - 绑定失败（参数无效、Socket 未使用等）                             int
 * 限定条件：Socket 已通过 net_socket() 创建且未被其他操作占用；net_init() 已调用
 * 函数说明：1. TCP Socket 仅记录本地端口，进入 BOUND 状态等待 listen
 *           2. UDP Socket（SOCK_DGRAM）立即打开 CH395F Socket 并配置为 Server 模式
 *              - Socket 4~7 需显式分配收发缓冲区
 */
int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
    net_sock_t *p_sock;
    const struct net_sockaddr_in *p_addr_in;

    /* 参数检�?*/
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == addr || addrlen < (int)sizeof(struct net_sockaddr_in)) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    p_addr_in = (const struct net_sockaddr_in *)addr;

    /* 设置本地端口（转换为主机序） */
    p_sock->local_port = net_ntohs(p_addr_in->sin_port);

    /* port=0 时自动分配动态端口（49152~65535） */
    if (p_sock->local_port == 0) {
        p_sock->local_port = s_dynamic_port;
        s_dynamic_port++;
        if (s_dynamic_port > 65535) {
            s_dynamic_port = 49152;
        }
    }

    /* UDP (SOCK_DGRAM): 直接在此打开 CH395F Socket */
    if (p_sock->type == NET_SOCK_DGRAM) {
        uint8_t status;

        /* Socket 4-7 默认无收发缓冲，需显式分配 */
        if (sockfd >= 4) {
            ch395f_set_send_buf((uint8_t)sockfd, 28, 2);
            ch395f_set_recv_buf((uint8_t)sockfd, 30, 2);
        }

        ch395f_set_proto_type((uint8_t)sockfd, CH395F_PROTO_TYPE_UDP);
        ch395f_set_sour_port((uint8_t)sockfd, p_sock->local_port);

        /* DesIP=0xFFFFFFFF  UDP Server 模式（接受任意来源） */
        {
            uint8_t broadcast[4] = {0xFF, 0xFF, 0xFF, 0xFF};
            ch395f_set_des_ip((uint8_t)sockfd, broadcast);
        }
        ch395f_set_des_port((uint8_t)sockfd, 0);

        status = ch395f_open_socket((uint8_t)sockfd);
    if (status != CH395F_ERR_SUCCESS) {
        DBG_ERROR("sock%d open_socket FAIL: status=0x%02X (expected 0x00)", sockfd, status);
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

        p_sock->state = NET_SOCK_STATE_UDP_OPEN;
    } else {
        p_sock->state = NET_SOCK_STATE_BOUND;
    }

    return 0;
}

/*
 * 函数功能：启动 TCP Server 监听（内部版本，必须在 netTask 上下文调用）
 * 入口参数：sockfd   - Socket 描述符 (0~7)                 int
 * 返回值：0 - 成功，-1 - 失败                              int
 * 限定条件：sockfd 已绑定且为 TCP；netTask 上下文
 */
int net_listen_locked(int sockfd) {
    /* 取监听 Socket 控制块（直接下标访问，sockfd 已在上层 net_listen 校验过范围） */
    net_sock_t *p_sock = &s_net_socks[sockfd];
    /* CH395F 打开 Socket 的返回状态 */
    uint8_t status;

    /* 合法性检查：Socket 必须已创建且为 TCP 流类型 */
    if (!p_sock->in_use || p_sock->type != NET_SOCK_STREAM) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    /* 状态检查：仅允许在 BOUND（已 bind）或 CREATED（未 bind 直接用随机端口）状态下启动监听 */
    if (p_sock->state != NET_SOCK_STATE_BOUND &&
        p_sock->state != NET_SOCK_STATE_CREATED) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    /*
     * 本实现仅支持单连接：监听 Socket 自身即为数据通道，复用 CH395F 默认收发缓冲
     * （Socket 0~3 默认缓冲互不重叠），不再为数据 Socket 额外分配。
     */
    ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
    ch395f_set_sour_port(sockfd, p_sock->local_port);

    /* CH395F 关闭 Socket 后需延时才能重新打开（Trap 09），故失败重试最多 3 次 */
    for (int open_try = 0; open_try < 3; open_try++) {
        status = ch395f_open_socket(sockfd);
        if (status == CH395F_ERR_SUCCESS) {
            break;  /* 打开成功，退出重试 */
        }
        ch395f_close_socket(sockfd);  /* 打开失败先关闭，再延时后重试 */
        HAL_Delay(500);
    }
    /* 3 次仍失败，返回错误 */
    if (status != CH395F_ERR_SUCCESS) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }
    /* 下发 TCP LISTEN 命令，进入监听状态 */
    status = ch395f_tcp_listen(sockfd);
    if (status != CH395F_ERR_SUCCESS) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    /* 监听 Socket 进入 LISTENING 态 */
    p_sock->state = NET_SOCK_STATE_LISTENING;
    /* 单连接：CONNECT 中断直接作用于本 Socket 自身 */

    /*
     * 启动监听前清空各 Socket 及全局中断状态寄存器（读即清除），
     * 避免历史残留/伪中断在监听刚开始时误触发连接或断开事件。
     */
    for (int j = 0; j < NET_MAX_SOCKETS; j++) {
        (void)ch395f_get_sock_int_status((uint8_t)j);
    }
    (void)ch395f_get_glob_int_status_all();

    return 0;
}

/*
 * 函数功能：启动 TCP Server 监听（线程安全版本，通过消息队列委托给 netTask）
 * 入口参数：sockfd   - Socket 描述符                                              int
 * 返回值：0 - 成功，-1 - 失败                                                   int
 * 限定条件：net_init() + MX_FREERTOS_Init() 已执行；必须在任务上下文中调用
 * 函数说明：通过消息队列委托给 netTask，确保 SPI 串行化
 */
int net_listen(int sockfd) {
    net_msg_t msg;

    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == netMsgQueueHandle) {
        s_net_errno = NET_ERR;
        return -1;
    }

    msg.type = NET_MSG_LISTEN;
    msg.sockfd = sockfd;
    msg.caller = xTaskGetCurrentTaskHandle();
    msg.result = -1;

    if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    {
        uint32_t s_notified;
        xTaskNotifyWait(0, 0, &s_notified, portMAX_DELAY);
        msg.result = (int)s_notified;
    }

    if (msg.result < 0) {
        s_net_errno = NET_ERR;
    }
    return msg.result;
}

/*
 * 函数功能：TCP Server 接受新连接（内部版本，必须在 netTask 上下文调用）
 * 入口参数：sockfd   - 监听 Socket 描述符                                       int
 *           addr     - 输出：客户端地址结构体指针                              struct net_sockaddr *（可为 NULL）
 *           addrlen  - 输入输出：地址结构体长度                                int *（可为 NULL）
 * 返回值：新连接的 Socket 描述符，失败返回 -1                                  int
 * 限定条件：Socket 处于 LISTENING 状态
 * 函数说明：单连接：监听 Socket 自身在 CONNECT 后已转为 ESTABLISHED
 */
static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen) {
    net_sock_t *p_listen_sock;

    p_listen_sock = &s_net_socks[sockfd];
    if (!p_listen_sock->in_use) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    net_poll();

    /* 单连接：本 Socket 自身在 CONNECT 后已转为 ESTABLISHED，
     * 只有处于 ESTABLISHED 才表示有可接受的连接；否则尚无连接 */
    if (p_listen_sock->state != NET_SOCK_STATE_ESTABLISHED) {
        s_net_errno = NET_ERR_WOULDBLOCK;
        return -1;
    }

    /* 填充对端地址（若调用方需要） */
    if (NULL != addr && NULL != addrlen) {
        struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)addr;
        p_addr_in->sin_family = NET_AF_INET;
        p_addr_in->sin_port = net_htons(p_listen_sock->remote_port);
        p_addr_in->sin_addr.s_addr = p_listen_sock->remote_ip;
        *addrlen = sizeof(struct net_sockaddr_in);
    }

    /* 单连接：返回的就是监听 Socket 自身（已转为数据通道） */
    return sockfd;
}

/*
 * 函数功能：TCP Server 接受新连接（线程安全版本，通过消息队列委托给 netTask）
 * 入口参数：sockfd   - 监听 Socket 描述符                                       int
 *           addr     - 输出：客户端地址结构体指针                              struct net_sockaddr *（可为 NULL）
 *           addrlen  - 输入输出：地址结构体长度                                int *（可为 NULL）
 * 返回值：新连接的 Socket 描述符，失败返回 -1                                  int
 * 限定条件：Socket 处于 LISTENING 状态；net_init() + MX_FREERTOS_Init() 已执行；非 netTask 上下文
 * 函数说明：将接受请求放入消息队列，阻塞等待 netTask 处理完毕
 */
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
    net_msg_t msg;

    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == netMsgQueueHandle) {
        s_net_errno = NET_ERR;
        return -1;
    }

    msg.type = NET_MSG_ACCEPT;
    msg.sockfd = sockfd;
    msg.buf = (void *)addr;
    msg.len = (NULL != addrlen) ? *addrlen : 0;
    msg.caller = xTaskGetCurrentTaskHandle();
    msg.result = -1;

    if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    {
        uint32_t s_notified;
        xTaskNotifyWait(0, 0, &s_notified, portMAX_DELAY);
        msg.result = (int)s_notified;
    }

    if (NULL != addrlen &&NULL != addr) {
        *addrlen = sizeof(struct net_sockaddr_in);
    }

    if (msg.result < 0) {
        s_net_errno = NET_ERR;
    }
    return msg.result;
}

/*
 * 函数功能：TCP Client 发起与服务器的连接
 * 入口参数：sockfd   - Socket 描述符 (0~7)，必须为已创建的 TCP Socket          int
 *           addr     - 服务器地址结构体指针                                    const struct net_sockaddr *
 *           addrlen  - 地址结构体长度                                          int >= sizeof(struct net_sockaddr_in)
 * 返回值：0 - 连接请求发送成功（异步，需等待 ESTABLISHED）                     int
 *         -1 - 连接失败（参数无效、状态错误等）                               int
 * 限定条件：Socket 已通过 net_socket() 创建且 type == NET_SOCK_STREAM；尚未连接
 * 函数说明：设置目标 IP 和端口后打开 CH395F Socket，进入 CONNECTING 状态。连接建立需等待
 *          net_poll() 检测到 CONNECT 事件并将状态更新为 ESTABLISHED
 */
int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen) {
    net_sock_t *p_sock;
    const struct net_sockaddr_in *p_addr_in;
    uint8_t status;

    /* 参数检�?*/
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use || p_sock->type != NET_SOCK_STREAM) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    if (NULL == addr || addrlen < (int)sizeof(struct net_sockaddr_in)) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    p_addr_in = (const struct net_sockaddr_in *)addr;

    /* 保存远端地址 */
    p_sock->remote_ip = p_addr_in->sin_addr.s_addr;
    p_sock->remote_port = net_ntohs(p_addr_in->sin_port);

    /* 转换 IP 为数组格式（低字节在前） */
    p_sock->remote_ip_arr[0] = (uint8_t)(p_sock->remote_ip);
    p_sock->remote_ip_arr[1] = (uint8_t)(p_sock->remote_ip >> 8);
    p_sock->remote_ip_arr[2] = (uint8_t)(p_sock->remote_ip >> 16);
    p_sock->remote_ip_arr[3] = (uint8_t)(p_sock->remote_ip >> 24);

    /* 配置 CH395F Socket */
    ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
    ch395f_set_sour_port(sockfd, p_sock->local_port);
    ch395f_set_des_ip(sockfd, p_sock->remote_ip_arr);
    ch395f_set_des_port(sockfd, p_sock->remote_port);
    status = ch395f_open_socket(sockfd);

    if (status != CH395F_ERR_SUCCESS) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    /* 发起 TCP 连接 */
    ch395f_tcp_connect(sockfd);
    p_sock->state = NET_SOCK_STATE_CONNECTING;

    return 0;
}

/*
 * SPI DMA 单次事务最大有效载荷（取 CH395F 驱动公开常量）
 */
#define NET_DMA_MAX_PAYLOAD           ((int)CH395F_SPI_DMA_MAX_PAYLOAD)

/*
 * 函数功能：发送数据（内部锁定版本，必须在 netTask 上下文调用）
 */
/*
 * 函数功能：发送数据（内部锁定版本，必须在 netTask 上下文调用）
 * 入口参数：p_sock - Socket 控制块指针                                  net_sock_t *
 *           buf    - 待发送数据缓冲区指针                               const void *
 *           len    - 数据长度                                           int    > 0
 * 出口参数：无
 * 返回值：实际发送字节数（>= 0）；-1 表示参数无效或 Socket 未连接      int
 * 限定条件：p_sock 非空；Socket 处于 ESTABLISHED 状态；netTask 上下文
 * 函数说明：1. 按 NET_DMA_MAX_PAYLOAD 分块写入 CH395F 发送缓冲区
 *           2. 发送前等待 send_ready 置位，超时返回已发送字节数
 *           3. 每写完一块等待 SEND_OK 中断（send_ready 清零后重新置位）
 */
static int net_send_locked(net_sock_t *p_sock, const void *buf, int len) {
    int sent = 0;
    uint32_t tick_start;
    int sockfd = (int)(p_sock - s_net_socks);

    if (NULL == buf || len <= 0) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    if (p_sock->state != NET_SOCK_STATE_ESTABLISHED) {
        s_net_errno = NET_ERR_NOTCONN;
        return -1;
    }

    tick_start = HAL_GetTick();

    while (sent < len) {
        int chunk = len - sent;
        if (chunk > NET_DMA_MAX_PAYLOAD) {
            chunk = NET_DMA_MAX_PAYLOAD;
        }

        if (!p_sock->send_ready) {
            if (NET_SEND_TIMEOUT_MS > 0 &&
                (HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
                s_net_errno = NET_ERR_TIMEDOUT;
                break;
            }
            net_poll();
            continue;
        }

        ch395f_write_send_buf(sockfd, (uint8_t *)buf + sent, (uint16_t)chunk);
        p_sock->send_ready = 0;
        sent += chunk;
        p_sock->send_bytes += (uint32_t)chunk;

        tick_start = HAL_GetTick();
        while (!p_sock->send_ready) {
            net_poll();
            if (NET_SEND_TIMEOUT_MS > 0 &&
                (HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
                break;
            }
        }
    }

    return sent;
}

/*
 * 函数功能：接收数据（内部锁定版本，必须在 netTask 上下文调用）
 */
/*
 * 函数功能：接收数据（内部锁定版本，必须在 netTask 上下文调用）
 * 入口参数：p_sock - Socket 控制块指针                                  net_sock_t *
 *           buf    - 接收缓冲区指针                                      void *
 *           len    - 缓冲区大小                                          int    > 0
 *           flags  - 标志位，NET_MSG_DONTWAIT 表示非阻塞                 int
 * 出口参数：buf    - 填充接收到的数据
 * 返回值：实际接收字节数（> 0）；0 表示对端关闭；-1 表示出错/超时/非阻塞无数据  int
 * 限定条件：p_sock 非空；netTask 上下文
 * 函数说明：1. 循环调用 net_poll() 检查接收长度，有数据即读出
 *           2. 非阻塞模式下无数据立即返回 -1（NET_ERR_WOULDBLOCK）
 *           3. CLOSED 状态尝试排空接收缓冲区残余数据（Trap 13：FIN 可能先于数据到达）
 */
static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags) {
    uint16_t recv_len;
    uint32_t tick_start;
    int sockfd = (int)(p_sock - s_net_socks);

    if (NULL == buf || len <= 0) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    tick_start = HAL_GetTick();

    while (1) {
        net_poll();

        recv_len = ch395f_get_recv_len(sockfd);
        if (recv_len > 0) {
            int read_len = (recv_len > (uint16_t)len) ? len : (int)recv_len;
            DBG_INFO("recv sock%d len=%d", sockfd, recv_len);
            ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
            p_sock->recv_bytes += (uint32_t)read_len;
            HAL_Delay(1);  /* 等待 CH395F 刷新 recv_len 寄存器 */
            return read_len;
        }

        if (flags & NET_MSG_DONTWAIT) {
            s_net_errno = NET_ERR_WOULDBLOCK;
            return -1;
        }

        if (NET_RECV_TIMEOUT_MS > 0 &&
            (HAL_GetTick() - tick_start) >= NET_RECV_TIMEOUT_MS) {
            s_net_errno = NET_ERR_TIMEDOUT;
            return -1;
        }

        if (p_sock->state == NET_SOCK_STATE_CLOSED) {
            /* 断开前尝试排空 CH395F 接收缓冲区（Trap 13：FIN 可能比数据先到） */
            uint16_t rem = ch395f_get_recv_len(sockfd);
            if (rem > 0) {
                int rd = (rem > (uint16_t)len) ? len : (int)rem;
                ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)rd);
                p_sock->recv_bytes += (uint32_t)rd;
                return rd;
            }
            return 0;
        }
    }
}

/*
 * 函数功能：关闭 socket（内部锁定版本，必须在 netTask 上下文调用）
 */
/*
 * 函数功能：关闭 Socket（内部锁定版本，必须在 netTask 上下文调用）
 * 入口参数：p_sock - Socket 控制块指针                                  net_sock_t *
 * 出口参数：无
 * 返回值：0 - 关闭成功                                                  int
 * 限定条件：p_sock 非空；netTask 上下文
 * 函数说明：1. 调用 ch395f_close_socket 关闭 CH395F 硬件 Socket
 *           2. 清空整个控制块（memset 0），释放该 Socket 资源
 */
static int net_close_locked(net_sock_t *p_sock) {
    int sockfd = (int)(p_sock - s_net_socks);

    ch395f_close_socket(sockfd);
    memset(p_sock, 0, sizeof(net_sock_t));

    return 0;
}

/*
 * 函数功能：发送数据（线程安全版本，通过消息队列委托给 netTask）
 * 入口参数：sockfd - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 *           buf    - 待发送数据缓冲区指针                                            const void *
 *           len    - 数据长度                                                        int > 0
 *           flags  - 标志位，通常为 0                                                int
 * 返回值：实际发送字节数                                                            int >= 0 || -1
 *         -1       - 发送失败（参数无效、队列满等）                                int
 * 限定条件：Socket 处于 ESTABLISHED 状态；net_init() + MX_FREERTOS_Init() 已执行；非 netTask 上下文
 * 函数说明：将发送请求放入消息队列，阻塞等待 netTask 处理完毕并返回结果。netTask 内请使用 net_send_sock()
 */
int net_send(int sockfd, const void *buf, int len, int flags) {
    (void)flags;
    net_msg_t msg;

    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == netMsgQueueHandle) {
        s_net_errno = NET_ERR;
        return -1;
    }

    msg.type = NET_MSG_SEND;
    msg.sockfd = sockfd;
    msg.buf = (void *)buf;
    msg.len = len;
    msg.flags = 0;
    msg.caller = xTaskGetCurrentTaskHandle();
    msg.result = -1;

    if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    {
        uint32_t s_notified;
        xTaskNotifyWait(0, 0, &s_notified, portMAX_DELAY);
        msg.result = (int)s_notified;
    }

    if (msg.result < 0) {
        s_net_errno = NET_ERR;
    }
    return msg.result;
}

/*
 * 函数功能：接收数据（线程安全版本，通过消息队列委托给 netTask）
 * 入口参数：sockfd - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 *           buf    - 接收缓冲区指针                                                  void *
 *           len    - 缓冲区大小                                                      int > 0
 *           flags  - 标志位，0=阻塞，NET_MSG_DONTWAIT=非阻塞                        int
 * 返回值：实际接收字节数                                                            int >= 0 || 0 || -1
 *         0        - 对端关闭连接                                                   int
 *         -1       - 接收失败（参数无效、队列满等）                               int
 * 限定条件：Socket 处于 ESTABLISHED 状态；net_init() + MX_FREERTOS_Init() 已执行；非 netTask 上下文
 * 函数说明：将接收请求放入消息队列，阻塞等待 netTask 处理完毕并返回结果。netTask 内请使用 net_recv_sock()
 */
int net_recv(int sockfd, void *buf, int len, int flags) {
    net_msg_t msg;

    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == netMsgQueueHandle) {
        s_net_errno = NET_ERR;
        return -1;
    }

    msg.type = NET_MSG_RECV;
    msg.sockfd = sockfd;
    msg.buf = buf;
    msg.len = len;
    msg.flags = flags;
    msg.caller = xTaskGetCurrentTaskHandle();
    msg.result = -1;

    if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    {
        uint32_t s_notified;
        xTaskNotifyWait(0, 0, &s_notified, portMAX_DELAY);
        msg.result = (int)s_notified;
    }

    if (msg.result < 0) {
        s_net_errno = NET_ERR;
    }
    return msg.result;
}

/*
 * 函数功能：关闭 Socket（线程安全版本，通过消息队列委托给 netTask）
 * 入口参数：sockfd - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 * 返回值：0 - 关闭成功                                                            int
 *         -1       - 关闭失败                                                     int
 * 限定条件：Socket 已创建且处于非 CLOSED 状态；net_init() + MX_FREERTOS_Init() 已执行；非 netTask 上下文
 * 函数说明：将关闭请求放入消息队列，阻塞等待 netTask 处理完毕。TCP Socket 先断开连接再释放控制块。
 *          netTask 内请使用 net_close_sock()
 */
int net_close(int sockfd) {
    net_msg_t msg;

    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == netMsgQueueHandle) {
        s_net_errno = NET_ERR;
        return -1;
    }

    msg.type = NET_MSG_CLOSE;
    msg.sockfd = sockfd;
    msg.caller = xTaskGetCurrentTaskHandle();
    msg.result = -1;

    if (osMessageQueuePut(netMsgQueueHandle, &msg, 0, osWaitForever) != osOK) {
        s_net_errno = NET_ERR_BUSY;
        return -1;
    }

    {
        uint32_t s_notified;
        xTaskNotifyWait(0, 0, &s_notified, portMAX_DELAY);
        msg.result = (int)s_notified;
    }

    if (msg.result < 0) {
        s_net_errno = NET_ERR;
    }
    return msg.result;
}

/*
 * 函数功能：发送 UDP 数据报（含目标地址）
 * 入口参数：sockfd     - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 *           buf        - 待发送数据缓冲区指针                                            const void *
 *           len        - 数据长度                                                        int > 0
 *           flags      - 标志位，通常为 0                                                int
 *           dest_addr  - 目标地址结构体指针                                              const struct net_sockaddr *
 *           addrlen    - 目标地址结构体长度                                              int >= sizeof(struct net_sockaddr_in)
 * 返回值：实际发送字节数                                                              int > 0 || -1
 *         -1          - 发送失败                                                      int
 * 限定条件：Socket 已创建且为 UDP 类型（SOCK_DGRAM）；net_init() 已调用
 */
int net_sendto(int sockfd, const void *buf, int len, int flags,
               const struct net_sockaddr *dest_addr, int addrlen) {
    net_sock_t *p_sock;
    const struct net_sockaddr_in *p_addr_in;
    int sent = 0;
    uint32_t tick_start;

    /* 参数检�?*/
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == buf || len <= 0) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    /* UDP 模式：设置目标地址 */
    if (NULL != dest_addr && addrlen >= (int)sizeof(struct net_sockaddr_in)) {
        p_addr_in = (const struct net_sockaddr_in *)dest_addr;

        /* 转换 IP 为数组格�?*/
        uint8_t ip_arr[4];
        uint32_t ip = p_addr_in->sin_addr.s_addr;
        ip_arr[0] = (uint8_t)(ip);
        ip_arr[1] = (uint8_t)(ip >> 8);
        ip_arr[2] = (uint8_t)(ip >> 16);
        ip_arr[3] = (uint8_t)(ip >> 24);

        ch395f_set_des_ip(sockfd, ip_arr);
        ch395f_set_des_port(sockfd, net_ntohs(p_addr_in->sin_port));
    }

    tick_start = HAL_GetTick();

    /* 发送数�?*/
    while (sent < len) {
        int chunk = len - sent;
        if (chunk > NET_SEND_BUF_SIZE) {
            chunk = NET_SEND_BUF_SIZE;
        }

        /* 检查发送缓冲区 */
        if (!p_sock->send_ready) {
            if (NET_SEND_TIMEOUT_MS > 0 &&
                (HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
                s_net_errno = NET_ERR_TIMEDOUT;
                break;
            }
            net_poll();
            continue;
        }

        ch395f_write_send_buf(sockfd, (uint8_t *)buf + sent, (uint16_t)chunk);
        p_sock->send_ready = 0;
        sent += chunk;
        p_sock->send_bytes += (uint32_t)chunk;

        /* 等待发送完�?*/
        tick_start = HAL_GetTick();
        while (!p_sock->send_ready) {
            net_poll();
            if (NET_SEND_TIMEOUT_MS > 0 &&
                (HAL_GetTick() - tick_start) >= NET_SEND_TIMEOUT_MS) {
                break;
            }
        }
    }

    return sent;
}
/*
 * 函数功能：接收 UDP 数据报（含源地址）
 * 入口参数：sockfd   - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 *           buf      - 接收缓冲区指针                                                  void *
 *           len      - 缓冲区大小                                                      int > 0
 *           flags    - 标志位，通常为 0                                                int
 *           src_addr - 输出：发送方地址结构体指针                                      struct net_sockaddr *（可为 NULL）
 *           addrlen  - 输入输出：源地址长度                                            int *（可为 NULL）
 * 返回值：实际接收字节数                                                              int >= 0 || -1
 *         -1          - 接收失败                                                    int
 * 限定条件：Socket 已创建且为 UDP 类型（SOCK_DGRAM）；net_init() 已调用；有数据可用
 */
int net_recvfrom(int sockfd, void *buf, int len, int flags,
                 struct net_sockaddr *src_addr, int *addrlen) {
    net_sock_t *p_sock;
    uint16_t recv_len;
    uint32_t tick_start;

    /* 参数检�?*/
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == buf || len <= 0) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    tick_start = HAL_GetTick();

    while (1) {
        net_poll();

        recv_len = ch395f_get_recv_len(sockfd);
        if (recv_len > 0) {
            /* UDP Server 模式：前 8 字节为固定格式（IP + 端口 + 长度�?*/
            if (p_sock->type == NET_SOCK_DGRAM && recv_len >= 8) {
                uint8_t header[8];
                ch395f_read_recv_buf(sockfd, header, 8);
                recv_len -= 8;

                /* 填充来源地址 */
                if (NULL != src_addr &&NULL != addrlen &&
                    *addrlen >= (int)sizeof(struct net_sockaddr_in)) {
                    struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)src_addr;
                    p_addr_in->sin_family = NET_AF_INET;
                    /* CH395F UDP �? [0-1] reserved  [2-3] src_port(LE)  [4-7] src_ip */
                    p_addr_in->sin_port = net_htons((uint16_t)(header[2] | (header[3] << 8)));
                    p_addr_in->sin_addr.s_addr = ((uint32_t)header[4]) |
                                               ((uint32_t)header[5] << 8) |
                                               ((uint32_t)header[6] << 16) |
                                               ((uint32_t)header[7] << 24);
                    *addrlen = sizeof(struct net_sockaddr_in);
                }
            }

            /* 读取数据 */
            if (recv_len > 0) {
                int read_len = (recv_len > (uint16_t)len) ? len : (int)recv_len;
            ch395f_read_recv_buf(sockfd, (uint8_t *)buf, (uint16_t)read_len);
            p_sock->recv_bytes += (uint32_t)read_len;
            return read_len;
            }
        }

        /* 非阻塞模式检�?*/
        if (flags & NET_MSG_DONTWAIT) {
            s_net_errno = NET_ERR_WOULDBLOCK;
            return -1;
        }

        /* 超时检�?*/
        if (NET_RECV_TIMEOUT_MS > 0 &&
            (HAL_GetTick() - tick_start) >= NET_RECV_TIMEOUT_MS) {
            s_net_errno = NET_ERR_TIMEDOUT;
            return -1;
        }
    }
}

/*
 * 函数功能：发送数据（内部版本，绕过消息队列，供 netTask 直接使用）
 */
/*
 * 函数功能：发送数据（内部版本，绕过消息队列，供 netTask 直接使用）
 * 入口参数：p_sock - Socket 控制块指针                                  net_sock_t *
 *           buf    - 待发送数据缓冲区指针                               const void *
 *           len    - 数据长度                                           int    > 0
 * 出口参数：无
 * 返回值：实际发送字节数（>= 0）；-1 表示参数无效                      int
 * 限定条件：p_sock 非空；netTask 上下文（避免向自身发送消息造成死锁）
 * 函数说明：直接调用 net_send_locked 完成发送
 */
int net_send_sock(net_sock_t *p_sock, const void *buf, int len) {
    if (NULL == p_sock) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }
    return net_send_locked(p_sock, buf, len);
}
/*
 * 函数功能：接收数据（内部版本，绕过消息队列，供 netTask 直接使用）
 * 入口参数：p_sock - Socket 控制块指针                                             net_sock_t *
 *           buf    - 接收缓冲区指针                                                  void *
 *           len    - 缓冲区大小                                                      int > 0
 *           flags  - 标志位，NET_MSG_DONTWAIT=非阻塞                                 int
 * 返回值：实际接收字节数                                                            int >= 0 || 0 || -1
 *         0        - 对端关闭连接                                                   int
 *         -1       - 接收失败                                                      int
 * 限定条件：必须在 netTask 上下文中调用；p_sock->in_use == 1
 * 函数说明：直接操作 Socket 控制块，不经过消息队列。避免 netTask 向自身发送消息造成死锁
 */
int net_recv_sock(net_sock_t *p_sock, void *buf, int len, int flags) {
    if (NULL == p_sock) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }
    return net_recv_locked(p_sock, buf, len, flags);
}
/*
 * 函数功能：关闭 Socket（内部版本，绕过消息队列，供 netTask 直接使用）
 * 入口参数：p_sock - Socket 控制块指针                                             net_sock_t *
 * 返回值：0 - 关闭成功                                                            int
 *         -1       - 关闭失败                                                     int
 * 限定条件：必须在 netTask 上下文中调用；p_sock->in_use == 1
 * 函数说明：直接操作 Socket 控制块，不经过消息队列。TCP Socket 先断开连接再释放控制块
 */
int net_close_sock(net_sock_t *p_sock) {
    if (NULL == p_sock) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }
    return net_close_locked(p_sock);
}
/*
 * 函数功能：注册 Socket 事件回调函数
 * 入口参数：sockfd - Socket 描述符                                                  int >= 0 && < NET_MAX_SOCKETS
 *           cb     - 回调函数指针                                                    net_event_cb_t（可为 NULL 取消注册）
 *           arg    - 用户自定义参数指针                                              void *
 * 返回值：0 - 注册成功                                                            int
 *         -1       - 注册失败                                                     int
 * 限定条件：Socket 已创建且 in_use == 1；net_init() 已调用
 */

int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
    net_sock_t *p_sock;

    /* 参数检�?*/
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    p_sock->event_cb = cb;
    p_sock->event_arg = arg;

    return 0;
}
/*
 * 函数功能：获取 Socket 最后一次操作返回的错误码
 * 返回值：当前错误码值（NET_OK=0, NET_ERR_xxx=-N）                                int
 * 限定条件：无
 * 函数说明：每次 net_*() API 调用失败后，错误码被设置。调用成功时不自动清零
 */

int net_get_errno(void) {
    return s_net_errno;
}

/*
 * 函数功能：将点分十进制 IP 地址字符串转换为网络字节序的 32 位地址
 * 入口参数：cp - 点分十进制 IP 字符串（如 "192.168.1.100"）            const char *
 * 出口参数：无
 * 返回值：网络字节序的 32 位 IP 地址（0 表示参数无效）                uint32_t
 * 限定条件：无
 * 函数说明：1. 逐段解析十进制数与并小端组装为 32 位值
 *           2. 转换结果经 NET_htonl 转为网络字节序
 */
uint32_t net_inet_addr(const char *cp) {
    uint32_t addr = 0;
    uint32_t val;
    int i;

    if (NULL == cp) {
        return 0;
    }

    for (i = 0; i < 4; i++) {
        val = 0;
        while (*cp >= '0' && *cp <= '9') {
            val = val * 10 + (*cp - '0');
            cp++;
        }
        addr |= (val << (i * 8));
        if (*cp == '.') {
            cp++;
        }
    }

    return NET_htonl(addr);
}

/*
 * 函数功能：将网络字节序的 32 位地址转换为点分十进制字符串
 * 入口参数：addr - 网络字节序的 32 位 IP 地址                         uint32_t
 *           buf  - 输出缓冲区（至少 16 字节）                          char *
 * 出口参数：buf  - 填充点分十进制字符串
 * 返回值：成功返回 buf 指针；buf 为 NULL 时返回 NULL                  char *
 * 限定条件：buf 非空且长度足够（>= 16 字节）
 * 函数说明：1. 先经 NET_ntohl 转为主机字节序再格式化输出
 */
char *net_inet_ntoa(uint32_t addr, char *buf) {
    uint32_t naddr = NET_ntohl(addr);

    if (NULL == buf) {
        return NULL;
    }

    sprintf(buf, "%lu.%lu.%lu.%lu",
            (unsigned long)(naddr & 0xFF),
            (unsigned long)((naddr >> 8) & 0xFF),
            (unsigned long)((naddr >> 16) & 0xFF),
            (unsigned long)((naddr >> 24) & 0xFF));

    return buf;
}


/*
 * 函数功能：端口字节序转换（主机序 -> 网络序）
 * 入口参数：hostshort - 主机字节序的 16 位端口                        uint16_t
 * 出口参数：无
 * 返回值：网络字节序的 16 位端口                                      uint16_t
 * 限定条件：无
 * 函数说明：直接调用 NET_htons 完成转换
 */
uint16_t net_htons(uint16_t hostshort) {
    return NET_htons(hostshort);
}


/*
 * 函数功能：端口字节序转换（网络序 -> 主机序）
 * 入口参数：netshort - 网络字节序的 16 位端口                         uint16_t
 * 出口参数：无
 * 返回值：主机字节序的 16 位端口                                      uint16_t
 * 限定条件：无
 * 函数说明：直接调用 NET_ntohs 完成转换
 */
uint16_t net_ntohs(uint16_t netshort) {
    return NET_ntohs(netshort);
}

/*
 * 函数功能：IP 地址字节序转换（主机序 -> 网络序）
 * 入口参数：hostlong - 主机字节序的 32 位 IP 地址                     uint32_t
 * 出口参数：无
 * 返回值：网络字节序的 32 位 IP 地址                                  uint32_t
 * 限定条件：无
 * 函数说明：直接调用 NET_htonl 完成转换
 */
uint32_t net_htonl(uint32_t hostlong) {
    return NET_htonl(hostlong);
}

/*
 * 函数功能：IP 地址字节序转换（网络序 -> 主机序）
 * 入口参数：netlong - 网络字节序的 32 位 IP 地址                      uint32_t
 * 出口参数：无
 * 返回值：主机字节序的 32 位 IP 地址                                  uint32_t
 * 限定条件：无
 * 函数说明：直接调用 NET_ntohl 完成转换
 */
uint32_t net_ntohl(uint32_t netlong) {
    return NET_ntohl(netlong);
}

/*
 * 函数功能：分配一个空闲的 Socket 控制块
 * 入口参数：无
 * 出口参数：无
 * 返回值：空闲 Socket 索引（0~NET_MAX_SOCKETS-1）；-1 表示无空闲 Socket    int
 * 限定条件：s_net_socks 已定义
 * 函数说明：1. 线性扫描 s_net_socks，返回首个 in_use == 0 的控制块索引
 *           2. 调用方负责初始化该控制块
 */
static int alloc_socket(void) {
    int i;

    for (i = 0; i < NET_MAX_SOCKETS; i++) {
        if (!s_net_socks[i].in_use) {
            return i;
        }
    }

    return -1;
}

/*
 * 入口参数：p_sock - 发生连接事件的 Socket 控制块指针                    net_sock_t *
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_poll() 检测到 CONNECT 中断后调用；netTask 上下文
 * 函数说明：1. 单连接：自身转 ESTABLISHED 并读取对端地址
 *           2. TCP Client（CONNECTING）：连接成功，读取对端地址并置 ESTABLISHED
 *           3. 连接成功后使能 KeepAlive 并触发 NET_EVENT_CONNECTED 回调
 */
static void handle_connect_event(net_sock_t *p_sock) {
    if (p_sock->state == NET_SOCK_STATE_LISTENING) {
        /* 单连接：收到 CONNECT 中断 = 自身有连接到达，转为 ESTABLISHED */
        DBG_INFO("sock%d standalone accept", p_sock->ch395_sock);
        uint8_t remote[6];
        ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
        memcpy(p_sock->remote_ip_arr, remote, 4);
        p_sock->remote_ip = ((uint32_t)remote[0]) |
                          ((uint32_t)remote[1] << 8) |
                          ((uint32_t)remote[2] << 16) |
                          ((uint32_t)remote[3] << 24);
        p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
        p_sock->state = NET_SOCK_STATE_ESTABLISHED;
        p_sock->send_ready = 1;

        /* 清除残留的 TIMEOUT 中断标志 */
        (void)ch395f_get_sock_int_status(p_sock->ch395_sock);

        fire_event(p_sock, NET_EVENT_CONNECTED);
    } else if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
        /* TCP Client 连接成功 */
        uint8_t remote[6];
        ch395f_get_remot_ipp(p_sock->ch395_sock, remote);
        memcpy(p_sock->remote_ip_arr, remote, 4);
        p_sock->remote_ip = ((uint32_t)remote[0]) |
                          ((uint32_t)remote[1] << 8) |
                          ((uint32_t)remote[2] << 16) |
                          ((uint32_t)remote[3] << 24);
        p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
        p_sock->state = NET_SOCK_STATE_ESTABLISHED;

        ch395f_set_keepalive_enable(p_sock->ch395_sock, 1);

        fire_event(p_sock, NET_EVENT_CONNECTED);
    }
}

/*
 * 函数功能：处理 Socket 断开（DISCONNECT）事件，更新 Socket 状态机
 * 入口参数：p_sock - 发生断开事件的 Socket 控制块指针                    net_sock_t *
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_poll() 检测到 DISCONNECT 中断后调用；netTask 上下文
 * 函数说明：1. CH395F 在 DISCONNECT 后自动关闭 Socket（FUN_PARA 默认），需重新 OPEN + LISTEN
 *           2. 单连接：置 CLOSED，交由 net_recv_locked 排空剩余数据后再关
 *           3. 触发 NET_EVENT_DISCONNECTED 回调
 */
static void handle_disconnect_event(net_sock_t *p_sock) {
    if (p_sock->state == NET_SOCK_STATE_LISTENING) {
        DBG_ERROR("WARNING: listen sock%d got disconnect", p_sock->ch395_sock);
    } else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
        /* 单连接：先不关 CH395F Socket，
         * 留给 net_recv_locked 把剩余数据读出来再关，置 CLOSED 等待应用重新监听 */
        DBG_INFO("sock%d DISCONNECTED, releasing", p_sock->ch395_sock);
        p_sock->state = NET_SOCK_STATE_CLOSED;
        fire_event(p_sock, NET_EVENT_DISCONNECTED);
    } else if (p_sock->state != NET_SOCK_STATE_CLOSED &&
               p_sock->state != NET_SOCK_STATE_BOUND &&
               p_sock->state != NET_SOCK_STATE_CREATED) {
        /* 未预期的断开 */
        DBG_ERROR("sock%d disconnect in state %d", p_sock->ch395_sock, p_sock->state);
        fire_event(p_sock, NET_EVENT_DISCONNECTED);
    }
}

/*
 * 函数功能：处理数据接收事件
 * 函数功能：处理 Socket 数据接收（RECV_OK）事件
 * 入口参数：p_sock - 发生接收事件的 Socket 控制块指针                    net_sock_t *
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_poll() 检测到 RECV_OK 中断后调用；netTask 上下文
 * 函数说明：1. 仅触发 NET_EVENT_DATA_RECEIVED 回调通知上层
 *           2. 不在此读取 recv_len，避免与 net_recv_locked 中的读取冲突（Trap 13）
 */
static void handle_recv_event(net_sock_t *p_sock) {
    /* RECV_OK 中断已触发，直接通知上层。不在此读 recv_len，
     * 避免和 net_recv_locked 里面的 ch395f_get_recv_len 冲突（Trap 13） */
    fire_event(p_sock, NET_EVENT_DATA_RECEIVED);
}

/*
 * 函数功能：处理 Socket 发送完成（SEND_OK）事件
 * 入口参数：p_sock - 发生发送完成事件的 Socket 控制块指针              net_sock_t *
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_poll() 检测到 SEND_OK 中断后调用；netTask 上下文
 * 函数说明：触发 NET_EVENT_SEND_COMPLETE 回调通知上层
 */
static void handle_send_event(net_sock_t *p_sock) {
    fire_event(p_sock, NET_EVENT_SEND_COMPLETE);
}

/*
 * 函数功能：处理 Socket 超时（SOCK_TIMEOUT）事件，更新 Socket 状态机
 * 入口参数：p_sock - 发生超时事件的 Socket 控制块指针                    net_sock_t *
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_poll() 检测到 SOCK_TIMEOUT 中断后调用；netTask 上下文
 * 函数说明：1. TCP Client（CONNECTING）：连接超时，回到 CREATED 状态
 *           2. 已建立连接：回到 CLOSED（单连接）
 *           3. 监听态：异常超时，记录错误日志
 *           4. 触发 NET_EVENT_TIMEOUT 回调
 */
static void handle_timeout_event(net_sock_t *p_sock) {
    if (p_sock->state == NET_SOCK_STATE_CONNECTING) {
        /* TCP Client 连接超时 */
        DBG_ERROR("sock%d CONNECT TIMEOUT", p_sock->ch395_sock);
        p_sock->state = NET_SOCK_STATE_CREATED;
    } else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
        DBG_ERROR("sock%d TIMEOUT", p_sock->ch395_sock);
        p_sock->state = NET_SOCK_STATE_CLOSED;
    } else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
        /* 监听超时（异常情况） */
        DBG_ERROR("sock%d LISTEN TIMEOUT", p_sock->ch395_sock);
    }

    fire_event(p_sock, NET_EVENT_TIMEOUT);
}

/*
 * 函数功能：触发 Socket 事件回调（若已注册）
 * 入口参数：p_sock - 触发事件的 Socket 控制块指针                      net_sock_t *
 *           event  - 事件类型                                          net_event_t
 * 出口参数：无
 * 返回值：无
 * 限定条件：net_init() 已调用
 * 函数说明：1. 仅当 p_sock->event_cb 非空时调用回调
 *           2. 回调参数为 ch395_sock、event、event_arg
 */
static void fire_event(net_sock_t *p_sock, net_event_t event) {
    if (NULL != p_sock->event_cb) {
        p_sock->event_cb(p_sock->ch395_sock, event, p_sock->event_arg);
    }
}

/*
 * 函数功能：将点分十进制 IP 地址字符串解析为 4 字节数组
 * 入口参数：str    - 点分十进制 IP 字符串（如 "192.168.1.100"）       const char *
 *           ip_arr - 输出：4 字节 IP 数组（网络序，低字节在前）        uint8_t *
 * 出口参数：ip_arr - 填充解析后的 IP 地址
 * 返回值：无
 * 限定条件：str 与 ip_arr 均非空
 * 函数说明：1. 逐段解析十进制数写入 ip_arr[0..3]
 *           2. 参数非法（NULL）时直接返回，不做解析
 */
static void parse_ip_string(const char *str, uint8_t *ip_arr) {
    uint32_t val;
    int i;

    if (NULL == str ||NULL == ip_arr) {
        return;
    }

    for (i = 0; i < 4; i++) {
        val = 0;
        while (*str >= '0' && *str <= '9') {
            val = val * 10 + (*str - '0');
            str++;
        }
        ip_arr[i] = (uint8_t)val;
        if (*str == '.') {
            str++;
        }
    }
}

/*
 * 函数功能：根据描述符获取 Socket 控制块指针（内部使用）
 * 入口参数：sockfd - Socket 描述符                                     int    0 - NET_MAX_SOCKETS-1
 * 出口参数：无
 * 返回值：Socket 控制块指针；描述符越界或未分配时返回 NULL             net_sock_t *
 * 限定条件：无
 * 函数说明：1. 描述符越界（<0 或 >= NET_MAX_SOCKETS）返回 NULL
 *           2. 未使用（in_use == 0）的 Socket 返回 NULL
 */
net_sock_t *net_get_sock(int sockfd) {
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        return NULL;
    }

    if (!s_net_socks[sockfd].in_use) {
        return NULL;
    }

    return &s_net_socks[sockfd];
}

/*
 * 函数功能：获取 Socket 本地地址（IP + Port）
 * 入口参数：sockfd   - socket 描述符                                    int
 *          addr     - 输出：本地地址                                   struct net_sockaddr *
 *          addrlen  - 输入输出：地址结构体长度                          int *
 * 返回值：0 - 成功，-1 - 失败                                           int
 * 限定条件：socket 已创建或已绑定
 * 函数说明：返回 sin_family + sin_port（网络序）+ sin_addr（网络序，从 net_init 缓存的 s_local_ip）
 */
int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen) {
    if (sockfd < 0 || sockfd >= NET_MAX_SOCKETS) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    net_sock_t *p_sock = &s_net_socks[sockfd];
    if (!p_sock->in_use && p_sock->state == NET_SOCK_STATE_CLOSED) {
        s_net_errno = NET_ERR_BADF;
        return -1;
    }

    if (NULL == addr ||NULL == addrlen || *addrlen < (int)sizeof(struct net_sockaddr_in)) {
        s_net_errno = NET_ERR_INVAL;
        return -1;
    }

    struct net_sockaddr_in *p_addr_in = (struct net_sockaddr_in *)addr;
    memset(p_addr_in, 0, sizeof(struct net_sockaddr_in));
    p_addr_in->sin_family = NET_AF_INET;
    p_addr_in->sin_port = net_htons(p_sock->local_port);
    p_addr_in->sin_addr.s_addr = ((uint32_t)s_local_ip[0]) |
                                 ((uint32_t)s_local_ip[1] << 8) |
                                 ((uint32_t)s_local_ip[2] << 16) |
                                 ((uint32_t)s_local_ip[3] << 24);
    *addrlen = sizeof(struct net_sockaddr_in);

    return 0;
}
