chore(编号): 存量编号全量转语义短语,门禁识别面与语料同批重打
登记簿、文档与代码注释里的存量字母加数字编号(N-x / S-x / T-x / E-x / A-x / 卡号) 一律改写为语义短语,净删 2,028 处引用;删除基线与待确认、并行分道方案、排期详述、 采集保护收尾 4 篇(内容已并入 docs/任务规划/README 与登记簿)。 门禁机器与三张账同批重打:check_ids.py 新增变更记录行豁免与第二根护栏 undecidable_total_ceiling;check_test_traceability.py 只加 stdout/stderr UTF-8 reconfigure(TC_RE 未动);check_cubemx_survival.py 的 --write 固定 newline=LF; id_registry / id_aliases(+19 条 retired-to-phrase)/ id_known_backlog 重打。 test/ 56 个文件同步 TC 标签语义化,其中 18 个 TU 改了 CHECK / printf 里的标签文字, 是本批唯一改变构建产物的文件集合。 为什么合成一笔、不拆四笔(实测撞闸,非偏好):pre-commit 跑钩子前会 stash 未 staged 部分,拆开后中间提交必然是「新规则 + 旧语料」——实跑可判定 85.15% < 基线 86.00%、 不可判定 1,453 > 上限 1,166,编号门禁直接拦下。编号识别面与它描述的语料只能同码移动。 实跑基线(工作区全量):754 文件 / 8,230 处编号字面量 / 可判定 7,079 = 86.01% (基线 86.0%,容差 0.1pp)/ 不可判定绝对数 1,151(上限 1,166)/ 校验 1-6 错误级 0 / 告警 = 悬空 2(App/algo/freq.c 的 S2,属 §4.4 同号不同义)+ 孤儿 50。 基线从 84.0 抬到 86.0 的理由见 docs/门禁说明/id-check.md §7.6:本批真删了 2,028 处 引用,可判定面随真实内容上升,不是把分母做小。同批新增排除 docs/硬件平台/ 语料,使 识别面少 264 处——芯片手册位号与网表料号不属编号空间(registry 有 excluded_paths_note)。 ⚠ 余量只剩 0.11pp(约 10 处)与绝对数 15 处:把「可判定的引用」改成散文会立刻撞第二 根护栏。另遗留一项:id_aliases 里 retired 的 N / S / T / A 别名没有 scope(U1~U5 有), 今后有人新写一个 A-4,校验 3 不会响,只能靠人,建议下批补 scope。 固件不变证据:115 个 .c/.h 剥注释并归一字符串后与 HEAD 逐字节全等,残留代码差异 0; App / Src / Drivers 的字符串字面量零改动。@build 0 错误 0 警告;40/40 主机套件、2,889 断言全通过;覆盖率 line 89.2% / func 92.6%;pre-commit 48 钩子 --all-files 全绿; check_doc_links --all 通过(176 文档,章节引用无法判定 0);逐字节卫生核过:14 个带 BOM 文件与 HEAD 一致、0 个 CR、0 个 U+FFFD,字符串字面量纯 ASCII。 .cubemx_survival_baseline.json 的 watchdog-module 哈希 56bf27 变 2bb051 属合法: Src/freertos.c 的 USER CODE 区内只有注释文字随编号改写,代码未变。 同批带上体积同码凭证与 RAM 台账行(@build 之后盖戳):RW_IRAM1 79,008 B / 60.3%, RW_CCM 57,376 B / 87.9%,阈值 92%。
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
真正兜底 = D10 预算到期 + 对账形态④ 重新登记)
|
||||
- 仅异常路径生效,正常 FIN 路径零改动
|
||||
|
||||
### 错误码(E-03 修复)
|
||||
### 错误码
|
||||
|
||||
- **按任务隔离**:`s_net_errno_slots[8]`(每槽 `{任务句柄, err}`),替代原全局 `s_net_errno`
|
||||
- `net_get_errno()` 只读本任务槽位,**对外语义不变**(成功不清零)
|
||||
|
||||
@@ -64,7 +64,7 @@ static command_t commands[] = {
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
/* N-19 FTP 鉴权:全局失败计数/锁定状态(跨会话持久——单连接服务器,全局
|
||||
/* FTP 鉴权:全局失败计数/锁定状态(跨会话持久——单连接服务器,全局
|
||||
* 计数即可;成功清零、锁定期满自动放行,见 lftpd_auth.c) */
|
||||
static ftp_auth_state_t s_auth_state;
|
||||
|
||||
@@ -343,7 +343,7 @@ static int cmd_cwd(lftpd_client_t *client, const char *arg)
|
||||
|
||||
static int cmd_dele(lftpd_client_t *client, const char *arg)
|
||||
{
|
||||
/* N-19:写命令门——[ftp] write=0 时拒绝(鉴权门已保证此处必为已登录态) */
|
||||
/* 写命令门——[ftp] write=0 时拒绝(鉴权门已保证此处必为已登录态) */
|
||||
const ftp_cfg_t *cfg = ftp_cfg_get();
|
||||
|
||||
if ((cfg == NULL) || (cfg->write_en == 0u)) {
|
||||
@@ -638,7 +638,7 @@ static int cmd_size(lftpd_client_t *client, const char *arg)
|
||||
|
||||
static int cmd_stor(lftpd_client_t *client, const char *arg)
|
||||
{
|
||||
/* N-19:写命令门——[ftp] write=0 时拒绝(鉴权门已保证此处必为已登录态) */
|
||||
/* 写命令门——[ftp] write=0 时拒绝(鉴权门已保证此处必为已登录态) */
|
||||
const ftp_cfg_t *cfg = ftp_cfg_get();
|
||||
|
||||
if ((cfg == NULL) || (cfg->write_en == 0u)) {
|
||||
@@ -757,7 +757,7 @@ static int handle_control_channel(lftpd_client_t *client)
|
||||
command_tmp[i] = (char)toupper((int)command_tmp[i]);
|
||||
}
|
||||
|
||||
/* N-19:未鉴权命令门——仅 QUIT/FEAT/SYST/NOOP 放行(客户端兼容需要,
|
||||
/* 未鉴权命令门——仅 QUIT/FEAT/SYST/NOOP 放行(客户端兼容需要,
|
||||
* 且无信息量);其余一律 530。USER/PASS 本身也在放行名单外,
|
||||
* 但它们在 gate 之前不可能通过 → 单独放行见下(USER/PASS 例外) */
|
||||
if (client->auth_logged_in == 0) {
|
||||
@@ -817,7 +817,7 @@ int lftpd_start(const char *directory, int port, lftpd_t *lftpd)
|
||||
lftpd->port = port;
|
||||
lftpd->server_socket = -1; /* memset 清零后显式置"无监听器"(0 是合法 fd) */
|
||||
|
||||
/* N-19:出厂默认口令在用告警(台架锚点;改了 [ftp] pwd_hash 即消失) */
|
||||
/* 出厂默认口令在用告警(台架锚点;改了 [ftp] pwd_hash 即消失) */
|
||||
if (ftp_cfg_is_default_pwd() != 0) {
|
||||
lftpd_log_info("using factory default password");
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef struct {
|
||||
char directory[256];
|
||||
int socket;
|
||||
int data_socket;
|
||||
/* N-19 FTP 鉴权会话态(每会话 memset 0 = 未登录;跨会话锁定计数在
|
||||
/* FTP 鉴权会话态(每会话 memset 0 = 未登录;跨会话锁定计数在
|
||||
* lftpd.c 的 s_auth_state,不在此处) */
|
||||
char auth_user[32]; /* USER 阶段暂存的用户名 */
|
||||
uint8_t auth_user_ok; /* 1 = 用户名与 [ftp] user 匹配 */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-10-11
|
||||
* 修改记录:
|
||||
* v1.0 2026-10-11 王建锋 创建初始版本(N-19 FTP 鉴权;契约由
|
||||
* v1.0 2026-10-11 王建锋 创建初始版本(FTP 鉴权;契约由
|
||||
* test/host/ftp_auth 主机单测钉死)
|
||||
*/
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-10-11
|
||||
* 修改记录:
|
||||
* v1.0 2026-10-11 王建锋 创建初始版本(N-19 FTP 鉴权;lftpd.c 为唯一消费者)
|
||||
* v1.0 2026-10-11 王建锋 创建初始版本(FTP 鉴权;lftpd.c 为唯一消费者)
|
||||
*/
|
||||
|
||||
#ifndef LFTPD_AUTH_H
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* E-02 头阻塞修复 + recv pending 化(M3 台架实证):
|
||||
* 头阻塞修复 + recv pending 化(M3 台架实证):
|
||||
* netTask 是全部 socket 操作的唯一执行者;lftpd 若用**阻塞** net_recv 等待对端
|
||||
* 下一行/下一块数据 → 只要客户端连上却不发完整行,netTask 就被长期占用,
|
||||
* 其余任务(含远端显示)的网络操作整体冻结(实测一次空闲 FTP 登录让 LCDMEM
|
||||
@@ -109,7 +109,7 @@ int lftpd_inet_accept_timeout(int socket, int timeout_ms)
|
||||
/* F-NET-15 M2(自愈专项实验 2026-10-12):镜像门控退役——原直读 p_sock->state 在
|
||||
* relisten 忙期(CLOSED 瞬态)误判"已关闭",扔掉 ~4.9s 等待预算;armed 门控
|
||||
* 认"监听器在服役(LISTENING)或待重建且 RX 有残留(closed-with-data 救回窗)",
|
||||
* 与 :7003 的 N-32 P1 同型修复 */
|
||||
* 与 :7003 的监听生命周期 P1 同型修复 */
|
||||
if (net_listener_armed(socket) == 0) {
|
||||
/* **故意留 error**:控制连接还活着、我方数据监听却已不在服役 →
|
||||
* 这是本侧异常,不是对端行为 */
|
||||
|
||||
@@ -123,7 +123,7 @@ void handle_connect_event(net_sock_t *p_sock) {
|
||||
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
|
||||
/* 状态 → ESTABLISHED(监听自身转数据通道) */
|
||||
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
|
||||
/* N-32(P1):新会话开始 —— 清"上一条会话已结束"电平。必须在置
|
||||
/* 监听生命周期 P1:新会话开始 —— 清"上一条会话已结束"电平。必须在置
|
||||
* ESTABLISHED 之后立刻做:否则抢先 relisten 后到新连接的窗口内
|
||||
* recv 仍会误得 EOF(把新客户端踢开) */
|
||||
p_sock->session_dead = 0U;
|
||||
@@ -164,7 +164,7 @@ void handle_connect_event(net_sock_t *p_sock) {
|
||||
p_sock->remote_port = (uint16_t)(remote[4] | (remote[5] << 8));
|
||||
/* 状态 → ESTABLISHED */
|
||||
p_sock->state = NET_SOCK_STATE_ESTABLISHED;
|
||||
/* N-32(P1):新会话开始 —— 清"上一条会话已结束"电平(同 LISTENING
|
||||
/* 监听生命周期 P1:新会话开始 —— 清"上一条会话已结束"电平(同 LISTENING
|
||||
* 分支:必须在转 ESTABLISHED 后立刻做,防抢先 relisten 窗口误 EOF) */
|
||||
p_sock->session_dead = 0U;
|
||||
/* F-NET-17 M3 前置:清可疑电平(同 LISTENING 分支) */
|
||||
@@ -201,9 +201,9 @@ void handle_disconnect_event(net_sock_t *p_sock) {
|
||||
|
||||
/* 监听态:DISCONNECT 落在监听器上 */
|
||||
if (p_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
/* TRAP-NET-17 / N-6:监听态收到 DISCONNECT——bit3=1(0x08)下芯片**不**关该 Socket(停 0x05/0x00,芯片 TCP 侧已 CLOSED);不重开则此后所有 SYN 全被拒 = 监听永久死亡;
|
||||
/* TRAP-NET-17:监听态收到 DISCONNECT——bit3=1(0x08)下芯片**不**关该 Socket(停 0x05/0x00,芯片 TCP 侧已 CLOSED);不重开则此后所有 SYN 全被拒 = 监听永久死亡;
|
||||
* 触发 = 断连后 <~1s 快速复连时 CONNECT 中断未上报(控制块滞留 LISTENING)后该连接断开(2026-09-23 生产固件复现);
|
||||
* N-32 P2:本分支**只回读留痕、不再 relisten** —— 重建统一交
|
||||
* 监听生命周期 P2:本分支**只回读留痕、不再 relisten** —— 重建统一交
|
||||
* net_reconcile_tick 形态③(每 100 ms 读驱动缓存,监听失位即重建)。原处直接
|
||||
* relisten 是 12 个所有者之一,且位于 DISCONNECT 事件路径,可能"抢先"
|
||||
* 于消费者 recv(P1 已消除其后果,P2 消除其可能)。
|
||||
@@ -275,7 +275,7 @@ void handle_disconnect_event(net_sock_t *p_sock) {
|
||||
/* 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)架空,
|
||||
* 门原保护目标(:21 @0ms 快复连)已被监听生命周期单一重建入口延迟化(恢复窗实测 0.3~1s)架空,
|
||||
* +100ms 沉降落在窗内不可见。沉降窗口同时让残渣 DISCONNECT 在 state==CLOSED
|
||||
* (无害、仅留痕)时被消费,断开"杀下一条 → 新拆链 → 再杀"的繁殖链 */
|
||||
{
|
||||
@@ -288,12 +288,12 @@ void handle_disconnect_event(net_sock_t *p_sock) {
|
||||
}
|
||||
/* 正常释放(对端 FIN):断连时挂起项以 EOF(0) 结束 */
|
||||
p_sock->released_abnormal = 0U;
|
||||
/* N-32(P1 不变量 I):置"本会话已结束"电平。须在置 CLOSED **之前**,
|
||||
/* 监听生命周期 P1 不变量 I:置"本会话已结束"电平。须在置 CLOSED **之前**,
|
||||
* 使 session_dead 覆盖"CLOSED 等待 recv 排空"整个窗口——排空期间
|
||||
* recv 的 DONTWAIT 快路径先返数据(recv_len>0 优先),数据尽后判据
|
||||
* 落到本标志 → 仍得 EOF,不因排空慢而漏报 */
|
||||
p_sock->session_dead = 1U;
|
||||
/* N-30(TRAP-NET-20):登记本连接对端端口(幽灵态甄别基准,须在状态
|
||||
/* TRAP-NET-20:登记本连接对端端口(幽灵态甄别基准,须在状态
|
||||
* 迁移前记录——remote_port 此刻仍有效,relisten 清零) */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
/* 状态 → CLOSED */
|
||||
@@ -382,9 +382,9 @@ void handle_timeout_event(net_sock_t *p_sock) {
|
||||
* NET_ERR_CONNRESET 结束(而非 EOF),应用(lftpd STOR)回报 5xx
|
||||
* 而非误报 226(见 net_pending_tick 断连分支) */
|
||||
p_sock->released_abnormal = 1U;
|
||||
/* N-30(TRAP-NET-20):异常释放同样登记对端端口(幽灵甄别基准) */
|
||||
/* TRAP-NET-20:异常释放同样登记对端端口(幽灵甄别基准) */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
/* N-32(P1 不变量 I):异常结束同样是"本会话已结束"电平(TIMEOUT/RST
|
||||
/* 监听生命周期 P1 不变量 I:异常结束同样是"本会话已结束"电平(TIMEOUT/RST
|
||||
* 已在下方 requarantine,本标志只表达"会话结束了"这一事实,与
|
||||
* released_abnormal(结束得好不好看)正交) */
|
||||
p_sock->session_dead = 1U;
|
||||
@@ -564,7 +564,7 @@ void net_reconcile_tick(void) {
|
||||
} else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
|
||||
if (c.tcp_state == CH395F_TCP_ESTABLISHED) {
|
||||
/* ② 本层 LISTENING 而芯片已完成握手(CONNECT 事件未收到)→ 补做 accept
|
||||
* N-30(TRAP-NET-20)幽灵态甄别:拆链收尾窗口内旧连接未拆净,状态如实
|
||||
* TRAP-NET-20幽灵态甄别:拆链收尾窗口内旧连接未拆净,状态如实
|
||||
* 显示 ESTABLISHED(E15:bit3=1 保留现场契约 + TCP 拆链状态机,非谎报),
|
||||
* 回读对端端口 = 上一条连接端口 → 不补 accept(补了会把数据发给
|
||||
* 已死的旧连接 = 生产 LIST#4 数据被吞的直接成因),等拆净或新 SYN。
|
||||
@@ -590,7 +590,7 @@ void net_reconcile_tick(void) {
|
||||
* 被动修正零风险:不去抖、不占冷却(原 pump 同口径) */
|
||||
DBG_INFO("sock%d reconcile: chip listening, resync CLOSED->LISTENING (U11)", i);
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* N-30(TRAP-NET-20):死连接对端端口转登幽灵甄别基准 + 探针计数清零
|
||||
/* TRAP-NET-20:死连接对端端口转登幽灵甄别基准 + 探针计数清零
|
||||
* —— 芯片监听器未被重开,芯片侧对端信息可能仍是上一条连接的,
|
||||
* 必须转登为基准,否则形态② 的幽灵拦截会失效 */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
@@ -629,7 +629,7 @@ void net_reconcile_tick(void) {
|
||||
DBG_INFO("sock%d reconcile: chip closed (0x%02X/0x%02X) -> disconnect",
|
||||
i, c.open, c.tcp_state);
|
||||
/* 复用断开状态机(含陈旧事件甄别 + 状态迁移 + 事件派发);
|
||||
* 只置事实,重建由本 tick 形态③④统一做(N-32 P2 单一所有者) */
|
||||
* 只置事实,重建由本 tick 形态③④统一做(监听生命周期 P2 单一所有者) */
|
||||
handle_disconnect_event(p_sock);
|
||||
} else if (bad == 5) {
|
||||
/* 类型⑤:静默回收 → RESYNC 语义(原 NET_MSG_RESYNC_LISTEN 分派体
|
||||
@@ -640,7 +640,7 @@ void net_reconcile_tick(void) {
|
||||
i, c.open, c.tcp_state);
|
||||
/* 仅修 MCU 侧;新连接的 CONNECT 中断会把两侧重新同步 */
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* N-30(TRAP-NET-20):死连接对端端口转登幽灵甄别基准 + 探针计数清零 */
|
||||
/* TRAP-NET-20:死连接对端端口转登幽灵甄别基准 + 探针计数清零 */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
/* 取消本 fd 在死连接上的挂起 recv(必通知,防调用方挂死) */
|
||||
|
||||
@@ -109,7 +109,7 @@ static void net_drain_chip_rx(int sockfd) {
|
||||
* 3. 复用原本地端口重新 OPEN + LISTEN,仅把 state 置回 LISTENING、不 memset
|
||||
* —— 实现 BSD 风格"监听 Socket 常驻",应用层无需手动重监听。
|
||||
* 4. fd 由参数传入(不用 `p_sock - s_net_socks` 反推),控制块经 net_get_sock()
|
||||
* 取 —— 本模块**不访问** net_socket.c 的 static 数组(N-32 §10)。
|
||||
* 取 —— 本模块**不访问** net_socket.c 的 static 数组(监听生命周期模块化)。
|
||||
*/
|
||||
static int net_relisten_locked(int sockfd) {
|
||||
uint8_t status;
|
||||
@@ -206,12 +206,12 @@ static int net_relisten_locked(int sockfd) {
|
||||
|
||||
/* 状态置回 LISTENING(fd 保留;auto_relisten 保持为 1,下次断连仍自动重监听) */
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* ⚠ 此处**刻意不清 session_dead**(N-32 P1):重建监听只是"芯片侧恢复就位",与
|
||||
/* ⚠ 此处**刻意不清 session_dead**(监听生命周期 P1):重建监听只是"芯片侧恢复就位",与
|
||||
* "应用是否已确认上一条会话结束"是两件事;清了它,抢先 relisten 之后消费者就再也
|
||||
* 得不到 EOF(B10"消费者卡死"原型)。它只由新 CONNECT 成功或 memset 清零。 */
|
||||
/* 新监听不得继承上一条连接的释放原因(TRAP-NET-18 待办 #3) */
|
||||
p_sock->released_abnormal = 0U;
|
||||
/* N-30(TRAP-NET-20):清零前把对端端口转登为幽灵甄别基准;去抖计数随之清零 */
|
||||
/* TRAP-NET-20:清零前把对端端口转登为幽灵甄别基准;去抖计数随之清零 */
|
||||
p_sock->last_peer_port = p_sock->remote_port;
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
/* 以下四项 = 清上一条的对端信息,新连接待用 */
|
||||
@@ -361,7 +361,7 @@ void net_listener_tick(void) {
|
||||
/* 已到放弃时限(0 = 尚未起算,见下) */
|
||||
if ((s_relisten_dead[i] != 0U) && ((int32_t)(now - s_relisten_dead[i]) >= 0)) {
|
||||
net_listener_clear(i);
|
||||
/* 预算耗尽 ≠ 放弃:交 reconciler 形态③④ 周期接管(N-32 单一重建入口),
|
||||
/* 预算耗尽 ≠ 放弃:交 reconciler 形态③④ 周期接管(监听生命周期单一重建入口),
|
||||
* 监听不会永久失效——旧文案 "give up" 夸大了失效语义 */
|
||||
DBG_ERROR("sock%d relisten retry budget exhausted, reconciler takes over", i);
|
||||
continue;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-10-12
|
||||
* 修改记录:
|
||||
* 2026-10-12 王建锋 从 net_socket.c 抽出监听生命周期(N-32 §10 模块化)
|
||||
* 2026-10-12 王建锋 从 net_socket.c 抽出监听生命周期(模块化,详述 docs/网络/网络自愈架构设计.md §9.3)
|
||||
* 2026-10-14 王建锋 单一所有者收口:net_listener_try(各调用点自带门、当场动作)
|
||||
* 改为 net_listener_request(只登记意图)+ net_listener_tick
|
||||
* (唯一执行者,门集与芯片在听判据集中一处)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* 限定条件:本文件真机专属——模拟器走 sim/net_socket_sim.c,
|
||||
* simulator/CMakeLists.txt 不编译本文件(同 net_listener.c 先例)
|
||||
*
|
||||
* 阻塞 recv / send 挂起模型(E-02 结构演进):阻塞等待 = 挂起请求 + 主循环节拍完成
|
||||
* 阻塞 recv / send 挂起模型(结构演进):阻塞等待 = 挂起请求 + 主循环节拍完成
|
||||
* "无数据 / 发送缓冲未空 + 阻塞等待"不再自旋占用 netTask:登记 pending 后立即返回
|
||||
* net_pending_tick / net_send_pending_tick(与 D10 重监听重试同节奏,
|
||||
* net_process_messages 开头每轮调用)
|
||||
@@ -73,7 +73,7 @@ void net_pending_capture_owner(void) {
|
||||
* 返回值:无
|
||||
* 限定条件:netTask 上下文;sockfd 合法且挂起在位(否则静默返回,防重复通知)
|
||||
* 函数说明:通知值 = 结果本身(与消息分派同一回传通道,调用方直接按通知值
|
||||
* 取结果);失败记入 netTask 自己的 errno 槽位(E-03)
|
||||
* 取结果);失败记入 netTask 自己的 errno 槽位
|
||||
*/
|
||||
static void net_pending_complete(int sockfd, int result) {
|
||||
/* 本 fd 挂起请求指针 */
|
||||
@@ -89,7 +89,7 @@ static void net_pending_complete(int sockfd, int result) {
|
||||
if (p->active == 0U) {
|
||||
return;
|
||||
}
|
||||
/* 失败结果:记入 netTask 自己的错误码槽位(E-03;不再写入跨任务共享全局) */
|
||||
/* 失败结果:记入 netTask 自己的错误码槽位(不再写入跨任务共享全局) */
|
||||
if (result < 0) {
|
||||
(void)net_set_errno(result);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ void net_pending_tick(net_sock_t *p_socks) {
|
||||
}
|
||||
|
||||
/* ③ 断连:排空 → 数据或 EOF(0) + 自动重监听。
|
||||
* 判据同 net_recv_locked(N-32 P1 不变量 I):`state == CLOSED ||
|
||||
* 判据同 net_recv_locked(监听生命周期 P1 不变量 I):`state == CLOSED ||
|
||||
* session_dead`。只判 CLOSED 时,抢先 relisten 后 ①(要求 ESTABLISHED)
|
||||
* 与 ③(要求 CLOSED) 两头落空 → 挂起的 recv 只能干等 ② deadline 超时
|
||||
* (lftpd 阻塞 recv 的"消费者卡死"原型)。无限等待登记没有 ②,
|
||||
@@ -259,7 +259,7 @@ void net_pending_tick(net_sock_t *p_socks) {
|
||||
* 原内层 `state == CLOSED` 门已**上收到 tick**——它防的是"对已回
|
||||
* LISTENING 的 fd 再 open+listen → 因 USE 错误走进关闭分支、关掉
|
||||
* 正听着的 Socket"(U12 同源),属执行侧安全不变量,不由登记点复述。
|
||||
* N-32 P2 修正:**保留本处即时登记** —— 它只在有**挂起 recv**
|
||||
* 监听生命周期 P2 修正:**保留本处即时登记** —— 它只在有**挂起 recv**
|
||||
* 时到达(`p->active != 0`),属"消费者在等这条连接结局"的
|
||||
* 消费者驱动路径,不是周期性抢先(同 net_recv_locked 的理由)。 */
|
||||
if (p_sock->auto_relisten != 0U) {
|
||||
@@ -312,7 +312,7 @@ void net_pending_tick(net_sock_t *p_socks) {
|
||||
* 出口参数:无
|
||||
* 返回值:1 - 有挂起;0 - 无(含描述符越界) int
|
||||
* 限定条件:任意上下文(纯 RAM 读,不发起 RPC)
|
||||
* 函数说明:1. N-32 §10 模块化:net_listener_tick 用它跳过"重开 Socket
|
||||
* 函数说明:1. 监听生命周期模块化:net_listener_tick 用它跳过"重开 Socket
|
||||
* 会摧毁在途连接"的 fd(挂起 recv 保险,原为直接读 s_net_pending[i].active)
|
||||
* 2. 声明在 net_pending.h(配对头,规范 S17 2.2)
|
||||
*/
|
||||
|
||||
@@ -123,7 +123,7 @@ void net_pending_settle_close(int sockfd, net_sock_t *p_sock);
|
||||
* 出口参数:无
|
||||
* 返回值:1 - 有挂起;0 - 无(含描述符越界) int
|
||||
* 限定条件:任意上下文(纯 RAM 读,不发起 RPC)
|
||||
* 函数说明:N-32 §10 模块化:net_listener_tick 用它跳过"重开 Socket
|
||||
* 函数说明:监听生命周期模块化:net_listener_tick 用它跳过"重开 Socket
|
||||
* 会摧毁在途连接"的 fd(挂起 recv 保险)
|
||||
*/
|
||||
int net_pending_active(int sockfd);
|
||||
|
||||
@@ -255,7 +255,7 @@ int net_poll_events(net_pollfd_t *fds, int nfds, int timeout) {
|
||||
* 出口参数:无
|
||||
* 返回值:1 - 可读(接收缓冲非空);0 - 不可读或描述符无效 int
|
||||
* 限定条件:net_init() 已调用
|
||||
* 函数说明:1. P2-7(2026-10-04):LISTENING 态**不再**恒判可读。本网络层无
|
||||
* 函数说明:1.(2026-10-04):LISTENING 态**不再**恒判可读。本网络层无
|
||||
* "待 accept 的挂起连接队列"——新连接到达时 CONNECT 事件把该 socket
|
||||
* 自身直接转为 ESTABLISHED(handle_connect_event:"监听自身转数据通道"),
|
||||
* 故监听态恒无数据可读。原实现对 LISTENING 恒返回 1,会使
|
||||
@@ -272,7 +272,7 @@ static int check_socket_readable(int sockfd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 监听态恒不可读(见上方 P2-7 说明) */
|
||||
/* 监听态恒不可读(见上方说明) */
|
||||
if (NET_SOCK_STATE_LISTENING == p_sock->state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ int net_msg_queue_adopt(osMessageQueueId_t queue_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================= 错误码存储(E-03 修复:按任务隔离,消除跨任务覆写竞态) =================
|
||||
/* ================= 错误码存储(按任务隔离,消除跨任务覆写竞态) =================
|
||||
*
|
||||
* 旧实现是单个全局 `static int s_net_errno`:netTask 在处理消息时写入本层的
|
||||
* 「最后错误码」,调用方包装器随后在**自己的上下文**再写一次。两条写路径分属不同
|
||||
@@ -227,7 +227,7 @@ static uint32_t net_errno_slot(void) {
|
||||
* 返回值:err 原值(便于写成 `return net_set_errno(NET_ERR_XXX);`)
|
||||
* 限定条件:无
|
||||
* 函数说明:1. 只写本任务的槽位,其他任务读不到、也改不了 → 消除跨任务覆写竞态
|
||||
* 2. N-32 §10 模块化:由 static 提升为**模块间可见**(net_listener.c
|
||||
* 2. 监听生命周期模块化:由 static 提升为**模块间可见**(net_listener.c
|
||||
* 也需要设 errno),声明与 NET_ERR_RETURN_1 宏见 net_socket.h
|
||||
*/
|
||||
int net_set_errno(int err) {
|
||||
@@ -332,7 +332,7 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
||||
* 无关),且违反保留位规定 → 0x09 改 0x08(2026-10-11 定案:官方手册
|
||||
* V1C/V1E/V2.2/V2.3 的 bit0 全是保留位,官方例程 bit0=0 下 Socket 0~7 照常
|
||||
* 可用、FTP 例程本身就传 0x08;证据链见 TRAP-NET-15,
|
||||
* 0x08 下的多 Socket 台架复测登记 N-31) */
|
||||
* 0x08 下的多 Socket 台架复测登记为 Phase 7 复跑项) */
|
||||
ch395f_set_fun_para(fun_para);
|
||||
|
||||
/* 设置 TCP MSS:维持 1024(512 裕量方案未采纳,当年支撑它的台架判据不可信,
|
||||
@@ -358,7 +358,7 @@ static bool s_mac_is_zero(const uint8_t *p_mac) {
|
||||
/* 设置 MAC(手册 §9.2.1 步骤①:SET_MAC 必须在 INIT_CH395 之前——SET_MAC 写芯片
|
||||
* EEPROM,而 INIT_CH395 会初始化/加载 MAC;顺序反了则本次上电芯片仍用旧 MAC,
|
||||
* UI 配置的 MAC 不生效(回落芯片内置/上次值),设备在线身份与 UI 显示不符。
|
||||
* P1-7,2026-10-04);NULL 或全零 = 保持芯片内置 MAC,不下发;
|
||||
* 2026-10-04);NULL 或全零 = 保持芯片内置 MAC,不下发;
|
||||
* 写 EEPROM,每上电重放同值幂等 */
|
||||
if (mac != NULL && s_mac_is_zero(mac) == false) {
|
||||
ch395f_set_mac_addr((uint8_t *)mac);
|
||||
@@ -572,7 +572,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);
|
||||
/* E-02 收口:驱动 sock_reset 状态机在 net_poll 步进
|
||||
/* 驱动 sock_reset 状态机在 net_poll 步进
|
||||
* (驱动头注释契约"在 net_poll 或测试循环里周期调用")。IDLE 槽位
|
||||
* 纯 RAM 判返回 0 无 SPI;仅活跃复位机做短 SPI。作用:同步包装
|
||||
* (net_sock_reset_sync)600ms 放弃后复位机不搁浅,芯片条件满足
|
||||
@@ -663,7 +663,7 @@ void net_process_messages(void) {
|
||||
net_send_pending_tick(s_net_socks);
|
||||
/* TRAP-NET-17 状态对账 + 监听重建合一(单一 100ms tick):
|
||||
* 判据读驱动缓存(net_poll 每轮全量刷新),①②⑤ 失同步 + ③④ 重建 +
|
||||
* U11 重同步全部在此(本层唯一周期重建入口,N-32 P2 单一所有者) */
|
||||
* U11 重同步全部在此(本层唯一周期重建入口,监听生命周期 P2 单一所有者) */
|
||||
net_reconcile_tick();
|
||||
|
||||
/* 队列排空:超时 0 非阻塞取,每条处理一轮,直到本轮队列为空 */
|
||||
@@ -758,8 +758,8 @@ void net_process_messages(void) {
|
||||
break;
|
||||
}
|
||||
case NET_MSG_DROP_CONN: {
|
||||
/* E-02 收口:应用放弃会话的主动拆除(拆连接、保监听)。监听型
|
||||
* 登记即返(N-17:拆链排渣交 net_listener_tick,本消息不再占用
|
||||
/* 应用放弃会话的主动拆除(拆连接、保监听)。监听型
|
||||
* 登记即返(探针窗口心跳缺口修复:拆链排渣交 net_listener_tick,本消息不再占用
|
||||
* netTask 数百 ms) */
|
||||
net_sock_t *p_sock = net_get_sock(msg.sockfd);
|
||||
if (p_sock == NULL) {
|
||||
@@ -813,7 +813,7 @@ void net_process_messages(void) {
|
||||
uint32_t notify_val = (uint32_t)msg.result;
|
||||
|
||||
/* 失败:回传本条消息**自身**的精确错误码(NET_ERR_WOULDBLOCK 等)。
|
||||
* E-03 后取的是 netTask 自己的错误码槽位——锁定实现(*_locked)在
|
||||
* 取的是 netTask 自己的错误码槽位——锁定实现(*_locked)在
|
||||
* 失败返回前记录的码,不受其他任务影响;未置位时回退通用 NET_ERR。 */
|
||||
if (msg.result < 0) {
|
||||
int te = s_net_errno_slots[net_errno_slot()].err;
|
||||
@@ -909,7 +909,7 @@ int net_socket(int domain, int type) {
|
||||
p_sock->blocking = 1;
|
||||
/* 新 fd 不得继承上一条连接的释放原因(TRAP-NET-18 待办 #3) */
|
||||
p_sock->released_abnormal = 0;
|
||||
/* N-32(P1):新 fd 不得继承"上一条会话已结束"电平(否则新建即 EOF,
|
||||
/* 监听生命周期 P1:新 fd 不得继承"上一条会话已结束"电平(否则新建即 EOF,
|
||||
* 消费侧连数据都收不到)——与 released_abnormal 同理,显式清零 */
|
||||
p_sock->session_dead = 0;
|
||||
/* 新 fd 不得继承上一次的待重试状态(D10) */
|
||||
@@ -1165,7 +1165,7 @@ int net_listen_locked(int sockfd) {
|
||||
p_sock->state = NET_SOCK_STATE_LISTENING;
|
||||
/* 单连接模式:连接断开后由 net 层自动回到 LISTEN(模拟 BSD 监听常驻) */
|
||||
p_sock->auto_relisten = 1;
|
||||
/* N-30(TRAP-NET-20):新监听会话,事件未收到去抖计数清零 */
|
||||
/* TRAP-NET-20:新监听会话,事件未收到去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
|
||||
/* 监听建立完成 */
|
||||
@@ -1232,7 +1232,7 @@ int net_listen(int sockfd) {
|
||||
* 限定条件:Socket 处于 LISTENING 状态
|
||||
* 函数说明:单连接:监听 Socket 自身在 CONNECT 后已转为 ESTABLISHED
|
||||
*/
|
||||
/* ===== N-30 accept 路径"CONNECT 事件未收到补 accept"(2026-10-11 台架实证;
|
||||
/* ===== TRAP-NET-20 accept 路径"CONNECT 事件未收到补 accept"(2026-10-11 台架实证;
|
||||
* E14 复核 2026-10-14:事件非芯片侧丢失,是被读清消费——机制不变)=====
|
||||
* 台架结论(剥离 OS/net/FTP 直接对芯片做受控 close→open→listen→connect 矩阵):
|
||||
* 芯片关闭连接后的拆链收尾窗口**变长且不可见**(状态寄存器显示 CLOSED 也不代表
|
||||
@@ -1274,7 +1274,7 @@ static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen
|
||||
/* 先轮询一次:把状态机刷新到芯片侧最新状态 */
|
||||
net_poll();
|
||||
|
||||
/* N-30(TRAP-NET-20):监听等待期兼做芯片状态第二信源——CONNECT 事件未收到时
|
||||
/* TRAP-NET-20:监听等待期兼做芯片状态第二信源——CONNECT 事件未收到时
|
||||
* 去抖补 accept(台架实证:拆链窗口事件未收到是数据被吞/425 的主根因,
|
||||
* E14 复核:事件非芯片丢失、被读清消费吞掉;纯事件等待无自愈可能;
|
||||
* 详见 net_lost_connect_probe 区块注释) */
|
||||
@@ -1286,13 +1286,13 @@ static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen
|
||||
* (含上一步探针补 accept 的命中);其余失同步由 net_reconcile_tick()
|
||||
* 周期对账(带去抖)兜底 */
|
||||
if (p_listen_sock->state != NET_SOCK_STATE_ESTABLISHED) {
|
||||
/* N-30(2026-10-11 手册 §5.23⑤ + 生产时间线定案):
|
||||
/* TRAP-NET-20(2026-10-11 手册 §5.23⑤ + 生产时间线定案):
|
||||
* "closed-but-readable" 接受——STOR 类传输客户端**发完数据立即关数据连接**
|
||||
* (正常 FTP 行为,Python ftplib sendall 后即 close),芯片按
|
||||
* FUN_PARA **bit3 SOCKET_CLOSE=1**(`0x08`,§5.52 ②)规格保留 Socket 与 RX 缓冲供 MCU 排空
|
||||
* (实测 DISCONNECT 后 st=0x05/0x00、recv_len=1027=完整载荷)。
|
||||
* 若 accept 轮询晚于对端 FIN,盲目 relisten(close+open 清缓冲)会把
|
||||
* 已到达的数据销毁 → 425(此前 N-30"425/被吞"的主根因,并非芯片杀连接)。
|
||||
* 已到达的数据销毁 → 425(此前 TRAP-NET-20"425/被吞"的主根因,并非芯片杀连接)。
|
||||
* 处置:芯片 RX 缓冲有数据 → 接受这条"已关但可读"连接,应用经
|
||||
* net_recv_locked 快路径(无状态门槛)排空,排空后 EOF 自然触发 relisten。 */
|
||||
int drain_pending = 0;
|
||||
@@ -1303,7 +1303,7 @@ static int net_accept_locked(int sockfd, struct net_sockaddr *addr, int *addrlen
|
||||
} else {
|
||||
/* 连接已断开(CLOSED)且无残留数据:登记重建请求,下一次 accept
|
||||
* 即可等待新连接(BSD 风格监听常驻)。
|
||||
* N-32 P2 修正:**保留本处即时登记** —— 它由消费者调 accept 触发
|
||||
* 监听生命周期 P2 修正:**保留本处即时登记** —— 它由消费者调 accept 触发
|
||||
* (消费者正在等新连接),不是周期性抢先;删掉会把 CLOSED 窗口
|
||||
* 拉长、导致调用方高频空转 accept(实测 [WD] task stall)。
|
||||
* 单一所有者收口后:动作发生在下一轮 net_listener_tick(≤1ms),非阻塞 */
|
||||
@@ -1446,7 +1446,7 @@ int net_listener_armed(int sockfd) {
|
||||
return 1;
|
||||
}
|
||||
/* 断连待重建态:**仅当芯片 RX 可能仍有残留数据**时放行,让
|
||||
* net_accept_locked 的 "closed-but-readable" 接受(N-30,对端"发完即 FIN")
|
||||
* net_accept_locked 的 "closed-but-readable" 接受(TRAP-NET-20,对端"发完即 FIN")
|
||||
* 仍能拿到该连接。
|
||||
* ⚠ 无残留时必须返回 0 —— 否则调用方会在整个 CLOSED 窗口内每轮都发起
|
||||
* net_accept(RPC:入队 + xTaskNotifyWait 回执**无上界**)→ 队列积压 →
|
||||
@@ -1694,11 +1694,11 @@ static int net_connect_locked(int sockfd, const struct net_sockaddr *addr, int a
|
||||
* 交给 CONNECT/TIM_OUT 裁定,不得当成失败(否则慢芯片会被误杀)。
|
||||
* 其余非 SUCCESS 均为明确的命令级失败(VAL/ARG/USE/OPEN/IF/MEM/BUF/RTE…):
|
||||
* 此前返回值被直接丢弃 → 本层停在 CONNECTING 干等 recv 30 s 超时才暴露
|
||||
* (2026-10-12 审计 B2)。按 §9.2.2 ⑧"再次连接需从 ⑤ 重开"回滚。 */
|
||||
* (2026-10-12 审计)。按 §9.2.2 ⑧"再次连接需从 ⑤ 重开"回滚。 */
|
||||
if ((status != CH395F_ERR_SUCCESS) && (status != CH395F_ERR_BUSY)) {
|
||||
DBG_ERROR("[CONN] sock%d TCP_CONNECT rejected by chip: 0x%02X", sockfd, status);
|
||||
(void)ch395f_close_socket((uint8_t)sockfd);
|
||||
/* N-32(P1 不变量 I):命令级失败同样是"本会话已结束"——此前这里只置
|
||||
/* 监听生命周期 P1 不变量 I:命令级失败同样是"本会话已结束"——此前这里只置
|
||||
* CLOSED,而 CONNECTING 态从未置 session_dead,挂起的 recv 只能干等
|
||||
* deadline(B2 审计发现的"停在 CONNECTING 干等 30s 超时才暴露"同源) */
|
||||
p_sock->session_dead = 1U;
|
||||
@@ -1891,7 +1891,7 @@ static int net_send_locked(net_sock_t *p_sock, const void *buf, int len,
|
||||
* 函数说明:1. 数据已在(快速路径)→ 立即读出返回
|
||||
* 2. 非阻塞(NET_MSG_DONTWAIT 单次覆盖 **或** socket blocking 属性为 0,
|
||||
* 模式属性)无数据立即返回 -1(NET_ERR_WOULDBLOCK)
|
||||
* 3. 无数据 + 阻塞等待 → 登记挂起请求(pending 化,E-02 结构演进)
|
||||
* 3. 无数据 + 阻塞等待 → 登记挂起请求(pending 化,结构演进)
|
||||
* 4. netTask 零占用立即返回;完成条件(数据/到点[仅显式预算]/断连)由 net_pending_tick 按主循环节拍检查
|
||||
* 5. 并通知 caller;关闭/网络重建/陈旧重同步由对应路径显式结束(取消必通知)
|
||||
* 6. CLOSED 状态语义(排空 + EOF + 自动重监听)逐项保留在 tick 内
|
||||
@@ -1936,7 +1936,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
/* 非阻塞且当前无数据:若连接已断开则视为 EOF(0) 并自动重监听,
|
||||
* 否则返回 WOULDBLOCK(-1) 表示暂时无数据 */
|
||||
/* 连接已断开(CLOSED)**或**本会话已结束(session_dead):按 EOF 处理。
|
||||
* 判据从纯 `state == CLOSED` 放宽为 `|| session_dead`(N-32 P1 不变量 I):
|
||||
* 判据从纯 `state == CLOSED` 放宽为 `|| session_dead`(监听生命周期 P1 不变量 I):
|
||||
* 抢先 relisten 后 state 已是 LISTENING 而会话确实已结束,旧判据在此
|
||||
* 恒返 WOULDBLOCK → EOF 永久失踪(新连接被旧会话静默吸收)。
|
||||
* 有数据时走上方快路径(recv_len>0 优先),本判据只在"无数据"时生效,
|
||||
@@ -1948,7 +1948,7 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
|
||||
* ch395f_close_socket → 把正听着新 SYN 的 Socket 当场关掉"(U12 同源
|
||||
* 事故)。这是**执行侧安全不变量**,不该由每个登记点各自复述——
|
||||
* 漏一处即事故;收口后 tick 另加"芯片已在听即了结",结构上不可能再犯。
|
||||
* N-32 P2 修正(2026-10-12 台架实证):**保留本处即时登记**——
|
||||
* 监听生命周期 P2 修正(2026-10-12 台架实证):**保留本处即时登记**——
|
||||
* 它是"消费者动作触发"(消费者正在等这条连接的结局),不是周期性
|
||||
* "抢先";删掉它会把 CLOSED 窗口从 ~0 拉长到 reconciler 周期+隔离期
|
||||
* (~100ms),期间调用方高频发起 net_accept(RPC 无上界)→
|
||||
@@ -2020,7 +2020,7 @@ static int net_close_locked(net_sock_t *p_sock) {
|
||||
}
|
||||
|
||||
/* 清零控制块(memset 0 = 释放本 fd 全部状态) */
|
||||
/* N-30(TRAP-NET-20):幽灵甄别基准跨 fd 释放保留(幽灵属芯片 Socket 级状态,
|
||||
/* TRAP-NET-20:幽灵甄别基准跨 fd 释放保留(幽灵属芯片 Socket 级状态,
|
||||
* 与 fd 复用无关——close 后新 listen 落在同一芯片 Socket 上仍可能撞幽灵) */
|
||||
uint16_t keep_peer = p_sock->remote_port;
|
||||
memset(p_sock, 0, sizeof(net_sock_t));
|
||||
@@ -2042,11 +2042,11 @@ static int net_close_locked(net_sock_t *p_sock) {
|
||||
* 出口参数:无
|
||||
* 返回值:0 - 拆除完成(监听型 fd 已重监听或交 D10) int
|
||||
* 限定条件:netTask 上下文;p_sock 在用且为 TCP 流
|
||||
* 函数说明:1. E-02 收口(《网络自愈架构设计》§5.2 E13):应用放弃的会话若 TCP 仍活
|
||||
* 函数说明:1.(《网络自愈架构设计》§5.2 E13):应用放弃的会话若 TCP 仍活
|
||||
* (PC 内核自动 ACK keepalive,僵尸判不死),单连接监听被永久
|
||||
* 占住;应用又不得 net_close 监听 fd(毁监听)——本函数补上
|
||||
* "拆连接不拆监听"的应用侧形态
|
||||
* 2. 芯片侧拆除(TRAP-NET-18 异常释放语义,N-17 收口改异步):监听型 fd
|
||||
* 2. 芯片侧拆除(TRAP-NET-18 异常释放语义,探针窗口心跳缺口收口改异步):监听型 fd
|
||||
* = net_listener_settle(QUARANTINE) + REQ_DROP 登记即返,动作全部交
|
||||
* net_listener_tick(隔离窗内持续排空/关闭正是该机的既有语义);
|
||||
* 非监听 client fd = 同步 sock_reset QUARANTINE(600ms 封顶,原形态)
|
||||
@@ -2064,7 +2064,7 @@ static int net_drop_conn_locked(net_sock_t *p_sock) {
|
||||
* 在本函数体内**没有任何机器表达**,而函数体是无条件的:置 CLOSED、清
|
||||
* readable、给监听型 fd 登记重建。也就是说——将来任何新增路径绕过
|
||||
* NET_MSG_DROP_CONN 的分派门直接调它,就会把一个**健康监听器**当会话拆掉
|
||||
* (症状是端口偶发不再 accept,与 N-30 一族同源难查)。断言把这条"进来时
|
||||
* (症状是端口偶发不再 accept,与 TRAP-NET-20 一族同源难查)。断言把这条"进来时
|
||||
* 必须处于活动会话态"钉成机器可查的不变量,正是"不该发生"而不是"外部输入"。
|
||||
* ⚠ 分派处(case NET_MSG_DROP_CONN)的三条错误返回原样保留——它们负责真机
|
||||
* 上把误用变成 -1,本断言负责在测试构建里把误用**当场喊出来**。
|
||||
@@ -2091,7 +2091,7 @@ static int net_drop_conn_locked(net_sock_t *p_sock) {
|
||||
* FIN 5/5 的通过版本)。旧形态在本处理器里 net_sock_reset_sync 同步等待,
|
||||
* netTask 被占用 400ms 底/600ms 顶:串行总线整窗停摆、UI/FTP/对时的 API 回
|
||||
* 执顺延、NET 与对时位同窗丢 100ms 抽样 → 800ms 停喂声明 stall,距 IWDG
|
||||
* 最坏超时余量仅 ~0.7s(登记簿 N-17;方向评估与否决论证 → 《网络自愈架构
|
||||
* 最坏超时余量仅 ~0.7s(探针窗口心跳缺口;方向评估与否决论证 → 《网络自愈架构
|
||||
* 设计》§4.6)。返回语义随之明确:返回 = 已登记,芯片未必已拆完。
|
||||
* 非监听 client fd:无监听可保,维持同步确定性排渣(600ms 封顶;全仓
|
||||
* 零生产调用者,形态原样保留防漂移)。 */
|
||||
@@ -2105,7 +2105,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):新会话起点,事件未收到去抖计数清零 */
|
||||
/* TRAP-NET-20:新会话起点,事件未收到去抖计数清零 */
|
||||
p_sock->lost_conn_seen = 0U;
|
||||
|
||||
if (p_sock->auto_relisten) {
|
||||
@@ -2293,7 +2293,7 @@ int net_recv_nb(int sockfd, void *buf, int len) {
|
||||
* 出口参数:无
|
||||
* 返回值:>0 字节数;0 = 对端关闭(EOF);-1 = 真错误(errno 可查);**-2 = 超时无数据**
|
||||
* 限定条件:非 netTask 上下文;net 层已初始化
|
||||
* 函数说明:1. E-02 修复配套接口:lftpd 等"等对端下一行/下一块数据"的调用方
|
||||
* 函数说明:1. 修复配套接口:lftpd 等"等对端下一行/下一块数据"的调用方
|
||||
* 若无限阻塞 recv,会把 netTask(全部 socket 操作的唯一执行者)长期占住
|
||||
* 2. 导致其余任务的网络操作整体冻结(M3 实测一次空闲 FTP 登录冻结远端显示 17.7s)
|
||||
* 3. 用本接口把等待切成 ≤timeout_ms 的片,调用方自行累计总预算:总超时语义不变、单次占用有界
|
||||
@@ -2335,7 +2335,7 @@ int net_recv_to(int sockfd, void *buf, int len, uint32_t timeout_ms) {
|
||||
msg.len = len;
|
||||
/* 阻塞式:netTask 侧轮询至"有数据"或"本片超时"(勿置 NET_MSG_DONTWAIT) */
|
||||
msg.flags = 0;
|
||||
/* 本片预算:netTask 最多等待 timeout_ms,保证对 netTask 的占用有界(E-02) */
|
||||
/* 本片预算:netTask 最多等待 timeout_ms,保证对 netTask 的占用有界 */
|
||||
msg.timeout_ms = timeout_ms;
|
||||
/* 记录调用任务句柄,netTask 处理后经 xTaskNotify() 精准回执 */
|
||||
msg.caller = xTaskGetCurrentTaskHandle();
|
||||
@@ -2440,9 +2440,9 @@ int net_close(int sockfd) {
|
||||
* (net 层 auto_relisten 已接管,见 AGENTS 单连接断开语义)
|
||||
* 函数说明:1. 单连接模型下挂起但 TCP 仍活的客户端会永久占住监听(keepalive
|
||||
* 被 PC 内核自动 ACK 判不死,《网络自愈架构设计》§5.2 E13);应用不得
|
||||
* net_close 监听 fd → 本 API 拆连接不拆监听(E-02 收口)
|
||||
* net_close 监听 fd → 本 API 拆连接不拆监听
|
||||
* 2. 监听型 fd:netTask 侧仅登记隔离沉降 + 重建请求即返回(动作在
|
||||
* net_listener_tick,netTask 零占用,登记簿 N-17 收口);非监听 client
|
||||
* net_listener_tick,netTask 零占用,探针窗口心跳缺口收口);非监听 client
|
||||
* fd 仍同步排渣(600ms 封顶)。见 net_drop_conn_locked
|
||||
*/
|
||||
int net_drop_conn(int sockfd) {
|
||||
@@ -2886,7 +2886,7 @@ int net_setblocking(int sockfd, int on) {
|
||||
* 出口参数:无
|
||||
* 返回值:错误码(NET_OK=0, NET_ERR_xxx=-N);本任务无失败记录时为 NET_OK
|
||||
* 限定条件:无(任何上下文可调用;中断上下文读 [0] 槽)
|
||||
* 函数说明:1. E-03 修复:错误码**按任务隔离**——只读本任务自己的槽位,
|
||||
* 函数说明:1. 错误码**按任务隔离**——只读本任务自己的槽位,
|
||||
* 其他任务的 net 调用再也覆盖不了它(旧实现为单一全局量,跨任务竞态)
|
||||
* 2. 调用成功时**不清零**(保持历史语义,向后兼容既有调用方)
|
||||
* 3. 超时场景(net_recv_to)请直接用返回码 -2 判定,不要依赖本接口
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef enum {
|
||||
NET_MSG_CONNECT,
|
||||
NET_MSG_LISTEN,
|
||||
NET_MSG_ACCEPT,
|
||||
NET_MSG_DROP_CONN, /* E-02 收口:主动拆会话、保监听(见 net_drop_conn) */
|
||||
NET_MSG_DROP_CONN, /* 主动拆会话、保监听(见 net_drop_conn) */
|
||||
/* F-NET-2/3:NET_MSG_RESYNC_LISTEN / NET_MSG_RELISTEN 已删——
|
||||
* 静默回收由对账⑤自动认领(net_reconcile_tick),重建由 reconciler
|
||||
* 形态③④/D10 单一
|
||||
@@ -186,7 +186,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||||
* 函数说明:1. 不变量 II(单一重建所有者;补齐 ESTABLISHED 放行):取代已退役的
|
||||
* `net_can_accept()`(只认 ESTABLISHED)作为监听 accept 门控——原门控使
|
||||
* :7003 永不进 `net_accept()`,
|
||||
* `net_lost_connect_probe`(CONNECT 事件未收到补 accept,N-30 实证的
|
||||
* `net_lost_connect_probe`(CONNECT 事件未收到补 accept,TRAP-NET-20 实证的
|
||||
* "数据被吞/425"主根因修复)对该端口等于从未运行
|
||||
* 2. 放行 LISTENING:探针与 "closed-but-readable 接受" 都发生在
|
||||
* `net_accept_locked` **内部**,门控挡在外面就永远到不了
|
||||
@@ -196,7 +196,7 @@ int net_accept(int sockfd, struct net_sockaddr *addr, int *addrlen);
|
||||
* (i104 200ms 抢不过对账② ~400ms 去抖)永不 accept、会话整场饿死
|
||||
* (实测全 18 项 FAIL)。此态 accept 必返 fd,无风暴风险
|
||||
* 3. 放行 CLOSED+auto_relisten **且 readable≠0**(有残留数据):
|
||||
* 保住 N-30 的 "closed-but-readable" 接受;**无残留时必须返回 0**,
|
||||
* 保住 TRAP-NET-20 的 "closed-but-readable" 接受;**无残留时必须返回 0**,
|
||||
* 否则调用方会在整个 CLOSED 窗口内每轮发起 `net_accept`(RPC 无上界)
|
||||
* → 队列积压 → 喂不上狗(2026-10-12 P2a 台架实测 48 条 task stall)。
|
||||
* 重建由 `net_reconcile_tick` 形态③④ 负责,调用方无需催促
|
||||
@@ -251,7 +251,7 @@ int net_connect(int sockfd, const struct net_sockaddr *addr, int addrlen);
|
||||
* 拷贝数据后触发发送——健康链路下(实测 219us 量级)行为与旧版逐字节一致
|
||||
* 2. 慢路径:自旋超预算后把请求**挂起登记**给 netTask,由
|
||||
* net_send_pending_tick 在发送缓冲区空闲时续传(分片 NET_SEND_CHUNK_MAX),
|
||||
* 调用方在任务通知上睡眠——**不再占用 netTask 执行者**(消除 E-02 队头阻塞)
|
||||
* 调用方在任务通知上睡眠——**不再占用 netTask 执行者**(消除队头阻塞)
|
||||
* 3. 短写语义:无论快路径超时还是挂起完成,只要存在未写完字节即按已发数返回,
|
||||
* 不假装全部成功;调用方按短写重试剩余部分(见 BSD_Socket_API 使用指南 §3.5)
|
||||
* 4. ⚠ 禁止在 IWDG required_mask 内任务做**无预算**的整块发送;挂起路径本身
|
||||
@@ -319,7 +319,7 @@ int net_setblocking(int sockfd, int on);
|
||||
* 函数说明:1. **显式预算**便捷入口(等价 Python settimeout,
|
||||
* 不再有隐藏默认值):net_recv 的无限阻塞 + 本接口的显式预算构成
|
||||
* 超时语义的全部来源;超时首选仍是 net_select
|
||||
* 2. E-02 修复配套:lftpd 等"等对端下一行/下一块数据"的调用方
|
||||
* 2. 修复配套:lftpd 等"等对端下一行/下一块数据"的调用方
|
||||
* 若无限阻塞 recv,会把 netTask(全部 socket 操作的唯一执行者)长期占住
|
||||
* 3. 用本接口把等待切成 ≤timeout_ms 的片,调用方自行累计总预算:总超时语义不变、单次占用有界
|
||||
* 4. 超时用独立返回码 -2(而非靠 errno 区分)→ 无跨任务 errno 竞态
|
||||
@@ -394,7 +394,7 @@ int net_recvfrom(int sockfd, void *buf, int len, int flags,
|
||||
int net_close(int sockfd);
|
||||
|
||||
/*
|
||||
* 函数功能:主动拆掉当前 TCP 会话,**保留监听**(E-02 收口)
|
||||
* 函数功能:主动拆掉当前 TCP 会话,**保留监听**
|
||||
* 入口参数:sockfd - socket 描述符
|
||||
* 返回值:0 成功(**监听型 fd 的“成功”= 拆除与重建已登记**,芯片未必已拆完,
|
||||
* 见函数说明 2;含幂等:无活动会话),-1 失败
|
||||
@@ -403,14 +403,14 @@ int net_close(int sockfd);
|
||||
* 单连接模型禁止对监听 fd net_close(连监听一起毁,AGENTS 约定),
|
||||
* 而挂起但 TCP 仍活的客户端会永久占住单连接监听(PC 内核自动
|
||||
* ACK keepalive,芯片僵尸判不死——《网络自愈架构设计》§5.2 E13 定案缺口)
|
||||
* 2. 实现(2026-10-25 N-17 起):auto_relisten fd = 登记 QUARANTINE 隔离
|
||||
* 2. 实现(2026-10-25 探针窗口心跳缺口修复起):auto_relisten fd = 登记 QUARANTINE 隔离
|
||||
* 沉降 + REQ_DROP 重建请求,**登记即返**——“FIN 关闭 + 排渣 + 排空
|
||||
* 事件 + 等 byte0=00H”(TRAP-NET-18 异常释放语义)与重建由
|
||||
* net_listener_tick 按 30ms 节奏异步执行,端口恢复窗 ~0.4-1s 与被动
|
||||
* 断连同型;**调用方不得按旧语义假设“返回即芯片已 CLOSED”**——返回
|
||||
* 后 accept/recv 得 WOULDBLOCK 直至重建完成(time_sync 既有轮询天然
|
||||
* 容忍)。旧同步形态曾使 netTask 占用 400-600ms、五任务心跳同窗
|
||||
* 缺席声明 stall(《网络自愈架构设计》§4.6 N-17 记录,勿复活)。
|
||||
* 缺席声明 stall(《网络自愈架构设计》§4.6 记录,勿复活)。
|
||||
* 非 auto_relisten(client fd)无监听可保,仍同步排渣(600ms 封顶)
|
||||
* 3. 幂等:非 ESTABLISHED/CONNECTING 直接返 0,不动监听
|
||||
*/
|
||||
@@ -441,7 +441,7 @@ int net_set_event_cb(int sockfd, net_event_cb_t cb, void *arg);
|
||||
* 出口参数:无
|
||||
* 返回值:错误码(NET_ERR_xxx);本任务尚无失败记录时为 NET_OK(0)
|
||||
* 限定条件:无(任何上下文可调用,含中断——查询为纯本任务索引读)
|
||||
* 函数说明:1. **按任务隔离**(2026-09-25 E-03 修复):错误码存在每个任务自己的
|
||||
* 函数说明:1. **按任务隔离**(2026-09-25):错误码存在每个任务自己的
|
||||
* 槽位里,任务间互不干扰,不存在跨任务覆写竞态——旧实现的单一全局
|
||||
* 变量会被 netTask/其他任务的 net 调用交错覆盖,调用方可能读到别人的码
|
||||
* 2. 语义:本任务最后一次返回 -1 的 net_*() 调用所对应的精确码;
|
||||
@@ -562,13 +562,13 @@ net_sock_t *net_sock_raw(int sockfd);
|
||||
* 返回值:err 原值(便于写成 `return net_set_errno(NET_ERR_XXX);`)
|
||||
* 限定条件:无
|
||||
* 函数说明:1. 只写本任务的槽位,其他任务读不到、也改不了 → 消除跨任务覆写竞态
|
||||
* 2. N-32 §10 模块化:由 net_socket.c 的 static 提升为**模块间可见**,
|
||||
* 2. 监听生命周期模块化:由 net_socket.c 的 static 提升为**模块间可见**,
|
||||
* 供 net_listener.c 等同目录内部模块复用(定义仍在 net_socket.c)
|
||||
*/
|
||||
int net_set_errno(int err);
|
||||
|
||||
/* 「记本任务错误码 + 统一失败返回 -1」的紧凑写法(取代 `s_net_errno = X; return -1;`)
|
||||
* N-32 §10:原定义在 net_socket.c,随 net_set_errno 一并提升到本头文件 */
|
||||
* 监听生命周期模块化:原定义在 net_socket.c,随 net_set_errno 一并提升到本头文件 */
|
||||
#define NET_ERR_RETURN_1(err) (net_set_errno(err), -1)
|
||||
|
||||
/*
|
||||
|
||||
@@ -203,18 +203,18 @@ typedef struct {
|
||||
* 连接的释放原因。 */
|
||||
uint8_t released_abnormal;
|
||||
|
||||
/* N-30(2026-10-11 裸机芯片台架实证):本 Socket 上一条被释放连接的**对端端口**。
|
||||
/* TRAP-NET-20(2026-10-11 裸机芯片台架实证):本 Socket 上一条被释放连接的**对端端口**。
|
||||
* 芯片拆链收尾窗口内旧连接未拆净,Socket 如实为 ESTABLISHED(幽灵态,E15:
|
||||
* bit3=1 保留现场契约,非谎报),此时回读的对端端口
|
||||
* = 旧连接端口;新连接的临时端口几乎必然不同。accept 路径补 accept 与对账②
|
||||
* 均以此甄别幽灵态(见 net_socket.c TRAP-NET-20)。跨 fd 释放保留(幽灵属芯片
|
||||
* Socket 级,与 fd 复用无关),新连接断开时刷新。 */
|
||||
uint16_t last_peer_port;
|
||||
/* N-30:accept 路径"CONNECT 事件未收到补 accept"的去抖计数(连续确认次数,
|
||||
/* TRAP-NET-20:accept 路径"CONNECT 事件未收到补 accept"的去抖计数(连续确认次数,
|
||||
* 节拍 = accept 轮询 100ms;新监听/补 accept 后清零) */
|
||||
uint8_t lost_conn_seen;
|
||||
|
||||
/* N-32 / B10 根治 P1(2026-10-12,设计文档 §2.3 不变量 I):本会话"已结束"的
|
||||
/* 监听生命周期 P1(B10 根治,2026-10-12,设计文档 §2.3 不变量 I):本会话"已结束"的
|
||||
* **电平**(粘滞),取代 `state == CLOSED` 这一**边沿**。
|
||||
* 为什么必须电平化:单连接复用模型下同一个 fd 既是监听器又是连接(handle
|
||||
* aliasing),"关掉一条连接"与"毁掉一个监听器"在类型上无法区分;而"会话结束"
|
||||
|
||||
Reference in New Issue
Block a user