fix(N34): E14 丢中断复核——芯片不丢事件;listen 排事件挪至 LISTEN 前+全局读收口+全库归因更正
48 轮直读 SINT 矩阵(8 周期×6 变体)复核历史"丢中断"说法:芯片侧事件 丢失 = 0。归类:drain 读清消费 3/48(drain-int 探针现场抓获)、门控 竞态 2/48、主机同步 1/48、幽灵态 0/48 未复现。 根除性修复:net_listen_locked / net_listener_try 的排事件读清从 listen 后挪至 LISTEN 命令之前——新连接 CONNECT 落进该窗即被本方读清 吞掉,即"数据被吞"的生产侧自伤机制(台架 3/48 为同形态放大版)。 全局读收口:全局中断寄存器唯一读者 = net_poll(I7);生产/测试/台架 游离全局读全部删除,ch395f.h 声明处加护栏注释。 归因更正:17 文件约 40 处"丢中断"措辞改为"事件未收到/读清消费竞态" (机制全部保留,仅归因更正);设计文档 §5.2 新增 E14 锚点;Trap Records TRAP-NET-17/-20/B3 归因更正段;配图生成器与 SVG 重生成。 台架:事件未收到复核探针保留(drain-int / SINT 补读×3 / 超时归类), 下次跑矩阵自动归类;实验注册(main.c/uvprojx)已完全还原。 验证:@build 0 错误 0 警告;ci_local L0 32/0 + gitlint + L0.5 953/953;doc-links --all --sections-strict 通过;@test PASS(无 [ERR],net init 619ms);回归 :7003 300ms×10 = 10/10、:21 n30×50 = 0/50 失败。
This commit is contained in:
@@ -20,9 +20,9 @@
|
||||
- 一期(RECV)已落地:`net_recv` 等支持带超时的阻塞(`pending` 挂起 + tick 唤醒)
|
||||
- 二期(ACCEPT + SEND)待做 → `docs/任务规划/登记簿.md` N-4
|
||||
|
||||
### 周期对账自愈(TRAP-NET-17 修复;N34 阶段 3 合并 pump)
|
||||
### 周期对账自愈(TRAP-NET-17 修复;自愈收敛阶段 3 合并 pump)
|
||||
|
||||
- `net_reconcile_tick()`(100ms,N34 阶段 3 起判据读**驱动状态缓存**——唯一
|
||||
- `net_reconcile_tick()`(100ms,自愈收敛阶段 3 起判据读**驱动状态缓存**——唯一
|
||||
刷新点 `net_poll` 每轮全量刷新,E2 实测单次回读 18.1us)修正失同步:
|
||||
本层 ESTABLISHED 而芯片已断 → 断开;本层 LISTENING 而芯片已握手 → 补 accept;
|
||||
本层 LISTENING/CLOSED(监听型 fd)而芯片监听消失 → 重建(原 pump③④);
|
||||
|
||||
@@ -467,7 +467,7 @@ static int cmd_pasv(lftpd_client_t *client, const char *arg)
|
||||
client->data_socket = -1;
|
||||
}
|
||||
|
||||
/* N34 阶段1-6:原 3×200ms 应用层重试已删(lftpd_inet_listen 单次化)——
|
||||
/* 自愈收敛阶段1-6:原 3×200ms 应用层重试已删(lftpd_inet_listen 单次化)——
|
||||
* 失败直接 425,FTP 客户端自带传输重试语义;服务端不再叠阻塞重试 */
|
||||
int listener_socket = lftpd_inet_listen(0);
|
||||
if (listener_socket < 0) {
|
||||
@@ -795,7 +795,7 @@ int lftpd_start(const char *directory, int port, lftpd_t *lftpd)
|
||||
{
|
||||
struct net_sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
/* N34 E13 §6 修复:原用 getsockname 打印的是**本机** IP:21(且
|
||||
/* E13 定案 修复:原用 getsockname 打印的是**本机** IP:21(且
|
||||
* ntoa 段序反转成 "100.1.168.192")——改 getpeername 打印真实
|
||||
* 对端(现场排障需要"谁连进来");未连接则退回无地址形态 */
|
||||
if (net_getpeername(client_socket,
|
||||
|
||||
@@ -34,7 +34,7 @@ void lftpd_task_wd_beat(void)
|
||||
|
||||
int lftpd_inet_listen(int port)
|
||||
{
|
||||
/* N34 阶段1-6:应用层阻塞重试退役(原 5 轮 500ms/2000ms,最坏 10s 阻塞
|
||||
/* 自愈收敛阶段1-6:应用层阻塞重试退役(原 5 轮 500ms/2000ms,最坏 10s 阻塞
|
||||
* ftpTask)——TRAP-NET-09 的启动形态已由就绪屏障消除(FTP_READY 等 NET_READY,
|
||||
* lftpd_start 外层本就有监听失败重建循环);芯片忙窗失败属罕见,PASV 数据
|
||||
* 监听交给 FTP 客户端自身的重试语义(主流 FTP 服务器 passive listen 失败
|
||||
@@ -108,7 +108,7 @@ int lftpd_inet_accept_timeout(int socket, int timeout_ms)
|
||||
if (s >= 0) {
|
||||
return s;
|
||||
}
|
||||
/* F-NET-15 M2(N34 实验 2026-10-12):镜像门控退役——原直读 p_sock->state 在
|
||||
/* F-NET-15 M2(自愈专项实验 2026-10-12):镜像门控退役——原直读 p_sock->state 在
|
||||
* relisten 忙期(CLOSED 瞬态)误判"已关闭",扔掉 ~4.9s 等待预算;armed 门控
|
||||
* 认"监听器在服役(LISTENING)或待重建且 RX 有残留(closed-with-data 救回窗)",
|
||||
* 与 :7003 的 N-32 P1 同型修复 */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 实际生效值 60s/5s/3 并在 net_socket.c 引用(原宏为无效遗留值)
|
||||
* 2026-09-22 新增 NET_RETRANS_COUNT/NET_RETRANS_PERIOD_MS(P0-a:重传周期
|
||||
* 500→200ms 治 D1 症状),net_socket.c 的字面量 8/500 移入本文件
|
||||
* 2026-10-13 N34 阶段 1.5:删除 NET_RECV_TIMEOUT_MS(30s 默认预算)——
|
||||
* 2026-10-13 自愈收敛阶段 1.5:删除 NET_RECV_TIMEOUT_MS(30s 默认预算)——
|
||||
* recv 超时改为调用方策略(net_recv 无限阻塞 /
|
||||
* net_recv_to 显式预算 / net_select 首选),API 不再强加默认值
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ extern "C" {
|
||||
/*
|
||||
* 超时时间配置(毫秒)
|
||||
* 0 = 无限等待(阻塞模式)
|
||||
* 注:recv 侧无编译期默认预算(N34 阶段 1.5 删除 NET_RECV_TIMEOUT_MS)——
|
||||
* 注:recv 侧无编译期默认预算(自愈收敛阶段 1.5 删除 NET_RECV_TIMEOUT_MS)——
|
||||
* 超时是调用方策略:net_recv() 无限阻塞、net_recv_to() 显式预算、
|
||||
* net_select() 首选机制。
|
||||
*/
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* 模块名称:Network Listener Lifecycle
|
||||
* 模块功能:监听器生命周期(真机专属)—— 维持 fd 处于 LISTEN 态的全部机制:
|
||||
* 重建(open+listen)、重建前的沉降/隔离(TRAP-NET-18)、排空 RX 残渣、
|
||||
* D10 非阻塞重试(周期性重建决策者=N34 阶段 3 合并后的
|
||||
* D10 非阻塞重试(周期性重建决策者=自愈收敛阶段 3 合并后的
|
||||
* net_reconcile_tick,见 net_socket.c)。
|
||||
* 适用平台:STM32F407ZGTx + CH395F 以太网芯片
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-10-12
|
||||
* 修改记录:
|
||||
* 2026-10-12 王建锋 从 net_socket.c 整体抽出监听生命周期(N-32 §10 模块化)
|
||||
* 2026-10-13 王建锋 N34 阶段 3:pump 并入 net_reconcile_tick(实施方案 §5 项 1)
|
||||
* 2026-10-13 王建锋 自愈收敛阶段 3:pump 并入 net_reconcile_tick(《网络自愈架构设计》§4.1)
|
||||
*
|
||||
* 职责与边界见 net_listener.h 头注释;设计依据见
|
||||
* docs/子系统设计/网络Socket监听生命周期设计说明.md §10。
|
||||
@@ -176,7 +176,7 @@ static int net_relisten_locked(int sockfd) {
|
||||
ch395f_close_socket((uint8_t)sockfd);
|
||||
/* 读即清:本 Socket 中断状态寄存器 */
|
||||
(void)ch395f_get_sock_int_status((uint8_t)sockfd);
|
||||
/* F-NET-15 M4-lite(N34 实验 2026-10-12):删除沉降段的全局读即清——
|
||||
/* F-NET-15 M4-lite(自愈专项实验 2026-10-12):删除沉降段的全局读即清——
|
||||
* ① 违反模块约定「所有 CH395F 中断在 net_poll 内集中读取并清除」;
|
||||
* ② 全局寄存器整体读即清无按位手段(B3 实证),每 30ms 重试一轮即搁浅
|
||||
* 其它在用 Socket 的 CONNECT/DISCONNECT/RECV_OK(net_poll 门控焊死);
|
||||
@@ -228,11 +228,18 @@ static int net_relisten_locked(int sockfd) {
|
||||
/* 交重试轮询(30ms 后复检) */
|
||||
return -1;
|
||||
}
|
||||
/* 排事件必须在 LISTEN 命令**之前**(E14 复核 2026-10-14:listen 后读清会把
|
||||
* 快速复连新连接的 CONNECT 吞掉——与 net_listen_locked 同源同改法;B3 机制
|
||||
* 与 git 考古见该处注释)。本处是每次断连 auto-relisten 的热路径:只清本
|
||||
* Socket,全局交 net_poll 集中读清(AGENTS 模块约定)。
|
||||
* 读即清:防上一条会话残留 DISCONNECT/TIMEOUT 误触发;挪后若仍有滞后事件
|
||||
* 落进新会话,事件处理器回读状态裁决(状态面为真相),无害 */
|
||||
(void)ch395f_get_sock_int_status((uint8_t)sockfd);
|
||||
/* 下发 TCP LISTEN 命令 */
|
||||
status = ch395f_tcp_listen((uint8_t)sockfd);
|
||||
/* LISTEN 失败 → BUSY(同样交重试) */
|
||||
if (status != CH395F_ERR_SUCCESS) {
|
||||
/* 0-3(N34 阶段0,U12 对称):open 已成而 LISTEN 失败——不 close 会把
|
||||
/* 0-3(自愈收敛阶段0,U12 对称):open 已成而 LISTEN 失败——不 close 会把
|
||||
* 芯片 Socket 卡在"OPEN 无监听",下一轮 open 返 USE 又进失败分支
|
||||
* (U12 同源事故形态)。close 交重试轮,与 open 失败分支同形 */
|
||||
ch395f_close_socket((uint8_t)sockfd);
|
||||
@@ -251,7 +258,7 @@ static int net_relisten_locked(int sockfd) {
|
||||
p_sock->released_abnormal = 0U;
|
||||
/* N-30(TRAP-NET-20):清零前把对端端口转登为幽灵甄别基准 */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
/* N-30:新监听会话,丢中断去抖计数清零 */
|
||||
/* N-30:新监听会话,事件未收到去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
/* 清对端端口(新连接待用) */
|
||||
p_sock->remote_port = 0;
|
||||
@@ -265,13 +272,6 @@ static int net_relisten_locked(int sockfd) {
|
||||
p_sock->recv_bytes = 0;
|
||||
/* auto_relisten 保持为 1,下次断连仍自动重监听 */
|
||||
|
||||
/* 读即清:仅本 Socket 的中断状态(防上一条会话残留误触发)。
|
||||
* 原为"全 8 个 Socket + 全局"读清,与 net_listen_locked 同源(B3,机制
|
||||
* 与 git 考古见该处注释):本处是每次断连 auto-relisten 的热路径,全量清
|
||||
* 会持续吞掉其它在用 Socket 的 CONNECT/DISCONNECT 等边沿事件。全局中断
|
||||
* 寄存器交 net_poll 集中读清(AGENTS 模块约定)。 */
|
||||
(void)ch395f_get_sock_int_status((uint8_t)sockfd);
|
||||
|
||||
/* 留痕:监听器重建完成 */
|
||||
DBG_INFO("sock%d auto-relisten ok", sockfd);
|
||||
/* 重监听成功 */
|
||||
@@ -415,7 +415,7 @@ void net_listener_retry_tick(void) {
|
||||
if (s_relisten_wait[i] == 0U) {
|
||||
continue;
|
||||
}
|
||||
/* 0-4(N34 阶段0)状态门:仅本层仍 LISTENING/CLOSED 才重试。若已转
|
||||
/* 0-4(自愈收敛阶段0)状态门:仅本层仍 LISTENING/CLOSED 才重试。若已转
|
||||
* ESTABLISHED(新会话抢先到达),在途重试登记即陈旧——继续跑会
|
||||
* open→close 摧毁活连接(认领口径与 reconciler 形态③④ 一致) */
|
||||
{
|
||||
@@ -460,7 +460,7 @@ void net_listener_retry_tick(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* N34 阶段 3(实施方案 §5 项 1):原"监听器 pump"(100ms 周期、去抖/冷却、
|
||||
/* 自愈收敛阶段 3(《网络自愈架构设计》§4.1):原"监听器 pump"(100ms 周期、去抖/冷却、
|
||||
* 情形①②③)已并入 net_socket.c 的 net_reconcile_tick 单一 100ms tick
|
||||
* (判据读驱动状态缓存);本模块保留沉降/隔离、D10 重试、armed 查询与
|
||||
* net_listener_try(重建动作本身,由 reconciler 形态③④ 调用)。 */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 模块名称:Network Listener Lifecycle (Header)
|
||||
* 模块功能:监听器生命周期模块的对外接口(**真机专属**)—— 维持 fd 处于
|
||||
* LISTEN 态的全部机制:重建、重建前的沉降/隔离(TRAP-NET-18)、排空 RX
|
||||
* 残渣、D10 非阻塞重试(周期重建决策者=N34 阶段 3 合并后的
|
||||
* 残渣、D10 非阻塞重试(周期重建决策者=自愈收敛阶段 3 合并后的
|
||||
* net_reconcile_tick,见 net_socket.c)。
|
||||
* 适用平台:STM32F407ZGTx + CH395F 以太网芯片
|
||||
* 作者:王建锋
|
||||
@@ -86,8 +86,8 @@ void net_listener_clear(int sockfd);
|
||||
*/
|
||||
void net_listener_retry_tick(void);
|
||||
|
||||
/* N34 阶段 3:原 `net_listener_pump`(周期重建决策者)已并入 net_socket.c 的
|
||||
* net_reconcile_tick 单一 100ms tick(判据读驱动状态缓存,实施方案 §5 项 1)。
|
||||
/* 自愈收敛阶段 3:原 `net_listener_pump`(周期重建决策者)已并入 net_socket.c 的
|
||||
* net_reconcile_tick 单一 100ms tick(判据读驱动状态缓存,《网络自愈架构设计》§4.1)。
|
||||
* 本模块的 net_listener_try 由 reconciler 形态③④ 与 D10 重试轮询调用。 */
|
||||
|
||||
/* 注:本模块消费的宿主能力 `net_pending_active()` 声明在 net_socket.h
|
||||
|
||||
+112
-102
@@ -39,13 +39,13 @@
|
||||
*/
|
||||
#define NET_PHY_CHECK_INTERVAL_MS 5000U /* PHY 状态定期检查间隔(ms) */
|
||||
|
||||
/* N34 E6 实验插桩(U15 失配频率,docs/网络/N34-自愈审计.md §6 E6):
|
||||
* 假设=「RX 非空但 readable=0」(RECV_OK 中断丢失的数据面形态)在生产真实
|
||||
/* E6 实验插桩(U15 失配频率,docs/网络/网络自愈架构设计.md §4.8;裁决锚点 §5.2 E6):
|
||||
* 假设=「RX 非空但 readable=0」(RECV_OK 事件未收到的数据面形态)在生产真实
|
||||
* 发生。置 1 烧实验固件:net_poll 每 32 轮对在用 fd 发一条 GET_RECV_LEN,
|
||||
* 命中计数 + 低频日志(每小时 ≤1 条防刷屏);跑 24h 常态 + E1 压测。
|
||||
* 判据:命中 >0 → 阶段 3 项 4(U15 内化)立项;=0(含压测)→ 上层 32 轮
|
||||
* 盲收保留现状、U15 登记观察项。**默认 0 = 产品构建零成本(编译剔除)**。
|
||||
* E6 已裁决(2026-10-13,实验方案 E6 结果):命中=0(含压测)→ 项 4 不立项,维持默认 0。
|
||||
* E6 已裁决(2026-10-13,《网络自愈架构设计》§5.2 E6):命中=0(含压测)→ 项 4 不立项,维持默认 0。
|
||||
* ⚠ 必须定义在文件最前部:bring_up 的 armed 日志与 net_poll 探测环两处消费。 */
|
||||
#define NET_U15_PROBE 0
|
||||
#if NET_U15_PROBE
|
||||
@@ -196,7 +196,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
|
||||
* 按 ①数据 ②到点(仅显式预算) ③断连 顺序检查完成条件并通知调用方(语义逐项对齐旧自旋循环)
|
||||
* 关闭/网络重建/陈旧重同步走显式 settle/cancel 路径(取消必通知,调用方永不挂死)
|
||||
* 公开 API 返回契约不变:>0 字节数 / 0 EOF / -1 错误(错误码经通知值回传)
|
||||
* N34 阶段 1.5:预算归调用方——timeout_ms=0 即无限等待(30s 默认预算已删),
|
||||
* 自愈收敛阶段 1.5:预算归调用方——timeout_ms=0 即无限等待(30s 默认预算已删),
|
||||
* 原"到点 +1s 强制了结"的看门狗降级为 tripwire(只留痕、绝不伪造返回值)
|
||||
*/
|
||||
#define NET_PENDING_REGISTERED 0x70000000 /* 内部哨兵:pending 已登记(分派跳过即时通知;取值不与字节数空间冲突) */
|
||||
@@ -204,7 +204,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
|
||||
|
||||
typedef struct {
|
||||
uint8_t active; /* 1 = 本 fd 有挂起 recv */
|
||||
uint8_t infinite; /* 1 = 无限等待(无 deadline,N34 阶段 1.5:0 预算 = 永等) */
|
||||
uint8_t infinite; /* 1 = 无限等待(无 deadline,自愈收敛阶段 1.5:0 预算 = 永等) */
|
||||
uint8_t tripwire_logged; /* 1 = 本轮挂起已打过 tripwire(保证只留痕一条) */
|
||||
void *buf; /* 调用方缓冲(仅指针,须保持有效至完成) */
|
||||
int len; /* 缓冲容量 */
|
||||
@@ -277,7 +277,7 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
||||
/* 复位芯片 */
|
||||
ch395f_reset();
|
||||
|
||||
/* 芯片版本留痕 + 0-6 版本门控(N34 阶段0,§5.52 表):bit3 SOCKET_CLOSE
|
||||
/* 芯片版本留痕 + 0-6 版本门控(自愈收敛阶段0,§5.52 表):bit3 SOCKET_CLOSE
|
||||
* 需芯片 ≥0x46、TCP_SERVER 需 ≥0x44。本台架芯片实测 ≥0x46(TRAP-NET-20 定案
|
||||
* SOCKET_CLOSE 实际生效);门控防批次漂移——版本不足则**拒置 bit3**
|
||||
* (退回芯片自动关断语义)并 [ERR] 留痕,不静默带病运行 */
|
||||
@@ -479,7 +479,7 @@ int net_poll(void) {
|
||||
/* 读取全局中断状态(2 字节):读操作本身会清除 CH395F 中断并使其拉高 INT#,
|
||||
* 若此后仍有新中断,CH395F 会再次拉低 INT#,由下一次 net_poll() 处理 */
|
||||
int_status = ch395f_get_glob_int_status_all();
|
||||
/* N34 阶段 3(F-DRV-13 接线):把全局位喂驱动——bit2 PHY_CHANGE 时驱动
|
||||
/* 自愈收敛阶段 3(F-DRV-13 接线):把全局位喂驱动——bit2 PHY_CHANGE 时驱动
|
||||
* 重读 PHY 更新 link_up 缓存 + 变化计数,net 层在 reconciler 订阅留痕
|
||||
* (运行期拔网线不再静默;不自动重配,重配仍走 UI/配置引擎路径) */
|
||||
ch395f_glob_event_feed(int_status);
|
||||
@@ -561,7 +561,7 @@ int net_poll(void) {
|
||||
/* 因此每次 net_poll() 只处理“一批”,剩余数据在后续轮询中读取 */
|
||||
} while (0);
|
||||
|
||||
/* N34 阶段 3(§5 项 1 基础):每轮全量刷新在用 Socket 的驱动状态缓存
|
||||
/* 自愈收敛阶段 3(§5 项 1 基础):每轮全量刷新在用 Socket 的驱动状态缓存
|
||||
* (唯一刷新点;E2 实测单次回读 18.1us,在用 5~6 个 ≈100us ≪ 1ms 轮询
|
||||
* 周期)。reconciler / 探针 / 镜像降级决策点一律读缓存(
|
||||
* ch395f_sock_state_cached),不再各自发状态 SPI。放在中断处理之后:
|
||||
@@ -569,7 +569,7 @@ int net_poll(void) {
|
||||
for (int i = 0; i < NET_MAX_SOCKETS; i++) {
|
||||
if (s_net_socks[i].in_use != 0U) {
|
||||
(void)ch395f_get_sock_state((uint8_t)i);
|
||||
/* N34 阶段 3(E-02 收口):驱动 sock_reset 状态机在 net_poll 步进
|
||||
/* 自愈收敛阶段 3(E-02 收口):驱动 sock_reset 状态机在 net_poll 步进
|
||||
* (驱动头注释契约"在 net_poll 或测试循环里周期调用")。IDLE 槽位
|
||||
* 纯 RAM 判返回 0 无 SPI;仅活跃复位机做短 SPI。作用:同步包装
|
||||
* (net_sock_reset_sync)600ms 放弃后复位机不搁浅,芯片条件满足
|
||||
@@ -579,9 +579,9 @@ int net_poll(void) {
|
||||
}
|
||||
|
||||
#if NET_U15_PROBE
|
||||
/* E6 探测(宏说明见文件前部):RX 非空而 readable=0 = RECV_OK 中断丢失
|
||||
/* E6 探测(宏说明见文件前部):RX 非空而 readable=0 = RECV_OK 事件未收到
|
||||
* 的数据面形态。**两级确认去良性竞态**:数据刚到、本轮中断尚未读取的
|
||||
* 竞态窗(≤1 个 poll)会在下一探测轮自然消失;丢中断则持续存在直到
|
||||
* 竞态窗(≤1 个 poll)会在下一探测轮自然消失;事件未收到则持续存在直到
|
||||
* 盲收/超时。候选轮标记 → 下一探测轮仍成立才计确认命中。排除 CLOSED:
|
||||
* closed-with-data 是已知被救回形态,非 U15 假设对象。独立于上面的
|
||||
* 缓存刷新环:GET_RECV_LEN 是独立 SPI。 */
|
||||
@@ -621,23 +621,22 @@ int net_poll(void) {
|
||||
return event_count;
|
||||
}
|
||||
|
||||
/* 对账+pump 合并周期(N34 阶段 3:原 200ms 对账 / 100ms pump 合一) */
|
||||
/* 对账+pump 合并周期(自愈收敛阶段 3:原 200ms 对账 / 100ms pump 合一) */
|
||||
#define NET_RECONCILE_PERIOD_MS 100U
|
||||
/* 同一 socket 两次动手的最小间隔(防抖成风暴) */
|
||||
#define NET_RECONCILE_COOLDOWN_MS 1000U
|
||||
/* 分级去抖门槛(单位=轮) */
|
||||
#define NET_RECON_STABLE_ACCEPT 1U /* 形态② 丢 CONNECT 补 accept(幽灵甄别兜底假阳性) */
|
||||
#define NET_RECON_STABLE_ACCEPT 1U /* 形态② CONNECT 事件未收到补 accept(幽灵甄别兜底假阳性) */
|
||||
#define NET_RECON_STABLE_RELISTEN 2U /* 形态③④ 监听失位重建 / ⑤ 静默回收 RESYNC */
|
||||
#define NET_RECON_STABLE_DEATH 4U /* 形态① 连接已失(M3 让位窗 400ms,勿改小) */
|
||||
|
||||
/*
|
||||
* 函数功能:芯片/本层 socket 状态周期对账(TRAP-NET-17 丢中断自愈)+ 监听器 pump
|
||||
* (N-32 P2)—— N34 阶段 3 合并为单一 100ms tick(docs/网络/N34-自愈审计.md §5.5 项 1)
|
||||
* 函数功能:芯片/本层 socket 状态周期对账(TRAP-NET-17 事件面未收到自愈,E14 复核:非芯片丢事件是被读清消费)+ 监听器 pump(N-32 P2)—— 自愈收敛阶段 3 合并为单一 100ms tick(docs/网络/网络自愈架构设计.md §4.1)
|
||||
* 入口参数:无
|
||||
* 出口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:netTask 上下文(由 net_process_messages 每轮调用)
|
||||
* 函数说明:1. 芯片快速复连会丢 CONNECT/DISCONNECT 中断,本层无法靠事件自愈
|
||||
* 函数说明:1. 芯片快速复连会收不到 CONNECT/DISCONNECT 事件(读清消费竞态,E14 复核:非芯片丢事件),本层无法靠事件自愈
|
||||
* 2. 判据读**驱动状态缓存**(唯一刷新点=net_poll 每轮全量刷新,E2 实测单次回读 18.1us)
|
||||
* 3. 覆盖形态(原对账①②⑤ + 原 pump③④/U11):
|
||||
* ① 本层 ESTABLISHED 而芯片已无连接 → 按断开处理(只置事实)
|
||||
@@ -702,7 +701,7 @@ static void net_reconcile_tick(void) {
|
||||
int listener_fd = ((p_sock->auto_relisten != 0U) &&
|
||||
(p_sock->type == NET_SOCK_STREAM) &&
|
||||
(p_sock->local_port != 0U));
|
||||
/* 失同步类型:1=连接已失 2=握手已成丢中断 3=监听失位 4=孤儿监听
|
||||
/* 失同步类型:1=连接已失 2=握手已成事件未收到 3=监听失位 4=孤儿监听
|
||||
* 5=芯片静默回收回监听(编号沿用历史口径,U11 重同步不设编号——被动零动作) */
|
||||
int bad = 0;
|
||||
/* 本形态去抖门槛(默认按重建档) */
|
||||
@@ -720,14 +719,14 @@ static void net_reconcile_tick(void) {
|
||||
stable_need = NET_RECON_STABLE_DEATH;
|
||||
} else if ((c.open != CH395F_SOCKET_CLOSED) &&
|
||||
(c.tcp_state == CH395F_TCP_LISTEN)) {
|
||||
/* ⑤(F-NET-2 缺口,N34 阶段1):芯片静默回收——本层 ESTABLISHED
|
||||
/* ⑤(F-NET-2 缺口,自愈收敛阶段1):芯片静默回收——本层 ESTABLISHED
|
||||
* 而芯片已自行把 Socket 收回 LISTEN(0x05/0x01,**不发 DISCONNECT
|
||||
* 中断**,run8 台架实证)→ RESYNC 语义 */
|
||||
bad = 5;
|
||||
}
|
||||
} else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
if (c.tcp_state == CH395F_TCP_ESTABLISHED) {
|
||||
/* ② 本层 LISTENING 而芯片已完成握手(丢 CONNECT 中断)→ 补做 accept
|
||||
/* ② 本层 LISTENING 而芯片已完成握手(CONNECT 事件未收到)→ 补做 accept
|
||||
* N-30(TRAP-NET-20)幽灵态甄别:拆链收尾窗口内芯片假报 ESTABLISHED,
|
||||
* 回读对端端口 = 上一条连接端口 → 不补 accept(补了会把数据发给
|
||||
* 已死的旧连接 = 生产 LIST#4 数据被吞的直接成因),等拆净或新 SYN。
|
||||
@@ -736,7 +735,7 @@ static void net_reconcile_tick(void) {
|
||||
ch395f_get_remot_ipp((uint8_t)i, remote);
|
||||
uint16_t peer = (uint16_t)(remote[4] | (remote[5] << 8));
|
||||
/* 仅"端口非零且 = 上一条连接端口"判幽灵拦截;peer==0 不拦截
|
||||
* (对端端口提交滞后时不得挡掉丢中断救援,见 net_lost_connect_probe 注释) */
|
||||
* (对端端口提交滞后时不得挡掉事件未收口的救援,见 net_lost_connect_probe 注释) */
|
||||
if (!((peer != 0U) && (peer == p_sock->last_peer_port))) {
|
||||
bad = 2;
|
||||
stable_need = NET_RECON_STABLE_ACCEPT;
|
||||
@@ -796,7 +795,7 @@ static void net_reconcile_tick(void) {
|
||||
handle_disconnect_event(p_sock);
|
||||
} else if (bad == 5) {
|
||||
/* 类型⑤:静默回收 → RESYNC 语义(原 NET_MSG_RESYNC_LISTEN 分派体
|
||||
* 原样并入,N34 阶段1;纪律同 U11:**不发任何芯片命令**——
|
||||
* 原样并入,自愈收敛阶段1;纪律同 U11:**不发任何芯片命令**——
|
||||
* 重下发 close/重监听会摧毁芯片侧健康监听器 → 端口永拒,
|
||||
* run8 实证 170s 拒绝) */
|
||||
DBG_INFO("sock%d reconcile: chip re-listened w/o DISCONNECT (0x%02X/0x%02X) -> resync",
|
||||
@@ -838,8 +837,8 @@ static void net_reconcile_tick(void) {
|
||||
* 2. net_listener_retry_tick(D10):断连后按 30ms(NET_RELISTEN_RETRY_MS)
|
||||
* 节拍重试 open+listen,2s 总时限到期放弃留痕;本 fd 有在途挂起 recv 时跳过(L3 保险)
|
||||
* 3. net_pending_tick(L3):按节拍了结挂起 recv(数据/到点[仅显式预算]/断连);
|
||||
* L3 tripwire(N34 阶段 1.5):挂起超 60s 只 DBG_ERROR 留痕一次,不再强制了结/伪造返回值
|
||||
* 4. net_reconcile_tick(TRAP-NET-17 + pump 合并,N34 阶段 3):每 100ms 对账
|
||||
* L3 tripwire(自愈收敛阶段 1.5):挂起超 60s 只 DBG_ERROR 留痕一次,不再强制了结/伪造返回值
|
||||
* 4. net_reconcile_tick(TRAP-NET-17 + pump 合并,自愈收敛阶段 3):每 100ms 对账
|
||||
* ①②⑤ + ③④ 重建 + U11 重同步,判据读驱动状态缓存(net_poll 每轮
|
||||
* 全量刷新,E2 背书);去抖分级(②=1 轮/③④⑤=2 轮/①=4 轮,M3 让位窗)
|
||||
* + 1s 冷却;重建失败进 D10 重试队列,reconciler 不重复催
|
||||
@@ -861,7 +860,7 @@ void net_process_messages(void) {
|
||||
net_listener_retry_tick();
|
||||
/* L3 挂起 recv 完成检查:数据到达 / 到点 / 断连时通知调用方 */
|
||||
net_pending_tick();
|
||||
/* TRAP-NET-17 状态对账 + 监听器 pump(N34 阶段 3 合并单一 100ms tick):
|
||||
/* TRAP-NET-17 状态对账 + 监听器 pump(自愈收敛阶段 3 合并单一 100ms tick):
|
||||
* 判据读驱动缓存(net_poll 每轮全量刷新),①②⑤ 失同步 + ③④ 重建 +
|
||||
* U11 重同步全部在此(本层唯一周期重建入口,N-32 P2 单一所有者) */
|
||||
net_reconcile_tick();
|
||||
@@ -952,7 +951,7 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_DROP_CONN: {
|
||||
/* N34 阶段 3(E-02 收口):应用放弃会话的主动拆除(拆连接、保监听) */
|
||||
/* 自愈收敛阶段 3(E-02 收口):应用放弃会话的主动拆除(拆连接、保监听) */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
/* 描述符无效 → BADF */
|
||||
@@ -971,7 +970,7 @@ void net_process_messages(void) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* N34 阶段1(F-NET-3):NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 两个
|
||||
/* 自愈收敛阶段1(F-NET-3):NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 两个
|
||||
* 手动自愈消息已删——RESYNC 语义并入对账⑤(net_reconcile_tick),
|
||||
* RELISTEN 与 reconciler/D10 完全重叠且对健康监听器是 footgun;
|
||||
* 生产调用者本就为零(仅 test/board Phase 13,已改由自动机制接管) */
|
||||
@@ -1095,7 +1094,7 @@ int net_socket(int domain, int type) {
|
||||
p_sock->send_ready = 1;
|
||||
/* 无可读数据 */
|
||||
p_sock->readable = 0;
|
||||
/* N34 阶段 1.5:阻塞模式默认 = 阻塞(BSD/Python 语义;非阻塞用
|
||||
/* 自愈收敛阶段 1.5:阻塞模式默认 = 阻塞(BSD/Python 语义;非阻塞用
|
||||
* net_setblocking(fd, 0) 显式设置)。close 的 memset 会清零本字段,
|
||||
* 新 fd 必须在此显式置 1(同 released_abnormal 的"不得继承"纪律) */
|
||||
p_sock->blocking = 1;
|
||||
@@ -1222,7 +1221,7 @@ int net_bind(int sockfd, const struct net_sockaddr *addr, int addrlen) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:驱动 sock_reset 原语的有界确定性排渣等待(P2b 收口,N34 阶段 3;
|
||||
* 函数功能:驱动 sock_reset 原语的有界确定性排渣等待(P2b 收口,自愈收敛阶段 3;
|
||||
* 替代原"close + 盲等 500ms"式忙等)
|
||||
* 入口参数:sockfd - Socket 描述符 (0~7) int
|
||||
* mode - CH395F_RESET_GRACEFUL(等 100ms)/ QUARANTINE(等 400ms)
|
||||
@@ -1298,7 +1297,7 @@ int net_listen_locked(int sockfd) {
|
||||
ch395f_set_sour_port(sockfd, p_sock->local_port);
|
||||
|
||||
/* CH395F 关闭 Socket 后需延时才能重新打开(TRAP-NET-09),故失败重试最多 3 次。
|
||||
* P2b 收口(N34 阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
|
||||
* P2b 收口(自愈收敛阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
|
||||
* sock_reset(读空 RX -> CLOSE -> 排空事件 -> 等 byte0=00H,内置 LISTEN
|
||||
* 态二段 CLOSE 补发;E4 定案 60 轮实证复位后 open 必成)。GRACEFUL
|
||||
* 最短等 100ms ≪ 原 500ms 盲等;复位失败/超时仍走下一轮重试,TRAP-NET-09 语义保留 */
|
||||
@@ -1316,24 +1315,14 @@ int net_listen_locked(int sockfd) {
|
||||
if (status != CH395F_ERR_SUCCESS) {
|
||||
return NET_ERR_RETURN_1(NET_ERR_BUSY);
|
||||
}
|
||||
/* 下发 TCP LISTEN 命令,进入监听状态 */
|
||||
status = ch395f_tcp_listen(sockfd);
|
||||
/* LISTEN 失败 → BUSY */
|
||||
if (status != CH395F_ERR_SUCCESS) {
|
||||
/* 0-3(N34 阶段0,U12 对称):open 已成而 LISTEN 失败必须 close,
|
||||
* 否则芯片 Socket 卡"OPEN 无监听"、后续 open 恒返 USE(同
|
||||
* net_relisten_locked 对应分支) */
|
||||
ch395f_close_socket(sockfd);
|
||||
return NET_ERR_RETURN_1(NET_ERR_BUSY);
|
||||
}
|
||||
|
||||
/* 监听 Socket 进入 LISTENING 态 */
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* 单连接模式:连接断开后由 net 层自动回到 LISTEN(模拟 BSD 监听常驻) */
|
||||
p_sock->auto_relisten = 1;
|
||||
/* N-30(TRAP-NET-20):新监听会话,丢中断去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
/* 读即清:仅本 Socket 的中断状态——丢弃上一条会话残留的 DISCONNECT/
|
||||
/* 排事件(读即清)必须在 LISTEN 命令**之前**(E14 复核实验 2026-10-14:
|
||||
* 原形态为 listen 后读清——快速复连时新连接的 CONNECT 在 LISTEN 生效后、
|
||||
* 读清前落进 SINT,被本方读清吞掉,即"CONNECT 事件未收到→数据被吞"的
|
||||
* 生产侧自伤机制(台架矩阵 3/48 被 drain-int 探针现场抓获);芯片侧
|
||||
* 从不丢事件。挪前后若仍有滞后 DISCONNECT 落进新会话,
|
||||
* handle_disconnect_event 的 LISTENING 分支回读状态裁决(状态面为真相),
|
||||
* 无害。
|
||||
* 读即清:仅本 Socket 的中断状态——丢弃上一条会话残留的 DISCONNECT/
|
||||
* TIMEOUT,避免监听刚开始就误触发事件。
|
||||
* ⚠ B3(2026-10-12 审计):此处原为"遍历 8 个 Socket 全清 + 再读清全局",
|
||||
* git 考古证明是多连接时代的调试遗留(e862009bc 无注释引入 → 319d00e3
|
||||
@@ -1350,6 +1339,24 @@ int net_listen_locked(int sockfd) {
|
||||
* 本次未动。 */
|
||||
(void)ch395f_get_sock_int_status((uint8_t)sockfd);
|
||||
|
||||
/* 下发 TCP LISTEN 命令,进入监听状态 */
|
||||
status = ch395f_tcp_listen(sockfd);
|
||||
/* LISTEN 失败 → BUSY */
|
||||
if (status != CH395F_ERR_SUCCESS) {
|
||||
/* 0-3(自愈收敛阶段0,U12 对称):open 已成而 LISTEN 失败必须 close,
|
||||
* 否则芯片 Socket 卡"OPEN 无监听"、后续 open 恒返 USE(同
|
||||
* net_relisten_locked 对应分支) */
|
||||
ch395f_close_socket(sockfd);
|
||||
return NET_ERR_RETURN_1(NET_ERR_BUSY);
|
||||
}
|
||||
|
||||
/* 监听 Socket 进入 LISTENING 态 */
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* 单连接模式:连接断开后由 net 层自动回到 LISTEN(模拟 BSD 监听常驻) */
|
||||
p_sock->auto_relisten = 1;
|
||||
/* N-30(TRAP-NET-20):新监听会话,事件未收到去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
|
||||
/* 监听建立完成 */
|
||||
return 0;
|
||||
}
|
||||
@@ -1414,27 +1421,29 @@ int net_listen(int sockfd) {
|
||||
* 限定条件:Socket 处于 LISTENING 状态
|
||||
* 函数说明:单连接:监听 Socket 自身在 CONNECT 后已转为 ESTABLISHED
|
||||
*/
|
||||
/* ===== N-30 accept 路径"丢 CONNECT 中断"补 accept(2026-10-11 裸机芯片台架实证)=====
|
||||
/* ===== N-30 accept 路径"CONNECT 事件未收到补 accept"(2026-10-11 台架实证;
|
||||
* E14 复核 2026-10-14:事件非芯片侧丢失,是被读清消费——机制不变)=====
|
||||
* 台架结论(剥离 OS/net/FTP 直接对芯片做受控 close→open→listen→connect 矩阵):
|
||||
* 芯片关闭连接后的拆链收尾窗口**变长且不可见**(状态寄存器显示 CLOSED 也不代表
|
||||
* 拆完,实测 >2s 仍可能未拆完);该窗口内重新 listen 后,新连接握手照常完成
|
||||
* (芯片状态寄存器 → ESTABLISHED)但 **CONNECT 中断被丢**——纯事件驱动的 accept
|
||||
* (芯片状态寄存器 → ESTABLISHED)但 **CONNECT 事件未收到**(E14 复核:被读清
|
||||
* 消费竞态吞掉)——纯事件驱动的 accept
|
||||
* 永远等不到 → 数据被吞 / 425。固定沉降延时、Socket 轮换、listen 后 close 重试、
|
||||
* 缓冲重分配均已被实验证伪;唯一有效 = "中断 + 状态轮询"双信源(修复组 15/15
|
||||
* 全过,机制触发 5 次全部救回)。→ CH395F_Trap_Records.md TRAP-NET-20
|
||||
* 幽灵态甄别:拆链窗口内芯片也会直接假报 ESTABLISHED(旧连接未拆净),此时回读
|
||||
* 对端端口 = 上一条连接端口;新连接临时端口几乎必然不同 → 端口相同不 accept,
|
||||
* 等旧连接拆净 / 新 SYN 到达(新连接若也丢中断,后续轮询以新端口命中)。 */
|
||||
* 等旧连接拆净 / 新 SYN 到达(新连接若事件也未收到,后续轮询以新端口命中)。 */
|
||||
|
||||
/*
|
||||
* 函数功能:监听等待期的芯片状态轮询探针——芯片已 ESTABLISHED 而 CONNECT 中断
|
||||
* 未到(丢中断)时补做 accept(复用 CONNECT 事件簿记路径)。
|
||||
* 函数功能:监听等待期的芯片状态轮询探针——芯片已 ESTABLISHED 而 CONNECT 事件
|
||||
* 未收到时补做 accept(复用 CONNECT 事件簿记路径)。
|
||||
* 入口参数:p_sock - 处于 LISTENING 的监听控制块 net_sock_t *
|
||||
* 出口参数:无(命中时 p_sock->state 经 handle_connect_event 转 ESTABLISHED)
|
||||
* 返回值:无
|
||||
* 限定条件:netTask 上下文(net_accept_locked 内调用,其开头已 net_poll(),
|
||||
* 驱动缓存新鲜度有保证)
|
||||
* 函数说明:1. N34 阶段 3(F-MS-9):判据改读**驱动状态缓存**(零 SPI;唯一
|
||||
* 函数说明:1. 自愈收敛阶段 3(F-MS-9):判据改读**驱动状态缓存**(零 SPI;唯一
|
||||
* 刷新点=net_poll),**探针去抖删除**——原去抖防的两类瞬态已
|
||||
* 结构性消除:"刚 listen 尚未生效"显示 TCP=00 永不命中 ESTABLISHED
|
||||
* 门(E2:LISTEN 可见 100% <=10ms 无长尾);拆链窗假 ESTABLISHED
|
||||
@@ -1458,16 +1467,16 @@ static void net_lost_connect_probe(net_sock_t *p_sock) {
|
||||
uint16_t peer = (uint16_t)(remote[4] | (remote[5] << 8));
|
||||
/* 幽灵甄别:仅"端口非零且 = 上一条连接端口"才判幽灵拦截;
|
||||
* peer==0(芯片对端端口提交滞后,TRAP-NET-13 同类)不拦截——宁可补 accept
|
||||
* 也不退回丢中断死等(2026-10-11 验证轮实测:peer==0 拦截把首连接
|
||||
* 丢中断的原有对账救援也挡死,LIST#1 卡满 20s,比修复前更糟) */
|
||||
* 也不退回事件未收口的死等(2026-10-11 验证轮实测:peer==0 拦截把首连接
|
||||
* 事件未收到的原有对账救援也挡死,LIST#1 卡满 20s,比修复前更糟) */
|
||||
if ((peer != 0U) && (peer == p_sock->last_peer_port)) {
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
return;
|
||||
}
|
||||
/* N34 阶段 3(F-MS-9):去抖已删(判据读缓存,两类瞬态结构性消除,
|
||||
/* 自愈收敛阶段 3(F-MS-9):去抖已删(判据读缓存,两类瞬态结构性消除,
|
||||
* 见函数头注释 1);lost_conn_seen 仅作 M3 可疑电平标志用,动手前清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
/* 留痕:丢中断自愈命中 */
|
||||
/* 留痕:事件未收到自愈命中 */
|
||||
DBG_INFO("sock%d lost-CONNECT self-accept (peer=%u)",
|
||||
(int)p_sock->ch395_sock, peer);
|
||||
/* 复用 CONNECT 事件的簿记路径(转 ESTABLISHED + 记对端 + 事件回调) */
|
||||
@@ -1482,7 +1491,7 @@ static void net_lost_connect_probe(net_sock_t *p_sock) {
|
||||
* 返回值:新连接的 Socket 描述符,失败返回 -1 int
|
||||
* 限定条件:Socket 处于 LISTENING 状态
|
||||
* 函数说明:1. 单连接:监听 Socket 自身在 CONNECT 后已转为 ESTABLISHED
|
||||
* 2. 等待期叠加芯片状态轮询探针(丢 CONNECT 中断自愈,TRAP-NET-20)
|
||||
* 2. 等待期叠加芯片状态轮询探针(CONNECT 事件未收到自愈,TRAP-NET-20)
|
||||
* 3. CLOSED + 芯片 RX 缓冲有残留数据:接受"已关但可读"连接排空
|
||||
* (FUN_PARA §5.52 ② 保留现场契约,TRAP-NET-20 三次定案)
|
||||
*/
|
||||
@@ -1500,9 +1509,10 @@ static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen
|
||||
/* 先轮询一次:把状态机刷新到芯片侧最新状态 */
|
||||
net_poll();
|
||||
|
||||
/* N-30(TRAP-NET-20):监听等待期兼做芯片状态第二信源——丢 CONNECT 中断时
|
||||
* 去抖补 accept(裸机台架实证:拆链窗口丢中断是数据被吞/425 的主根因,
|
||||
* 纯事件等待无自愈可能;详见 net_lost_connect_probe 区块注释) */
|
||||
/* N-30(TRAP-NET-20):监听等待期兼做芯片状态第二信源——CONNECT 事件未收到时
|
||||
* 去抖补 accept(台架实证:拆链窗口事件未收到是数据被吞/425 的主根因,
|
||||
* E14 复核:事件非芯片丢失、被读清消费吞掉;纯事件等待无自愈可能;
|
||||
* 详见 net_lost_connect_probe 区块注释) */
|
||||
if (p_listen_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
net_lost_connect_probe(p_listen_sock);
|
||||
}
|
||||
@@ -1621,8 +1631,8 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
|
||||
return msg.result;
|
||||
}
|
||||
|
||||
/* N34 阶段1(F-NET-4):net_can_accept 已删除——它只认 ESTABLISHED,作为 accept
|
||||
* 门控会把"监听器在服役但本轮还没 CONNECT"的窗口全挡掉(:2404 丢 CONNECT 探针
|
||||
/* 自愈收敛阶段1(F-NET-4):net_can_accept 已删除——它只认 ESTABLISHED,作为 accept
|
||||
* 门控会把"监听器在服役但本轮还没 CONNECT"的窗口全挡掉(:2404 CONNECT 事件补 accept 探针
|
||||
* 因此从不运行,与已修的 :7003 探针失效同型);唯一生产调用者 iec104 已迁
|
||||
* net_listener_armed。net_can_read(RECV 门控)不受影响、保留。 */
|
||||
|
||||
@@ -1634,9 +1644,9 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen) {
|
||||
* 0 - 未就绪(fd 未分配 / 非监听型 / 正处隔离期以外的不就绪态) int
|
||||
* 限定条件:任意任务上下文;net_init() 已调用
|
||||
* 函数说明:1. N-32(P1 不变量 II):取代已退役的 net_can_accept()(要求
|
||||
* ESTABLISHED,N34 阶段1 删除)作为监听 accept 门控。原门控下
|
||||
* ESTABLISHED,自愈收敛阶段1 删除)作为监听 accept 门控。原门控下
|
||||
* :7003 永不进 net_accept →
|
||||
* net_lost_connect_probe(丢 CONNECT 中断补 accept)对该端口从不运行
|
||||
* net_lost_connect_probe(CONNECT 事件未收到补 accept)对该端口从不运行
|
||||
* (设计文档 §2.3 末"探针失效")
|
||||
* 2. 为什么放行 LISTENING:探针与"closed-but-readable 接受"(:1338)
|
||||
* 只在 net_accept_locked 内部发生,门控挡在外面就永远到不了;
|
||||
@@ -1659,13 +1669,13 @@ int net_listener_armed(int sockfd) {
|
||||
/* 连接已到、应用尚未 accept:单连接模型下 CONNECT 处理(net_poll 分派 /
|
||||
* 探针补 accept / 对账② standalone accept)把监听 fd 转 ESTABLISHED,
|
||||
* 这就是"待 accept"电平——**必须放行**(原 net_can_accept 唯一放行态;
|
||||
* N34 阶段1 i104 台架实证:200ms 任务周期抢不过对账②的 ~400ms 去抖,
|
||||
* 自愈收敛阶段1 i104 台架实证:200ms 任务周期抢不过对账②的 ~400ms 去抖,
|
||||
* 对账②先转 ESTABLISHED → 不放行则应用永不 accept、会话整场饿死)。
|
||||
* 无 RPC 风暴风险:此态下 accept 必返 fd,一次调用即离开本分支 */
|
||||
if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
|
||||
return 1;
|
||||
}
|
||||
/* 正常监听态:放行。net_lost_connect_probe(丢 CONNECT 补 accept)与常规
|
||||
/* 正常监听态:放行。net_lost_connect_probe(CONNECT 事件未收到补 accept)与常规
|
||||
* accept 都发生在 net_accept_locked 内部,门控挡在外面就永远到不了 */
|
||||
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
return 1;
|
||||
@@ -1700,7 +1710,7 @@ int net_listener_armed(int sockfd) {
|
||||
* 2. 非 ESTABLISHED / 描述符失效一律返回 1:必须让上层真的 recv 一次
|
||||
* 拿到 EOF/错误并复位自身状态,门掉它会把"连接已不存在"永久藏住
|
||||
* 3. ⚠ readable 仅由 RECV_OK 中断置位,TRAP-NET-17 对账不含"RX 非空但
|
||||
* readable=0" → 中断丢失时本函数恒返 0,调用方须保留低频兜底 recv
|
||||
* readable=0" → 事件未收到时本函数恒返 0,调用方须保留低频兜底 recv
|
||||
*/
|
||||
int net_can_read(int sockfd) {
|
||||
/* Socket 控制块(纯 RAM 读,可能为 NULL = 描述符越界或未分配) */
|
||||
@@ -1848,7 +1858,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
|
||||
ch395f_set_proto_type(sockfd, CH395F_PROTO_TYPE_TCP);
|
||||
|
||||
/* CH395F 关闭 Socket 后需延时才能重新打开(TRAP-NET-09),故失败重试最多 3 次。
|
||||
* P2b 收口(N34 阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
|
||||
* P2b 收口(自愈收敛阶段 3):原"close + 盲等 500ms"改**确定性排渣**——
|
||||
* sock_reset(读空 RX -> CLOSE -> 排空事件 -> 等 byte0=00H,内置 LISTEN
|
||||
* 态二段 CLOSE 补发;E4 定案 60 轮实证复位后 open 必成)。GRACEFUL
|
||||
* 最短等 100ms ≪ 原 500ms 盲等;复位失败/超时仍走下一轮重试,TRAP-NET-09 语义保留 */
|
||||
@@ -1869,7 +1879,7 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
|
||||
}
|
||||
|
||||
/* 清掉本 Socket 可能残留的中断状态,丢弃上一条连接遗留的 DISCONNECT。
|
||||
* F-NET-7(N34 阶段 3):只清**本 Socket** SINT(驱动护栏原语)——原
|
||||
* F-NET-7(自愈收敛阶段 3):只清**本 Socket** SINT(驱动护栏原语)——原
|
||||
* "再读清全局"会焊死其它在用 Socket 的事件位(全局寄存器唯一读者=net_poll) */
|
||||
(void)ch395f_sock_events((uint8_t)sockfd);
|
||||
|
||||
@@ -2070,7 +2080,7 @@ static int net_send_locked(net_sock_t *p_sock, const void *buf, int len) {
|
||||
* buf - 接收缓冲区指针 void *
|
||||
* len - 缓冲区大小 int > 0
|
||||
* flags - 标志位,NET_MSG_DONTWAIT 表示非阻塞 int
|
||||
* timeout_ms - 本次等待预算(0 = 无限等待,N34 阶段 1.5 起无默认值)uint32_t
|
||||
* timeout_ms - 本次等待预算(0 = 无限等待,自愈收敛阶段 1.5 起无默认值)uint32_t
|
||||
* caller - 调用方任务句柄(挂起请求的完成通知目标) TaskHandle_t
|
||||
* 出口参数:buf - 填充接收到的数据
|
||||
* 返回值:实际接收字节数(> 0);0 表示对端关闭;-1 表示出错/非阻塞无数据 int
|
||||
@@ -2078,7 +2088,7 @@ static int net_send_locked(net_sock_t *p_sock, const void *buf, int len) {
|
||||
* 限定条件:p_sock 非空;netTask 上下文
|
||||
* 函数说明:1. 数据已在(快速路径)→ 立即读出返回,行为与旧实现一致
|
||||
* 2. 非阻塞(NET_MSG_DONTWAIT 单次覆盖 **或** socket blocking 属性为 0,
|
||||
* N34 阶段 1.5 模式属性)无数据立即返回 -1(NET_ERR_WOULDBLOCK)
|
||||
* 自愈收敛阶段 1.5 模式属性)无数据立即返回 -1(NET_ERR_WOULDBLOCK)
|
||||
* 3. 无数据 + 阻塞等待 → 登记挂起请求(L3 pending 化,E-02 结构演进)
|
||||
* 4. netTask 零占用立即返回;完成条件(数据/到点[仅显式预算]/断连)由 net_pending_tick 按主循环节拍检查
|
||||
* 5. 并通知 caller;关闭/网络重建/陈旧重同步由对应路径显式了结(取消必通知)
|
||||
@@ -2095,7 +2105,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
}
|
||||
|
||||
/* 超时来源:只有调用方显式预算(net_recv_to);0 = 无限等待
|
||||
* (N34 阶段 1.5:NET_RECV_TIMEOUT_MS 30s 默认预算已删,API 不强加隐藏值) */
|
||||
* (自愈收敛阶段 1.5:NET_RECV_TIMEOUT_MS 30s 默认预算已删,API 不强加隐藏值) */
|
||||
uint32_t to_ms = timeout_ms;
|
||||
|
||||
/* 先轮询一次:刷新状态机与可读标志 */
|
||||
@@ -2119,7 +2129,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
}
|
||||
|
||||
/* 非阻塞模式:NET_MSG_DONTWAIT 单次覆盖,或 socket 的 blocking 属性为 0
|
||||
* (net_setblocking(fd, 0),N34 阶段 1.5 模式挂控制块属性) */
|
||||
* (net_setblocking(fd, 0),自愈收敛阶段 1.5 模式挂控制块属性) */
|
||||
if ((flags & NET_MSG_DONTWAIT) || (p_sock->blocking == 0U)) {
|
||||
/* 非阻塞且当前无数据:若连接已断开则视为 EOF(0) 并自动重监听,
|
||||
* 否则返回 WOULDBLOCK(-1) 表示暂时无数据 */
|
||||
@@ -2169,7 +2179,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
* 2. 清空整个控制块(memset 0),释放该 Socket 资源
|
||||
*/
|
||||
|
||||
/* ===== L3 挂起 recv 请求的实现(一期,2026-09-22;N34 阶段 1.5 语义主流化) =====
|
||||
/* ===== L3 挂起 recv 请求的实现(一期,2026-09-22;自愈收敛阶段 1.5 语义主流化) =====
|
||||
* 完成条件按 ①数据 ②到点(仅显式预算) ③断连 顺序检查(逐项对齐旧自旋循环语义)
|
||||
* ① 数据通道(ESTABLISHED/UDP_OPEN)内 readable 门控 SPI 读——常见无数据路径零额外 SPI 事务
|
||||
* (INT# 电平触发链保证缓冲有数据时每轮重读 SINT 重位置位)
|
||||
@@ -2179,7 +2189,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
* 旧注归"部分读归零"机理、已随复核注降级)→ 有数据按数据完成,否则 EOF(0) + 自动重监听
|
||||
* 其他状态(CONNECTING/LISTENING/…)保持等待状态迁移(CONNECT→ESTABLISHED 是合法路径;
|
||||
* 陈旧 resync 由显式取消处理)——不做状态推断取消,避免误杀正在建链的等待
|
||||
* tripwire(N34 阶段 1.5 降级):挂起超 60s = "完成逻辑缺位"探针 → 只 [ERR] 留痕一次,
|
||||
* tripwire(自愈收敛阶段 1.5 降级):挂起超 60s = "完成逻辑缺位"探针 → 只 [ERR] 留痕一次,
|
||||
* **绝不强制了结、绝不伪造 TIMEDOUT 返回值**(唤醒责任在 ①②③ 与显式 cancel 路径)
|
||||
*/
|
||||
|
||||
@@ -2222,7 +2232,7 @@ static void net_pending_complete(int sockfd, int result) {
|
||||
* 入口参数:sockfd - Socket 描述符 (0~7) int
|
||||
* buf - 调用方接收缓冲(须保持有效至完成) void *
|
||||
* len - 缓冲容量 int
|
||||
* to_ms - 本次等待预算(0 = 无限等待,N34 阶段 1.5) uint32_t
|
||||
* to_ms - 本次等待预算(0 = 无限等待,自愈收敛阶段 1.5) uint32_t
|
||||
* caller - 调用方任务句柄(完成通知目标) TaskHandle_t
|
||||
* 出口参数:无
|
||||
* 返回值:NET_PENDING_REGISTERED - 登记成功(分派跳过即时通知)
|
||||
@@ -2285,7 +2295,7 @@ static int net_pending_register(int sockfd, void *buf, int len,
|
||||
* 限定条件:netTask 上下文
|
||||
* 函数说明:1. 逐 fd 检查完成条件:数据到达 / 到点(仅显式预算)/ 断连
|
||||
* 2. 完成即经 net_pending_complete 通知并清除
|
||||
* 3. tripwire(N34 阶段 1.5):挂起超 NET_RECV_TRIPWIRE_MS 只 [ERR] 留痕
|
||||
* 3. tripwire(自愈收敛阶段 1.5):挂起超 NET_RECV_TRIPWIRE_MS 只 [ERR] 留痕
|
||||
* 一次("完成逻辑缺位"探针),绝不强制了结、绝不伪造返回值
|
||||
*/
|
||||
static void net_pending_tick(void) {
|
||||
@@ -2338,7 +2348,7 @@ static void net_pending_tick(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ② 到点(仅显式预算登记;无限等待登记无 deadline——N34 阶段 1.5:
|
||||
/* ② 到点(仅显式预算登记;无限等待登记无 deadline——自愈收敛阶段 1.5:
|
||||
* 超时是调用方策略,net_recv_to 的预算在此兑现,不是伪造。
|
||||
* tick 差值按有符号比较,抗回绕) */
|
||||
if ((p->infinite == 0U) && ((int32_t)(now - p->deadline) >= 0)) {
|
||||
@@ -2351,7 +2361,7 @@ static void net_pending_tick(void) {
|
||||
* 判据同 net_recv_locked(N-32 P1 不变量 I):`state == CLOSED ||
|
||||
* session_dead`。只判 CLOSED 时,抢先 relisten 后 ①(要求 ESTABLISHED)
|
||||
* 与 ③(要求 CLOSED) 两头落空 → 挂起的 recv 只能干等 ② deadline 超时
|
||||
* (lftpd 阻塞 recv 的"消费者卡死"原型)。N34 阶段 1.5 后该形态更致命:
|
||||
* (lftpd 阻塞 recv 的"消费者卡死"原型)。自愈收敛阶段 1.5 后该形态更致命:
|
||||
* 无限等待登记没有 ②,漏 ③ = 永久挂死(只剩 tripwire 留痕)——
|
||||
* ③ 与显式 cancel 是无限 recv 的全部唤醒责任方,勿动判据。 */
|
||||
if ((p_sock->state == NET_SOCK_STATE_CLOSED) || (p_sock->session_dead != 0U)) {
|
||||
@@ -2399,7 +2409,7 @@ static void net_pending_tick(void) {
|
||||
|
||||
/* 其他状态:保持等待(见本区块头注释) */
|
||||
|
||||
/* ④ tripwire(N34 阶段 1.5 降级,原"看门狗强制了结"):挂起超 60s =
|
||||
/* ④ tripwire(自愈收敛阶段 1.5 降级,原"看门狗强制了结"):挂起超 60s =
|
||||
* "完成逻辑缺位"探针 → 只 [ERR] 留痕一次,**绝不强制了结、绝不伪造
|
||||
* TIMEDOUT 返回值**(旧实现到点 +1s 兜底伪造 TIMEDOUT,掩盖完成路径
|
||||
* 缺陷;新语义下无限等待本就无预算,伪造返回值反而违背调用方意图)。
|
||||
@@ -2535,7 +2545,7 @@ static void net_pending_settle_close(net_sock_t *p_sock) {
|
||||
* 出口参数:无
|
||||
* 返回值:0 - 关闭成功 int
|
||||
* 限定条件:必须在 netTask 上下文中调用;p_sock 有效
|
||||
* 函数说明:1. P2b 收口(N34 阶段 3):原"close + 500ms 盲等排空循环"改
|
||||
* 函数说明:1. P2b 收口(自愈收敛阶段 3):原"close + 500ms 盲等排空循环"改
|
||||
* **确定性 sock_reset**(读空 RX -> CLOSE(幂等) -> 排空本 Socket
|
||||
* 事件(quiescent) -> 等 byte0=00H,内置 LISTEN 态二段 CLOSE 补发
|
||||
* ——E2 补充发现:一次 CLOSE 只拆监听 byte0 恒 05)
|
||||
@@ -2582,7 +2592,7 @@ static int net_close_locked(net_sock_t *p_sock) {
|
||||
* 出口参数:无
|
||||
* 返回值:0 - 拆除完成(监听型 fd 已重监听或交 D10) int
|
||||
* 限定条件:netTask 上下文;p_sock 在用且为 TCP 流
|
||||
* 函数说明:1. E-02 收口(实验方案 E13 §5):应用放弃的会话若 TCP 仍活
|
||||
* 函数说明:1. E-02 收口(《网络自愈架构设计》§5.2 E13):应用放弃的会话若 TCP 仍活
|
||||
* (PC 内核自动 ACK keepalive,僵尸判不死),单连接监听被永久
|
||||
* 占住;应用又不得 net_close 监听 fd(毁监听)——本函数补上
|
||||
* "拆连接不拆监听"的应用侧形态
|
||||
@@ -2610,7 +2620,7 @@ static int net_drop_conn_locked(net_sock_t *p_sock) {
|
||||
/* 会话簿记收口(保留 fd:不 memset、不动 local_port/auto_relisten) */
|
||||
p_sock->state = NET_SOCK_STATE_CLOSED;
|
||||
p_sock->readable = 0U;
|
||||
/* N-30(TRAP-NET-20):新会话起点,丢中断去抖计数清零 */
|
||||
/* N-30(TRAP-NET-20):新会话起点,事件未收到去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
|
||||
if (p_sock->auto_relisten) {
|
||||
@@ -2700,7 +2710,7 @@ int net_send(int sockfd, const void *buf, int len, int flags) {
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(线程安全版本,通过消息队列委托给 netTask;
|
||||
* **默认无限阻塞**——N34 阶段 1.5 语义主流化,30s 默认预算已删)
|
||||
* **默认无限阻塞**——自愈收敛阶段 1.5 语义主流化,30s 默认预算已删)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 接收缓冲区指针 void *
|
||||
* len - 缓冲区大小 int > 0
|
||||
@@ -2744,7 +2754,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
|
||||
msg.len = len;
|
||||
/* 标志:0=按 socket 阻塞属性,NET_MSG_DONTWAIT=单次非阻塞 */
|
||||
msg.flags = flags;
|
||||
/* 0 = 无限等待(N34 阶段 1.5:无默认预算;显式预算走 net_recv_to) */
|
||||
/* 0 = 无限等待(自愈收敛阶段 1.5:无默认预算;显式预算走 net_recv_to) */
|
||||
msg.timeout_ms = 0U;
|
||||
/* 调用方任务句柄(netTask 凭它回传回执) */
|
||||
msg.caller = xTaskGetCurrentTaskHandle();
|
||||
@@ -2770,7 +2780,7 @@ int net_recv(int sockfd, void *buf, int len, int flags) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(非阻塞具名入口——N34 阶段 1.5 把 NET_MSG_DONTWAIT 路径转正,
|
||||
* 函数功能:接收数据(非阻塞具名入口——自愈收敛阶段 1.5 把 NET_MSG_DONTWAIT 路径转正,
|
||||
* 对齐 BSD recv(MSG_DONTWAIT) / Python recv 非阻塞模式的"名如其义")
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf - 接收缓冲区指针 void *
|
||||
@@ -2790,7 +2800,7 @@ int net_recv_nb(int sockfd, void *buf, int len) {
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(带调用方指定超时的阻塞版,用于分片有界读;
|
||||
* N34 阶段 1.5 起为**显式预算**便捷入口,等价 Python settimeout,
|
||||
* 自愈收敛阶段 1.5 起为**显式预算**便捷入口,等价 Python settimeout,
|
||||
* 不再有隐藏默认值)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* buf / len - 接收缓冲与容量 void * / int > 0
|
||||
@@ -2822,7 +2832,7 @@ int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms) {
|
||||
}
|
||||
|
||||
/* ---- 3. 分片长度检查:timeout_ms = 0 在 netTask 侧意味着"**无限等待**"
|
||||
* (N34 阶段 1.5 删除 30s 默认预算),恰与本接口"有界等待"的存在
|
||||
* (自愈收敛阶段 1.5 删除 30s 默认预算),恰与本接口"有界等待"的存在
|
||||
* 理由相反,直接拒绝 ---- */
|
||||
if (timeout_ms == 0U) {
|
||||
/* 分片长度必须 > 0 */
|
||||
@@ -2944,7 +2954,7 @@ int net_close(int sockfd) {
|
||||
* 2. 场景=应用放弃会话(对时 30s 预算耗尽、协议超时);EOF 路径**不要**调
|
||||
* (net 层 auto_relisten 已接管,见 AGENTS 单连接断开语义)
|
||||
* 函数说明:1. 单连接模型下挂起但 TCP 仍活的客户端会永久占住监听(keepalive
|
||||
* 被 PC 内核自动 ACK 判不死,实验方案 E13 §5);应用不得
|
||||
* 被 PC 内核自动 ACK 判不死,《网络自愈架构设计》§5.2 E13);应用不得
|
||||
* net_close 监听 fd → 本 API 拆连接不拆监听(E-02 收口)
|
||||
* 2. netTask 侧执行 sock_reset QUARANTINE + 监听即时重建(见
|
||||
* net_drop_conn_locked);等待期 netTask 有界占用 ~400-600ms
|
||||
@@ -3131,7 +3141,7 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
* 限定条件:Socket 已创建且为 UDP 类型(SOCK_DGRAM);net_init() 已调用;有数据可用
|
||||
* 函数说明:1. 轮询检查芯片接收缓冲(net_poll + get_recv_len),有数据即返回
|
||||
* 2. UDP 数据报前 8 字节为报文头(源端口+源 IP),据此填充 src_addr
|
||||
* 3. 无数据时(N34 阶段 1.5,与 net_recv 同构):DONTWAIT / 非阻塞属性
|
||||
* 3. 无数据时(自愈收敛阶段 1.5,与 net_recv 同构):DONTWAIT / 非阻塞属性
|
||||
* 立即返回 -1(WOULDBLOCK);阻塞模式**无限等待**(30s 默认预算已删;
|
||||
* 本接口为轮询自旋实现且无生产调用者,受 IWDG 监控的任务勿用无限形态)
|
||||
*/
|
||||
@@ -3158,7 +3168,7 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
return NET_ERR_RETURN_1(NET_ERR_INVAL);
|
||||
}
|
||||
|
||||
/* 轮询直到:有数据 / 非阻塞(N34 阶段 1.5:阻塞 = 无限等待,无默认预算) */
|
||||
/* 轮询直到:有数据 / 非阻塞(自愈收敛阶段 1.5:阻塞 = 无限等待,无默认预算) */
|
||||
while (1) {
|
||||
/* 轮询一次:更新状态机与可读标志 */
|
||||
net_poll();
|
||||
@@ -3211,13 +3221,13 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
}
|
||||
|
||||
/* 非阻塞模式:NET_MSG_DONTWAIT 单次覆盖,或 socket blocking 属性为 0
|
||||
* (N34 阶段 1.5,与 net_recv_locked 同判据):无数据立即返回 */
|
||||
* (自愈收敛阶段 1.5,与 net_recv_locked 同判据):无数据立即返回 */
|
||||
if ((flags & NET_MSG_DONTWAIT) || (p_sock->blocking == 0U)) {
|
||||
/* 置 WOULDBLOCK */
|
||||
return NET_ERR_RETURN_1(NET_ERR_WOULDBLOCK);
|
||||
}
|
||||
|
||||
/* 阻塞模式:无数据继续轮询等待(N34 阶段 1.5:无限等待,无默认预算——
|
||||
/* 阻塞模式:无数据继续轮询等待(自愈收敛阶段 1.5:无限等待,无默认预算——
|
||||
* 旧 NET_RECV_TIMEOUT_MS 30s 兜底已删;唤醒源 = 数据,与 net_recv 的
|
||||
* 差异是本接口为自旋实现,勿在受 IWDG 监控任务中使用无限形态) */
|
||||
}
|
||||
@@ -3324,7 +3334,7 @@ int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:设置 Socket 阻塞/非阻塞**模式属性**(N34 阶段 1.5,模式挂控制块属性,
|
||||
* 函数功能:设置 Socket 阻塞/非阻塞**模式属性**(自愈收敛阶段 1.5,模式挂控制块属性,
|
||||
* 对齐 BSD O_NONBLOCK / Python setblocking)
|
||||
* 入口参数:sockfd - Socket 描述符 int >= 0 && < NET_MAX_SOCKETS
|
||||
* on - 1 = 阻塞(net_socket 默认);0 = 非阻塞 int
|
||||
@@ -3402,7 +3412,7 @@ int net_sock_state(int sockfd) {
|
||||
return (int)s_net_socks[sockfd].state;
|
||||
}
|
||||
|
||||
/* N34 阶段1(F-NET-3):手动自愈 API net_resync_listen / net_relisten 已删除——
|
||||
/* 自愈收敛阶段1(F-NET-3):手动自愈 API net_resync_listen / net_relisten 已删除——
|
||||
* RESYNC 语义并入对账⑤(net_reconcile_tick 自动认领"芯片静默回收回 LISTEN"形态,
|
||||
* 200ms×2 去抖 + 1s 冷却沿用);RELISTEN 与 reconciler/D10 完全重叠且对健康监听器是
|
||||
* footgun(无条件 open→USE→close 自毁 ~1s,原注释自认)。生产调用者本就为零
|
||||
@@ -3458,7 +3468,7 @@ uint32_t net_inet_addr(const char *cp) {
|
||||
* 返回值:成功返回 buf 指针;buf 为 NULL 时返回 NULL char *
|
||||
* 限定条件:buf 非空且长度足够(>= 16 字节)
|
||||
* 函数说明:1. 先经 NET_NTOHL 转为主机字节序再格式化输出
|
||||
* 2. ⚠ 段序(N34 E13 §6 修复):NTOHL 后主机序数值的高字节才是
|
||||
* 2. ⚠ 段序(E13 定案 修复):NTOHL 后主机序数值的高字节才是
|
||||
* 点分第一段(192.168.1.100 → 0xC0A80164 → "192.168.1.100")。
|
||||
* 原实现低段在前,显示成字节反转的 "100.1.168.192"
|
||||
*/
|
||||
@@ -3612,7 +3622,7 @@ static void handle_connect_event(net_sock_t *p_sock) {
|
||||
|
||||
/* §5.56:TCP 服务器须在 CONNECT 后开启 KeepAlive。2026-10-12 曾加后
|
||||
* 撤回(当时仅证明"物理断链"已被 +2s TIM_OUT 快速覆盖,其余场景
|
||||
* 无法注入、未证明);E11(2026-10-13,实验方案.md)用"禁用 PC 网卡"
|
||||
* 无法注入、未证明);E11(2026-10-13,《网络自愈架构设计》)用"禁用 PC 网卡"
|
||||
* 注入"链路在、对端静默"(NAT/黑洞)补上证据链:生产参数 60/5/3
|
||||
* 实测 ≈30 s 判死 → TIM_OUT → QUARANTINE → reconciler 重建;对端存活时
|
||||
* 探测被 ACK、空闲会话不误杀。消费链路现成,按手册位置转正。 */
|
||||
@@ -3712,11 +3722,11 @@ static void handle_disconnect_event(net_sock_t *p_sock) {
|
||||
/* 直接返回(中断已读清,不会重复上报) */
|
||||
return;
|
||||
}
|
||||
/* F-NET-17 M3(N34 实验 2026-10-13):矛盾态可疑门——芯片 Socket 仍 OPEN(0x05)
|
||||
/* F-NET-17 M3(自愈专项实验 2026-10-13):矛盾态可疑门——芯片 Socket 仍 OPEN(0x05)
|
||||
* 而 TCP 槽 0x00 且本层 ESTABLISHED = 逻辑矛盾(活连接应 0x04):陈旧 DISCONNECT
|
||||
* (拆链完成滞后锁存,TRAP-NET-12)与"真断开恰被旧拆链覆写槽"在 D20 上不可分辨
|
||||
* (结构性失明,F-NET-15 Q1)。处置:不吃边沿,置可疑电平返回,交对账①
|
||||
* (ESTABLISHED + 芯片 TCP==CLOSED)电平去抖再入本函数(N34 阶段 3 合并
|
||||
* (ESTABLISHED + 芯片 TCP==CLOSED)电平去抖再入本函数(自愈收敛阶段 3 合并
|
||||
* 后=4×100ms,NET_RECON_STABLE_DEATH,让位租约 400ms 不变 + 冷却):
|
||||
* flag==1 旁路本门 → 正常释放;连接真活则租约内
|
||||
* 会话正常完成(风暴链掐断,E9a n30 0/50 实证)。
|
||||
@@ -3746,7 +3756,7 @@ static void handle_disconnect_event(net_sock_t *p_sock) {
|
||||
/* TRAP-NET-18 推广(2026-09-24 台架实证):正常 DISCONNECT 释放留下的芯片收尾状态
|
||||
* 会在复用同一 fd 的下一条连接上以"伪 DISCONNECT"形式投递(实测 accept 后约 10~20ms)→ 该连接被提前释放,应用把已到的 2048B 当整份文件并回报 226;
|
||||
* 仅**本连接收过数据**时登记沉降(实测触发源 = 收过数据的数据通道被关闭),纯连接即关/只发不收的连接免沉降,保住 TRAP-NET-17 的快速复连时序(:21 @0ms ×50 全通过) */
|
||||
/* F-NET-15 M1(N34 实验 2026-10-12):沉降**无条件**登记。原 recv_bytes!=0 门的
|
||||
/* F-NET-15 M1(自愈专项实验 2026-10-12):沉降**无条件**登记。原 recv_bytes!=0 门的
|
||||
* 受害者由事件时序定义(accept 后 ~20ms 被陈旧 DISCONNECT 杀 → recv_bytes==0 是
|
||||
* 构造性必然),门对"残渣循环自持"形态失效(n30_repro 背靠背 9/10 失败,E1 实测);
|
||||
* 门原保护目标(:21 @0ms 快复连)已被 N-32 单一重建入口延迟化(恢复窗实测 0.3~1s)架空,
|
||||
@@ -4003,7 +4013,7 @@ int net_getsockname(int sockfd, struct net_sockaddr *addr, int *addrlen) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取 Socket 对端地址(IP + Port)—— N34 E13 §6 lftpd 对端显示收口
|
||||
* 函数功能:获取 Socket 对端地址(IP + Port)—— E13 定案 lftpd 对端显示收口
|
||||
* 入口参数:sockfd - socket 描述符 int
|
||||
* 出口参数:addr - 输出:对端地址 struct net_sockaddr *
|
||||
* addrlen - 输入输出:地址结构体长度 int *
|
||||
|
||||
@@ -37,8 +37,8 @@ typedef enum {
|
||||
NET_MSG_CONNECT,
|
||||
NET_MSG_LISTEN,
|
||||
NET_MSG_ACCEPT,
|
||||
NET_MSG_DROP_CONN, /* N34 阶段 3(E-02 收口):主动拆会话、保监听(见 net_drop_conn) */
|
||||
/* N34 阶段1(F-NET-2/3):NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 已删——
|
||||
NET_MSG_DROP_CONN, /* 自愈收敛阶段 3(E-02 收口):主动拆会话、保监听(见 net_drop_conn) */
|
||||
/* 自愈收敛阶段1(F-NET-2/3):NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 已删——
|
||||
* 静默回收由对账⑤自动认领(net_reconcile_tick),重建由 reconciler
|
||||
* 形态③④/D10 单一
|
||||
* 所有者负责;手动自愈 API 面退役(生产调用者本就为零) */
|
||||
@@ -51,7 +51,7 @@ typedef struct {
|
||||
int len; /* 数据长度/缓冲区大小 */
|
||||
int flags; /* 接收标志 */
|
||||
uint32_t timeout_ms; /* 接收超时(入队方向;0 = 无限等待,无默认预算——
|
||||
* N34 阶段 1.5 删除 NET_RECV_TIMEOUT_MS 30s 默认) */
|
||||
* 自愈收敛阶段 1.5 删除 NET_RECV_TIMEOUT_MS 30s 默认) */
|
||||
TaskHandle_t caller; /* 调用方任务句柄 */
|
||||
int result; /* 操作结果 */
|
||||
/* 连接参数 */
|
||||
@@ -154,8 +154,8 @@ int net_listen(int sockfd);
|
||||
*/
|
||||
int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||||
|
||||
/* N34 阶段1(F-NET-4):net_can_accept 已退役——只认 ESTABLISHED 的旧门控会把
|
||||
* "监听器在服役、本轮待 CONNECT"窗口全挡掉(丢 CONNECT 探针因此从不运行);
|
||||
/* 自愈收敛阶段1(F-NET-4):net_can_accept 已退役——只认 ESTABLISHED 的旧门控会把
|
||||
* "监听器在服役、本轮待 CONNECT"窗口全挡掉(CONNECT 事件补 accept 探针因此从不运行);
|
||||
* 监听 accept 门控统一用 net_listener_armed(),recv 门控 net_can_read() 保留。 */
|
||||
|
||||
/*
|
||||
@@ -165,14 +165,14 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||||
* 返回值:1 - 就绪(ESTABLISHED 待 accept / LISTENING / CLOSED+auto_relisten
|
||||
* +残留数据);0 - 不就绪 int
|
||||
* 限定条件:net_init() 已调用;任意任务上下文
|
||||
* 函数说明:1. N-32(P1 不变量 II,N34 阶段1 补齐 ESTABLISHED 放行):取代已退役的
|
||||
* 函数说明:1. N-32(P1 不变量 II,自愈收敛阶段1 补齐 ESTABLISHED 放行):取代已退役的
|
||||
* `net_can_accept()`(只认 ESTABLISHED)作为监听 accept 门控——原门控使
|
||||
* :7003 永不进 `net_accept()`,
|
||||
* `net_lost_connect_probe`(丢 CONNECT 中断补 accept,N-30 实证的
|
||||
* `net_lost_connect_probe`(CONNECT 事件未收到补 accept,N-30 实证的
|
||||
* "数据被吞/425"主根因修复)对该端口等于从未运行
|
||||
* 2. 放行 LISTENING:探针与 "closed-but-readable 接受" 都发生在
|
||||
* `net_accept_locked` **内部**,门控挡在外面就永远到不了
|
||||
* 2b. 放行 ESTABLISHED(N34 阶段1 台架修正):单连接模型下 CONNECT 处理
|
||||
* 2b. 放行 ESTABLISHED(自愈收敛阶段1 台架修正):单连接模型下 CONNECT 处理
|
||||
* (net_poll 分派 / 探针补 accept / 对账② standalone accept)把监听 fd
|
||||
* 转 ESTABLISHED,这正是"待 accept"电平——漏放行则任务周期慢的消费者
|
||||
* (i104 200ms 抢不过对账② ~400ms 去抖)永不 accept、会话整场饿死
|
||||
@@ -203,7 +203,7 @@ int net_listener_armed(int sockfd);
|
||||
* 走调用方既有的错误分支重建,而不是静默卡死
|
||||
* 4. ⚠ **不可作为唯一判据**:readable 只由 RECV_OK 中断置位,而
|
||||
* net_reconcile_tick 的三类对账**不含**"芯片 RX 非空但 readable=0"
|
||||
* → 中断丢失时本函数会恒返 0。调用方须保留**低频兜底 recv**
|
||||
* → 事件未收到时本函数会恒返 0。调用方须保留**低频兜底 recv**
|
||||
* (ui_net_sink 每 32 轮无条件收一次,最坏延迟 ≈320 ms)
|
||||
*/
|
||||
int net_can_read(int sockfd);
|
||||
@@ -233,7 +233,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
int net_send(int sockfd, const void *buf, int len, int flags);
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(TCP,**默认无限阻塞**——N34 阶段 1.5 语义主流化)
|
||||
* 函数功能:接收数据(TCP,**默认无限阻塞**——自愈收敛阶段 1.5 语义主流化)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* buf - 接收缓冲区
|
||||
* len - 缓冲区大小
|
||||
@@ -254,7 +254,7 @@ int net_send(int sockfd, const void *buf, int len, int flags);
|
||||
int net_recv(int sockfd, void *buf, int len, int flags);
|
||||
|
||||
/*
|
||||
* 函数功能:接收数据(非阻塞具名入口,原 NET_MSG_DONTWAIT 路径转正——N34 阶段 1.5)
|
||||
* 函数功能:接收数据(非阻塞具名入口,原 NET_MSG_DONTWAIT 路径转正——自愈收敛阶段 1.5)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* buf - 接收缓冲区
|
||||
* len - 缓冲区大小
|
||||
@@ -268,7 +268,7 @@ int net_recv_nb(int sockfd, void *buf, int len);
|
||||
|
||||
/*
|
||||
* 函数功能:设置 Socket 阻塞/非阻塞**模式属性**(对齐 BSD O_NONBLOCK / Python
|
||||
* setblocking——N34 阶段 1.5,模式挂 socket 控制块属性)
|
||||
* setblocking——自愈收敛阶段 1.5,模式挂 socket 控制块属性)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* on - 1 = 阻塞(net_socket 默认);0 = 非阻塞
|
||||
* 返回值:0 成功;-1 失败(描述符无效/未占用)
|
||||
@@ -289,7 +289,7 @@ int net_setblocking(int sockfd, int on);
|
||||
* timeout_ms - 单次调用在 netTask 内的最长等待(毫秒,>0)
|
||||
* 返回值:>0 实际字节数;0 = 对端关闭(EOF);-1 = 真错误(errno 可查);**-2 = 超时无数据**
|
||||
* 限定条件:非 netTask 上下文;Socket 已连接
|
||||
* 函数说明:1. **显式预算**便捷入口(等价 Python settimeout,N34 阶段 1.5 起
|
||||
* 函数说明:1. **显式预算**便捷入口(等价 Python settimeout,自愈收敛阶段 1.5 起
|
||||
* 不再有隐藏默认值):net_recv 的无限阻塞 + 本接口的显式预算构成
|
||||
* 超时语义的全部来源;超时首选仍是 net_select
|
||||
* 2. E-02 修复配套:lftpd 等"等对端下一行/下一块数据"的调用方
|
||||
@@ -326,7 +326,7 @@ int net_sendto(int sockfd, const void *buf, int len, int flags,
|
||||
* 返回值:实际接收字节数,失败返回 -1
|
||||
* 限定条件:socket 已创建,指针非空
|
||||
* 函数说明:1. 读取 CH395F 接收缓冲区,获取对端地址
|
||||
* 2. 阻塞语义与 net_recv 同(N34 阶段 1.5):blocking 属性下无数据
|
||||
* 2. 阻塞语义与 net_recv 同(自愈收敛阶段 1.5):blocking 属性下无数据
|
||||
* 无限等待,DONTWAIT / 非阻塞属性立即 NET_ERR_WOULDBLOCK;
|
||||
* 本接口为轮询自旋实现(历史遗留,UDP 专用),受 IWDG 监控的
|
||||
* 任务同样禁止对其无限等待
|
||||
@@ -344,14 +344,14 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
int net_close(int sockfd);
|
||||
|
||||
/*
|
||||
* 函数功能:主动拆掉当前 TCP 会话,**保留监听**(N34 阶段 3,E-02 收口)
|
||||
* 函数功能:主动拆掉当前 TCP 会话,**保留监听**(自愈收敛阶段 3,E-02 收口)
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:0 成功(含幂等:无活动会话),-1 失败
|
||||
* 限定条件:非 netTask 上下文(经消息队列委托,同其它 net_* API)
|
||||
* 函数说明:1. 适用场景=应用层放弃会话(对时 30s 预算耗尽、协议超时等):
|
||||
* 单连接模型禁止对监听 fd net_close(连监听一起毁,AGENTS 约定),
|
||||
* 而挂起但 TCP 仍活的客户端会永久占住单连接监听(PC 内核自动
|
||||
* ACK keepalive,芯片僵尸判不死——实验方案 E13 §5 定案缺口)
|
||||
* ACK keepalive,芯片僵尸判不死——《网络自愈架构设计》§5.2 E13 定案缺口)
|
||||
* 2. 实现=sock_reset QUARANTINE(FIN 关闭 + 排渣 + 排空事件 + 等
|
||||
* byte0=00H,TRAP-NET-18 异常释放语义);auto_relisten fd 随即重监听
|
||||
* (失败交 D10 重试),非 auto_relisten(client fd)收口 CLOSED
|
||||
@@ -400,7 +400,7 @@ int net_get_errno(void);
|
||||
*/
|
||||
int net_sock_state(int sockfd);
|
||||
|
||||
/* N34 阶段1(F-NET-3):net_resync_listen / net_relisten 声明已删——
|
||||
/* 自愈收敛阶段1(F-NET-3):net_resync_listen / net_relisten 声明已删——
|
||||
* 静默回收形态由对账⑤自动认领(2 轮去抖 + 1s 冷却,纪律"不发芯片命令"
|
||||
* 原样保留在认领动作内);监听重建由 reconciler 形态③④(100ms 周期)/
|
||||
* D10(30ms 重试)单一所有者。勿再引入"应用层手动自愈"入口。 */
|
||||
|
||||
@@ -49,7 +49,7 @@ extern "C" {
|
||||
*/
|
||||
#define NET_MSG_DONTWAIT 0x01 /* 非阻塞模式(单次覆盖 socket 的 blocking 属性;
|
||||
* 具名入口见 net_recv_nb() / net_setblocking(),
|
||||
* N34 阶段 1.5) */
|
||||
* 自愈收敛阶段 1.5) */
|
||||
|
||||
/*
|
||||
* 网络字节序转换宏
|
||||
@@ -112,7 +112,7 @@ struct net_sockaddr_in {
|
||||
|
||||
/*
|
||||
* Socket 状态枚举(**本层会话投影**,非芯片状态事实源)
|
||||
* N34 阶段 3(镜像降级,实施方案 docs/网络/N34-自愈审计.md §5.5 项 5):
|
||||
* 自愈收敛阶段 3(镜像降级,docs/网络/网络自愈架构设计.md §3.3):
|
||||
* 芯片侧状态唯一事实源=驱动状态缓存(ch395f_sock_state_cached,刷新点=net_poll);
|
||||
* 本 8 态只表达**本层会话语义**(fd 生命周期/待 accept 电平/门控展示),
|
||||
* 事件与对账把它与芯片事实对齐。新增"按芯片状态决策"的代码一律读驱动缓存,
|
||||
@@ -178,7 +178,7 @@ typedef struct {
|
||||
/* 单连接模式自动重监听:连接断开后由 net 层自动回到 LISTEN(BSD 风格监听常驻) */
|
||||
uint8_t auto_relisten;
|
||||
|
||||
/* N34 阶段 1.5(2026-10-13):阻塞/非阻塞**模式属性**(对齐 BSD O_NONBLOCK /
|
||||
/* 自愈收敛阶段 1.5(2026-10-13):阻塞/非阻塞**模式属性**(对齐 BSD O_NONBLOCK /
|
||||
* Python setblocking 的"模式归使用者"模型)。
|
||||
* 1 = 阻塞(net_socket() 默认);0 = 非阻塞(net_setblocking(fd, 0))。
|
||||
* net_recv() 无 NET_MSG_DONTWAIT 时按本属性决定"无数据 → 登记挂起等待"
|
||||
@@ -201,7 +201,7 @@ typedef struct {
|
||||
* 均以此甄别幽灵态(见 net_socket.c TRAP-NET-20)。跨 fd 释放保留(幽灵属芯片
|
||||
* Socket 级,与 fd 复用无关),新连接断开时刷新。 */
|
||||
uint16_t last_peer_port;
|
||||
/* N-30:accept 路径"丢 CONNECT 中断补 accept"的去抖计数(连续确认次数,
|
||||
/* N-30:accept 路径"CONNECT 事件未收到补 accept"的去抖计数(连续确认次数,
|
||||
* 节拍 = accept 轮询 100ms;新监听/补 accept 后清零) */
|
||||
uint8_t lost_conn_seen;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user