net_socket.c补net_process_messages分派文档:三个自愈tick机制、各消息类型处理说明与结果回传路径
This commit is contained in:
@@ -496,10 +496,26 @@ static void net_reconcile_tick(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:处理消息队列中的请求
|
||||
* 限定条件:必须在 netTask 上下文中调用(独占 CH395F 和 s_net_socks 访问权)
|
||||
* 函数说明:每次调用处理一条消息。处理 send/recv 时内部会调用 net_poll()
|
||||
* 等待操作完成。处理完毕后通知调用方任务。
|
||||
* 函数功能:netTask 主循环核心 —— 自愈 tick 宿主 + 消息队列分派器。每轮
|
||||
* 先跑三个非阻塞自愈 tick(D10 重监听 / L3 挂起 recv / Trap 22
|
||||
* 状态对账),再非阻塞排空队列按 msg.type 分派到 _locked 实现。
|
||||
* 限定条件:必须在 netTask 上下文中调用(独占 CH395F 与 s_net_socks 访问权);
|
||||
* 由 net_task.c 在 net_stack_bring_up 之后每次 1ms 循环调用。
|
||||
* 返回值 :void;结果经 xTaskNotify 通知值回传(成功=字节数/描述符,
|
||||
* 失败=具体错误码);调用方 net_wait_result 拾取,对外统一 -1。
|
||||
* 函数说明:
|
||||
* ① 三个自愈 tick 均非阻塞(绝不 osDelay 忙等,netTask 永不冻结):
|
||||
* - net_relisten_retry_tick(D10):断连后按 30ms(NET_RELISTEN_RETRY_MS)
|
||||
* 节拍重试 open+listen,2s(NET_RELISTEN_DEADLINE_MS)总时限到期放弃留痕;
|
||||
* 本 fd 有在途挂起 recv 时跳过(L3 保险)。
|
||||
* - net_pending_tick(L3):按节拍了结挂起 recv(①数据 ②到点 ③断连);
|
||||
* 到点后 1s(NET_PENDING_WATCHDOG_MS)未了结 → 强制了结 + DBG_ERROR 留痕。
|
||||
* - net_reconcile_tick(Trap 22):每 200ms(NET_RECONCILE_PERIOD_MS)对账,
|
||||
* 连续 2 次失配去抖 + 1s 冷却,三类失同步自愈。
|
||||
* ② net_msg_t 按值入队,netTask 侧副本调用方不可见 → 结果只能搭
|
||||
* 任务通知值回传;32 位整体即结果,不做位域压缩。
|
||||
* ③ RECV 特例:无数据+阻塞 → 登记 pending 哨兵 NET_PENDING_REGISTERED
|
||||
* (0x70000000),do_notify=0,回执推迟到 net_pending_tick 完成时。
|
||||
*/
|
||||
void net_process_messages(void) {
|
||||
net_msg_t msg;
|
||||
@@ -515,11 +531,25 @@ void net_process_messages(void) {
|
||||
net_pending_tick();
|
||||
net_reconcile_tick(); /* Trap 22:芯片/本层状态周期对账(丢中断自愈) */
|
||||
|
||||
/* 队列排空:超时 0 非阻塞取,直到本轮队列为空。do_notify=1 表示
|
||||
* 本条消息需要即时回执;=0 只出现在 RECV 挂起登记(返回哨兵
|
||||
* NET_PENDING_REGISTERED)——回执推迟到 net_pending_tick 完成检查
|
||||
* 发出,避免把"登记成功"误当成处理结果通知调用方。 */
|
||||
while (osMessageQueueGet(netMsgQueueHandle, &msg, NULL, 0) == osOK) {
|
||||
int do_notify = 1;
|
||||
|
||||
switch (msg.type) {
|
||||
case NET_MSG_SEND: {
|
||||
/* TCP send:由 net_send_locked 真正写 CH395F。
|
||||
* - net_get_sock 返回 NULL(fd 越界/已 close)→ NET_ERR_BADF
|
||||
* - 状态非 ESTABLISHED → NET_ERR_NOTCONN
|
||||
* - 否则按硬件发送缓冲上限(NET_SEND_CHUNK_MAX=1KB)分块
|
||||
* 写入并等待 send_ready(SEND_OK 中断),单块停滞
|
||||
* NET_SEND_TIMEOUT_MS(1s) 超时;中途断连立即失败 CONNRESET
|
||||
* (不白等满超时)。
|
||||
* 返回实际写入字节数;短写会 DBG_ERROR 留痕,调用方须校验
|
||||
* 返回值而非只看非负。成功=字节数、失败=-1(errno 随通知值
|
||||
* 回传)。 */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
@@ -533,6 +563,21 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_RECV: {
|
||||
/* TCP/UDP recv:由 net_recv_locked 走三条出口——
|
||||
* ① 数据已就绪 → 快速 SPI 读出,返回字节数(即时回执);
|
||||
* ② 无数据 + NET_MSG_DONTWAIT → CLOSED 态按对端关闭返回 0
|
||||
* (触发 auto_relisten),否则 NET_ERR_WOULDBLOCK(-1)
|
||||
* (即时回执);
|
||||
* ③ 无数据 + 阻塞等待 → 登记挂起请求并返回哨兵
|
||||
* NET_PENDING_REGISTERED(每 fd 至多一个,禁止覆盖——
|
||||
* 覆盖会丢失前一次调用方的通知使其永久挂死;
|
||||
* caller==NULL 或调用者本身是 netTask 时拒绝登记,
|
||||
* 防"自等自通知"死锁):本条消息 do_notify=0 不发即时
|
||||
* 回执,完成(数据/30s 默认超时或 msg.timeout_ms 指定
|
||||
* 预算/断连/显式取消 close、resync、网络重建)由
|
||||
* net_pending_tick 按主循环节拍以字节数/0/负错误码通知
|
||||
* caller。挂起期间 msg.buf 指针须保持有效(net_pending
|
||||
* 只存指针不拷贝数据)。 */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
@@ -549,6 +594,14 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_CLOSE: {
|
||||
/* TCP close:先了结本 fd 的挂起 recv(排空可读数据或
|
||||
* NET_ERR_CONNRESET 取消——必通知,防等待中调用方永久挂死),
|
||||
* 再 ch395f_close_socket、轮询等芯片回 CLOSED(≤500ms)并
|
||||
* 排空残留中断、memset 控制块、清 D10 待重试与 L3 挂起状态。
|
||||
* fd 越界/已关闭 → NET_ERR_BADF;成功返回 0。
|
||||
* 单连接模型注意:监听 fd 断开后 auto_relisten 会自动恢复
|
||||
* 监听,EOF 时应用层**不要**对监听 fd 发 close(会毁掉端口
|
||||
* → 连接永拒),仅独立数据 fd 才 close。 */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
s_net_errno = NET_ERR_BADF;
|
||||
@@ -559,16 +612,39 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_CONNECT: {
|
||||
/* TCP connect(异步,返回成功即已下发 CONNECT 命令):保存
|
||||
* 远端 IP/端口(msg.addr/addrlen 由公开 API net_connect 的
|
||||
* memcpy 填入)→ open 失败 3 次重试(Trap 09,每次失败先
|
||||
* close 再重试)→ 清本 Socket 残留中断(防上一条连接遗留
|
||||
* DISCONNECT 误判)→ 下发 TCP CONNECT → 状态置 CONNECTING
|
||||
* 等待 CONNECT 中断(net_poll 维护状态与事件)。失败 NET_ERR_BUSY/
|
||||
* INVAL 返回 -1;成功返回 0,调用方须轮询 net_sock_state()
|
||||
* 等 ESTABLISHED 后才是可用连接。 */
|
||||
msg.result = net_connect_locked(msg.sockfd,
|
||||
(const struct net_sockaddr *)&msg.addr,
|
||||
msg.addrlen);
|
||||
break;
|
||||
}
|
||||
case NET_MSG_LISTEN: {
|
||||
/* TCP listen:仅 BOUND/CREATED 态的 TCP 流 socket 允许。
|
||||
* open+TCP_LISTEN 失败 3 次重试(Trap 09)→ 状态置
|
||||
* LISTENING、auto_relisten=1、清各 Socket 及全局历史中断
|
||||
*(防残留/伪中断在监听刚生效时误触发连接/断开事件)。成功
|
||||
* 返回 0;失败 NET_ERR_INVAL/BUSY 返回 -1。单连接模型下该
|
||||
* fd 后续即数据通道(g_client==g_listen),断开后自动重监听
|
||||
*(模拟 BSD 监听常驻,应用层无需手动重建)。 */
|
||||
msg.result = net_listen_locked(msg.sockfd);
|
||||
break;
|
||||
}
|
||||
case NET_MSG_ACCEPT: {
|
||||
/* accept:入参经 net_msg_t 的 buf/len 字段携带(公开 API
|
||||
* net_accept 将 addr 指针与 addrlen 填入 msg.buf/msg.len;
|
||||
* addrlen>0 且 buf 非 NULL 时,net_accept_locked 通过局部
|
||||
* 变量指针回填对端地址长度 sizeof(net_sockaddr_in))。
|
||||
* 单连接:状态 ESTABLISHED 即有可接受连接 → 返回同一 fd
|
||||
*(监听 Socket 自身已转为数据通道);非 ESTABLISHED →
|
||||
* CLOSED+auto_relisten 先非阻塞尝试恢复监听,最终
|
||||
* NET_ERR_WOULDBLOCK(-1)。失败返回具体错误码。 */
|
||||
struct net_sockaddr *p_addr = (struct net_sockaddr *)msg.buf;
|
||||
int addrlen = msg.len;
|
||||
int *p_addrlen = (p_addr != NULL && addrlen > 0) ? &addrlen : NULL;
|
||||
@@ -609,7 +685,11 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
s_net_errno = NET_ERR; /* 未知消息类型:置通用错误码,保证回传值有效 */
|
||||
/* 未知消息类型(枚举闭合,正常不应触发):置通用错误码
|
||||
* NET_ERR、结果 -1,保证通知值永远有效——调用方通过
|
||||
* net_wait_result 拿到的是本条消息的确定结果,而非
|
||||
* 上一条消息的残留值。 */
|
||||
s_net_errno = NET_ERR;
|
||||
msg.result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user