refactor(编号): 第一批清号——登记簿旧号/阶段号/台架阶段裸形三族清零,位号目录排除
按 §9 批次一执行。**这批的关键发现是「看着像 62 处编号,实际能算编号的只有一小半」**,所以先分类再动手, 没有按站点数硬清: · **真·编号(已改名)**:`N-6`(`MDK-ARM/tcp_reconnect_probe.py` 的「TRAP-NET-17 / N-6 」→ 只留 TRAP 锚点 + 中文说明);台架阶段裸形 `T0`~`T3` 全部转成场景名——`e11_keepalive_probe.py` 的「静默对端 / 正常空闲存活」、 `ftp_auth_bench.py` 的「匿名登录 / 未登录直接 NLST / 错口令锁定」、`serial_tool.py` 自检里的「行拆分 / 解码回退链 / 时间戳行格式 / 端口建议」、`net_test_task.c` 与 `CH395F_Test_Guide.md` 的「空闲存活场景」、 网络自愈设计里的「三路审计」。另把 `test/host/iec104_master.py` 的变量 `T0` 改成 `t_start`(那是起始时刻 变量,被裸形族误抓)。 · **不是编号、但被误判(按 §4.4 处理,不改语料)**:`tools/netlist_semantics/` 里的 `T1` 是**网络变压 器位号** (硬件知识库),整目录进 `excluded_paths`,与 `docs/硬件平台/` 同口径;`BSD_Socket_API_函数调用关系. md` 的 `T1/T2/T3` 是 **Mermaid 节点名**,已改成语义节点(`RetryTick`/`PendTick`/`PendShimTic k`/`ReconcileTick`)—— 图本身没变,只是节点不再叫字母号;`docs/门禁说明/gitlint.md` 里的 `T2` 是 **gitlint 自己的规则名**(不是本仓 的号),已改写成规则描述;`docs/算法/傅氏算法详解.md` 的 `N-1` 是**数学记号**(求和上界 `x(N-1)`),保留不动, 并在 §4.4 登记为「唯一已知误判」。 · **规范自身两处示例**顺手去掉字面量:`S3 / TM-PHY-01 / DP-03` → `S3 / TM-… / DP-…`;「报告 N- 16」→「报告 + 登记簿旧号」。 结果(用门禁接口复测):`TM` 族 0 引用、`T-TEST` 族只剩规范自身 2 处示例、`N` 族只剩数学记号 1 处; `F-*`(38 站点 / 12 个号,代码注释里的网络设计条目号)**留下批单独做**,因为每处要读懂语义、不能替换字面量。 口径变更已写进 §4.4:位号目录 `tools/netlist_semantics/` 进排除面;`N-1` 声明为已知误判。歧义面收窄后, 新错误级仍为 0、`id-check --strict` exit 0。 ⚠ 这批**刻意没有复活「别名表洗白」那条路**:`N-6` 这类死号不进 `id_aliases.json`,让门禁继续咬将来的残留 引用(与 FTP 死号同一处理,见 §5.7)。
This commit is contained in:
@@ -1123,26 +1123,26 @@ def run_selftest():
|
||||
def check(name, cond, detail=""):
|
||||
results.append((name, bool(cond), detail))
|
||||
|
||||
# T1 行拆分:CRLF / 多行 / 残行冲刷
|
||||
# 行拆分:CRLF / 多行 / 残行冲刷
|
||||
sp = LineSplitter()
|
||||
got = [l for _, l in sp.feed(b"abc\r\n", 1000.0)]
|
||||
check("T1a CRLF 行", got == [b"abc"], repr(got))
|
||||
check("行拆分:CRLF 行", got == [b"abc"], repr(got))
|
||||
got = [l for _, l in sp.feed(b"de\nf\n", 1001.0)]
|
||||
check("T1b 多行", got == [b"de", b"f"], repr(got))
|
||||
check("T1c 残行不入文件", sp.feed(b"ghi", 1002.0) == [] and sp.buf == b"ghi")
|
||||
check("行拆分:多行", got == [b"de", b"f"], repr(got))
|
||||
check("行拆分:残行不入文件", sp.feed(b"ghi", 1002.0) == [] and sp.buf == b"ghi")
|
||||
got = [l for _, l in sp.flush_partial()]
|
||||
check("T1d 残行冲刷", got == [b"ghi"], repr(got))
|
||||
check("行拆分:残行冲刷", got == [b"ghi"], repr(got))
|
||||
got = sp.feed(b"\n\n", 1003.0)
|
||||
check("T1e 空行忽略", all(not raw for _, raw in got) and sp.buf == b"", repr(got))
|
||||
check("行拆分:空行忽略", all(not raw for _, raw in got) and sp.buf == b"", repr(got))
|
||||
|
||||
# T2 解码回退链
|
||||
# 解码回退链
|
||||
check("T2a UTF-8", decode_line("中文ok".encode("utf-8")) == "中文ok")
|
||||
check("T2b GBK", decode_line("中文".encode("gbk")) == "中文")
|
||||
check("T2c HEX 兜底", decode_line(b"\xff\xfe\x01") == "HEX:fffe01")
|
||||
|
||||
# T3 时间戳格式
|
||||
# 时间戳格式
|
||||
s = line_at(time.time(), "RX", "x")
|
||||
check("T3 行格式", s.startswith("[RX] ") and "T" in s.split(" ")[1], s)
|
||||
check("时间戳行格式", s.startswith("[RX] ") and "T" in s.split(" ")[1], s)
|
||||
|
||||
# T4 截头算法(保留尾部 + 截后继续追加)
|
||||
pat = b"0123456789abcdef"
|
||||
@@ -1298,8 +1298,8 @@ def run_selftest():
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# T10 端口建议:换 USB 口后 COM 号变了,唯一候选直接给(多候选不猜)
|
||||
check("T10 port_hint 唯一候选才给建议",
|
||||
# 端口建议:换 USB 口后 COM 号变了,唯一候选直接给(多候选不猜)
|
||||
check("端口建议:唯一候选才给建议",
|
||||
port_hint("COM7", ["COM6"]) == "COM6"
|
||||
and port_hint("COM7", ["COM6", "COM9"]) is None
|
||||
and port_hint("COM6", ["COM6"]) is None)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# TRAP-NET-17 / N-6 trustworthy reproduction probe: rapid reconnect to a device listener.
|
||||
# TRAP-NET-17 复现探针:快速重连到设备监听器: rapid reconnect to a device listener.
|
||||
#
|
||||
# Failure under test (original report): after a rapid reconnect (<~1s) on a
|
||||
# relistened socket, the chip completes the handshake but the MCU never gets
|
||||
|
||||
@@ -1095,7 +1095,7 @@ IDLE → ACCEPT → [SEND: 分块发 → DONE] / [RECV: 分块收+校验 → DON
|
||||
| **标题** | TCP 连接空闲超过 KeepAlive 阈值后自动断开 |
|
||||
| **前置条件** | 1. `NET_KEEPALIVE_IDLE_MS=60000` / `INTVL=5000` / `CNT=3`(`net_config.h`)<br>2. 对端须为**死对端**:PC 连接 8080 后**禁用网卡**制造"链路在、对端静默"(存活对端会 ACK 探测 → 永不 TIMEOUT;Windows 防火墙规则对已建立连接无效,E11 实证)<br>3. 勿与 Phase 6/9/10/13 混选(recv 互抢数据) |
|
||||
| **测试步骤** | 1. PC 连接 8080,不发数据<br>2. 立即禁用 PC 网卡(中间有交换机 → 设备侧 PHY 链路保持)<br>3. 等待芯片报 TIM_OUT(实测判死窗:连接起 **18~31s**,芯片定时语义与手册公式 75s 不符,见 `docs/网络/网络自愈架构设计.md` §5.2 E11/E13)<br>4. 本层 QUARANTINE → reconciler 形态③④ 重建 → s0 回 LISTEN<br>5. 恢复网卡,重连 8080 验证端口已恢复 |
|
||||
| **通过标准** | recv 返回 0 且耗时落在 **10s~120s 有界窗**(下限防"存活空闲会话被误杀"——T2 实测存活对端静默 90s 不触发;上限防"判死缺位");s0 回 LISTEN 且可接受新连接。报告后测试自动释放 socket 等新连接再测(一次性,防对已死连接 10ms 节奏刷假 FAIL) |
|
||||
| **通过标准** | recv 返回 0 且耗时落在 **10s~120s 有界窗**(下限防"存活空闲会话被误杀"——空闲存活场景实测存活对端静默 90s 不触发;上限防"判死缺位");s0 回 LISTEN 且可接受新连接。报告后测试自动释放 socket 等新连接再测(一次性,防对已死连接 10ms 节奏刷假 FAIL) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+8
-3
@@ -74,7 +74,7 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
|
||||
- 登记处就是那张表:表首格写短语,**不要再配一个字母号**;跨文档引用写成
|
||||
`` `docs/任务规划/登记簿.md` 「双转换器无共同采样触发」 ``,同篇后续直接用短语。
|
||||
- 文档内的实施步骤 / 测试阶段 / 设计原则条目写中文:「步骤 3」「阶段 7」「DMA 边界安全」,
|
||||
**不写 `S3` / `TM-PHY-01` / `DP-03` 这种号**。
|
||||
**不写 `S3` / `TM-…` / `DP-…` 这种号**。
|
||||
|
||||
---
|
||||
|
||||
@@ -128,11 +128,16 @@ P-6 号必须能反查到定义(属主登记处得存在)· P-7 编号不语
|
||||
元器件位号 `U1`/`C12`/`R3`/`L5`/`D7`(硬件语料按目录整体排除)、数学与协议记号(`N-1`、测频的正序与
|
||||
负序分量 `S1`/`S2`、`SHA-256`、`RS-485`、`ADC1_IN14`、手册页码)、活表代号 `E0~E19`(网络自愈 §5.2,
|
||||
**无连字符**,与死号 `E-nn` 只差一个连字符)、Socket 状态组合 `U1~U15`(网络自愈 §1.1)、档位词 `P0~P3`。
|
||||
判据只有一条:**带连字符、且能在属主登记表查到定义**才叫编号;查不到的就是普通文本,不是"漏登记的号"。
|
||||
判据只有一条:**带连字符、且能在属主登记表查到定义**才叫编号;查不到的就是普通文本,不是「漏登记的号」。
|
||||
|
||||
> 2026-10-27 补两条实测口径:① **元器件位号目录整体排除**——`tools/netlist_semantics/` 是硬件知识库
|
||||
> (`T1` 在那里是网络变压器位号),已进 `id_registry.json` 的 `excluded_paths`,与 `docs/硬件平台/` 同口径;
|
||||
> ② **唯一已知误判**:`docs/算法/傅氏算法详解.md` 里的数学记号 `N-1`(「一个周波 N 个点」的求和上界)会被
|
||||
> `N-x` 族命中,属可判定引用、不影响两根护栏,**不清**——清了反而破坏公式。
|
||||
|
||||
### 4.5 已删报告的自有族
|
||||
《项目审查与优化建议报告》2026-10-25 已删除,它自造的六族随之失去定义,且与登记簿同字母不同义。
|
||||
看到"报告 N-16"这类写法一律按死号处理:删号留事实——各条目原本指向的设计文档就是现在的出处。
|
||||
看到「报告 + 登记簿旧号」这类写法一律按死号处理:删号留事实——各条目原本指向的设计文档就是现在的出处。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -50,10 +50,10 @@ flowchart TB
|
||||
subgraph NT["netTask 主循环 — 1ms/tick;芯片操作唯一执行者"]
|
||||
NPM["netProcessMessages<br/>先跑 4 个 tick,再排空队列分派"]
|
||||
NP["netPoll<br/>INT# GPIO 轮询 → 全局中断 → 各 Socket SINT → 状态缓存全量刷新 + sock_reset 步进 → 每轮一批"]
|
||||
T1["① netListenerRetryTick<br/>D10 重监听重试:30ms / 2s 时限"]
|
||||
T2["② netPendingTick<br/>挂起 recv:①数据 ②到点(仅显式预算) ③断连 ④tripwire 60s 只留痕"]
|
||||
T2B["③ netSendPendingTick<br/>挂起 send:①断连 ②推进(每轮≤1块) ③写完 ④无进展超时"]
|
||||
T3["④ netReconcileTick<br/>TRAP-NET-17 对账 + 监听重建合一:100ms / 分级去抖 / 冷却<br/>读驱动状态缓存(①②③④⑤ + U11)"]
|
||||
RetryTick["① netListenerRetryTick<br/>D10 重监听重试:30ms / 2s 时限"]
|
||||
PendTick["② netPendingTick<br/>挂起 recv:①数据 ②到点(仅显式预算) ③断连 ④tripwire 60s 只留痕"]
|
||||
PendShimTick["③ netSendPendingTick<br/>挂起 send:①断连 ②推进(每轮≤1块) ③写完 ④无进展超时"]
|
||||
ReconcileTick["④ netReconcileTick<br/>TRAP-NET-17 对账 + 监听重建合一:100ms / 分级去抖 / 冷却<br/>读驱动状态缓存(①②③④⑤ + U11)"]
|
||||
DISP["队列分派 switch<br/>SEND · RECV · CLOSE<br/>CONNECT · LISTEN · ACCEPT · DROP_CONN"]
|
||||
subgraph LK["_locked / 内部分派目标(仅 netTask 上下文)"]
|
||||
LL["netListenLocked<br/>初次监听(open 重试 3× + sock_reset 排渣)"]
|
||||
@@ -76,24 +76,24 @@ flowchart TB
|
||||
PUB -->|入队| MQ
|
||||
MQ --> DISP
|
||||
DISP --> LL & LN & LS & LR & LA & LC & DC & RLS
|
||||
NPM --> T1 & T2 & T2B & T3 & NP
|
||||
T1 --> RLS
|
||||
T3 -->|"① 已断"| EV
|
||||
T3 -->|"② 补 accept"| EV
|
||||
T3 -->|"⑤ 静默回收:RESYNC 只修本层 + 取消挂起(不发芯片命令,吸收原 net_resync_listen 语义)"| RSY["reconcile⑤ RESYNC 动作"]
|
||||
T3 -->|"③④ 监听失位 / 孤儿监听即重建(原 pump)"| RLS
|
||||
NPM --> RetryTick & PendTick & PendShimTick & ReconcileTick & NP
|
||||
RetryTick --> RLS
|
||||
ReconcileTick -->|"① 已断"| EV
|
||||
ReconcileTick -->|"② 补 accept"| EV
|
||||
ReconcileTick -->|"⑤ 静默回收:RESYNC 只修本层 + 取消挂起(不发芯片命令,吸收原 net_resync_listen 语义)"| RSY["reconcile⑤ RESYNC 动作"]
|
||||
ReconcileTick -->|"③④ 监听失位 / 孤儿监听即重建(原 pump)"| RLS
|
||||
DC -->|"拆会话后登记重监听"| RLS
|
||||
NP --> EV
|
||||
EV --> FE
|
||||
FE -.-> CB
|
||||
EV -->|"断连/超时:只置事实"| ST
|
||||
ST -.->|"事实 → 由 reconciler 形态③④ 统一重建"| T3
|
||||
ST -.->|"事实 → 由 reconciler 形态③④ 统一重建"| ReconcileTick
|
||||
LR -->|无数据+阻塞| PR
|
||||
PR --> T2
|
||||
T2 -->|xTaskNotify| XN
|
||||
PR --> PendTick
|
||||
PendTick -->|xTaskNotify| XN
|
||||
LS -->|等发送缓冲超预算| SR
|
||||
SR --> T2B
|
||||
T2B -->|xTaskNotify| XN
|
||||
SR --> PendShimTick
|
||||
PendShimTick -->|xTaskNotify| XN
|
||||
XN -->|唤醒| PUB
|
||||
NP --> CH
|
||||
LL & LN & LS & LR & LA & LC & DC & RLS --> CH
|
||||
@@ -107,7 +107,7 @@ flowchart TB
|
||||
2. `net_process_messages()` 开头的 **4 个 tick 是网络层自愈主干**:没有任何应用消息时,重试 / 挂起 recv 完成 / 挂起 send 推进 / 状态对账 + 监听重建照常运转——"断连后即使没人发消息,监听器也能自己活过来"靠的就是它们。
|
||||
3. 事件处理器**只由 `net_poll` 驱动**,例外是 `net_reconcile_tick`(分级去抖 + 1s 冷却)可再入 `handle_disconnect_event` / `handle_connect_event`——对账是事件未收到的自愈通道(TRAP-NET-17)。**注意职责边界(对账与重建合并后)**:对账与事件处理器**只置事实**(置 CLOSED / 登记沉降),**重建监听的动作统一由 `net_reconcile_tick` 形态③④ 做**(本层唯一重建入口)——"谁先看到 DISCONNECT 就谁重建"的竞争在结构上消失。
|
||||
4. 回调 `event_cb` 在 **netTask 上下文**执行:回调内不得阻塞、不得发网络操作。
|
||||
5. **模块归属**:`T1`(D10 重试)/ `RLS` 的 `net_listener_request` / `ST`(settle)在 `net_listener.c`(真机专属、模拟器不编译);挂起 recv 完成检查(`net_pending_tick`)、挂起 send 推进(`net_send_pending_tick`)与两张挂起表(`PR` / `SR`)在 `net_pending.c`(真机专属);其余 tick(含合并后的 `T3` reconciler)与 `_locked` 在 `net_socket.c`。
|
||||
5. **模块归属**:`RetryTick`(D10 重试)/ `RLS` 的 `net_listener_request` / `ST`(settle)在 `net_listener.c`(真机专属、模拟器不编译);挂起 recv 完成检查(`net_pending_tick`)、挂起 send 推进(`net_send_pending_tick`)与两张挂起表(`PR` / `SR`)在 `net_pending.c`(真机专属);其余 tick(含合并后的 `ReconcileTick` reconciler)与 `_locked` 在 `net_socket.c`。
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -858,7 +858,7 @@ accept 走 `handle_connect_event`),且 `NET_RECON_STABLE_DEATH` 两边共用
|
||||
- 本文引用格式:`docs/网络/网络自愈架构设计.md` §N.M(紧邻写法);E 编号引 §5.2
|
||||
(如"§5.2 E12"),F 编号引 §7。
|
||||
- **勿引用已删除的过程章节**。过程考古:
|
||||
- N34 自愈审计(T1~T4 三路审计、39 条编号发现全文、E0~E15 原始记录、分阶段实施清单):
|
||||
- N34 自愈审计(三路审计、39 条编号发现全文、E0~E15 原始记录、分阶段实施清单):
|
||||
`git show 1a35b36^:docs/网络/N34-自愈审计/`(目录合并前 7 份文档)或
|
||||
`git log --oneline -- docs/网络/N34-自愈审计/`;
|
||||
- 监听生命周期(本文 §1.1~§1.4 / §4.9 / §9~§11 的来源,含 P0~P3 勾选清单与台架验收记录):
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
```
|
||||
gitlint..............................................................Failed
|
||||
12: BBody line length limit exceeded, lengthy body line (max-line-length: 79)
|
||||
1: T2 Title has trailing whitespace
|
||||
1: Title has trailing whitespace
|
||||
```
|
||||
|
||||
- 前缀数字是行号(第 1 行是标题)。本仓最常犯的是 `B`(正文行超长)与标题超 100。
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
".dsh/n31_neg_inject_gen221_form5.log",
|
||||
"scripts/id_known_backlog.json",
|
||||
"scripts/rename_maps/",
|
||||
"docs/硬件平台/"
|
||||
"docs/硬件平台/",
|
||||
"tools/netlist_semantics/"
|
||||
],
|
||||
"excluded_suffixes": [
|
||||
".svg",
|
||||
@@ -133,7 +134,8 @@
|
||||
"^Y[0-9]-[0-9]+$",
|
||||
"^A-Z0-9$",
|
||||
"^X-[0-9]+$",
|
||||
"^V[0-9A-Z]{2,}-[0-9]+$"
|
||||
"^V[0-9A-Z]{2,}-[0-9]+$",
|
||||
"N-1"
|
||||
],
|
||||
"malformed": [
|
||||
{
|
||||
|
||||
@@ -842,7 +842,7 @@ static int phase11_run(int32_t sockfd) {
|
||||
* 生产参数实测判死窗口 18~31s(产品验证 连接+30.5s、E11 T5
|
||||
* 对端失联+30s、T4 短参数 连接+~10s)。本 socket 无在途 TX、
|
||||
* 对端静默且已失联 → 唯一开枪源是 keepalive,故判据为
|
||||
* **有界窗**:>=10s(存活空闲会话 T2 实测 90s 不被杀,10s 下限
|
||||
* **有界窗**:>=10s(存活空闲会话 空闲存活场景实测 90s 不被杀,10s 下限
|
||||
* 区分"误杀"与"keepalive 判死")且 <=120s(判死必须发生)。
|
||||
* 勿改回 >=60000——那是对着手册公式写的,会在正确固件上假 FAIL */
|
||||
TEST_CHECK(elapsed >= 10000U && elapsed <= 120000U,
|
||||
|
||||
@@ -8,18 +8,18 @@ App/ 无任何 net_connect() → 产品上 keepalive 实际关闭。本脚本用
|
||||
"开启后能否在有界时间内判死静默对端,且不误杀正常空闲会话"。
|
||||
|
||||
用法:
|
||||
# T2 正常空闲存活:连接后静默 hold 秒,末尾发 KEEPLIVE 验证会话仍在
|
||||
# 场景「正常空闲存活」:连接后静默 hold 秒,末尾发 KEEPLIVE 验证会话仍在
|
||||
python e11_keepalive_probe.py --mode idle --hold-s 90
|
||||
|
||||
# T1 静默对端:连接后立即装 Windows 防火墙入站 DROP(仅本连接本地端口 +
|
||||
# 场景「静默对端」:连接后立即装 Windows 防火墙入站 DROP(仅本连接本地端口 +
|
||||
# 设备 IP)→ 芯片 keepalive 探测得不到 ACK → 期望设备在
|
||||
# IDLE + INTVL×CNT 内判死(本仓 60 + 5x3 = 75s)
|
||||
python e11_keepalive_probe.py --mode block --hold-s 120
|
||||
|
||||
判据(设备侧事件由串口日志核对,本脚本打印 PC 侧时间线):
|
||||
T1 期望:串口出现 `[ERR][NET] sockN TIMEOUT`(耗时≈75s),随后
|
||||
期望:串口出现 `[ERR][NET] sockN TIMEOUT`(耗时≈75s),随后
|
||||
`sockN pump/relisten` 恢复;本脚本移除规则后新连接必须成功。
|
||||
T2 期望:hold 期间**无** TIMEOUT;末尾 KEEPLIVE 必须收到 0xBB 回显。
|
||||
期望:hold 期间**无** TIMEOUT;末尾 KEEPLIVE 必须收到 0xBB 回显。
|
||||
|
||||
需要管理员权限(仅 block 模式装/卸防火墙规则;脚本自行清理)。
|
||||
"""
|
||||
|
||||
+11
-11
@@ -5,9 +5,9 @@
|
||||
验证固件侧 lftpd 鉴权集成的完整行为矩阵(主机单测 test/host/ftp_auth 覆盖
|
||||
不到的"协议接线"部分:命令门、530/331/230/550 响应码、跨会话锁定):
|
||||
|
||||
T1 匿名登录(anonymous) → 期望 530 拒
|
||||
T2 未登录直接 NLST → 期望 530(命令门)
|
||||
T3 对用户名 + 错口令 ×5 → 期望 530 ×5(并触发锁定)
|
||||
场景「匿名登录」(anonymous) → 期望 530 拒
|
||||
场景「未登录直接 NLST」 → 期望 530(命令门)
|
||||
场景「对用户名 + 错口令 ×5」 → 期望 530 ×5(并触发锁定)
|
||||
T4 锁定窗内正确口令 → 期望 530(LOCKED,不算哈希)
|
||||
T5 等待锁定期满后正确口令 → 期望 230(60s + 余量)
|
||||
T6 登录后 NLST / STOR / RETR / DELE → 期望全通(出厂 write=1)
|
||||
@@ -83,26 +83,26 @@ def main(argv=None):
|
||||
if not cond:
|
||||
fails.append(name)
|
||||
|
||||
# ---- T1 匿名登录被拒 ----
|
||||
# ---- 场景「匿名登录被拒」----
|
||||
ok, code, conn = _try_login(args.host, args.port, args.timeout, "anonymous", "x@x")
|
||||
if ok is None:
|
||||
print("[env] 连不上 %s:%d → %s" % (args.host, args.port, code))
|
||||
return 2
|
||||
expect("T1 匿名登录 → 530", (ok is False) and code.startswith("530"), code)
|
||||
expect("匿名登录 → 530", (ok is False) and code.startswith("530"), code)
|
||||
if conn:
|
||||
conn.quit()
|
||||
|
||||
# ---- T2 未登录直接 NLST → 530(命令门)----
|
||||
# ---- 场景「未登录直接 NLST → 530(命令门)」----
|
||||
time.sleep(0.5) # 单连接 socket:等 auto_relisten 沉降(~50 ms + 余量)
|
||||
f = FTP()
|
||||
f.connect(args.host, args.port, timeout=args.timeout)
|
||||
try:
|
||||
f.sendcmd("NLST")
|
||||
expect("T2 未登录 NLST → 530", False, "居然放行")
|
||||
expect("未登录 NLST → 530", False, "居然放行")
|
||||
except error_perm as e:
|
||||
expect("T2 未登录 NLST → 530", str(e).startswith("530"), str(e))
|
||||
expect("未登录 NLST → 530", str(e).startswith("530"), str(e))
|
||||
except Exception as e: # noqa: BLE001
|
||||
expect("T2 未登录 NLST → 530", False, repr(e))
|
||||
expect("未登录 NLST → 530", False, repr(e))
|
||||
# ⚠ 必须 close:单连接模型下不关 = 占住 socket,后续步骤全被拒
|
||||
# (2026-10-11 台架实测:QUIT 后不 close → 芯片视角旧连接仍 ESTABLISHED)
|
||||
try:
|
||||
@@ -114,11 +114,11 @@ def main(argv=None):
|
||||
pass
|
||||
time.sleep(0.5)
|
||||
|
||||
# ---- T3 错口令 ×5 → 530 ×5 ----
|
||||
# ---- 场景「错口令 ×5 → 530 ×5」----
|
||||
for i in range(1, 6):
|
||||
ok, code, conn = _try_login(args.host, args.port, args.timeout,
|
||||
args.user, "wrong-pass-%d" % i)
|
||||
expect("T3.%d 错口令 → 530" % i, (ok is False) and code.startswith("530"), code)
|
||||
expect("错口令 %d → 530" % i, (ok is False) and code.startswith("530"), code)
|
||||
if conn:
|
||||
conn.quit()
|
||||
|
||||
|
||||
@@ -80,11 +80,11 @@ SCAN_COTS = (COT_BG, COT_INIT)
|
||||
YX_NAMES = {15: "YX15 fault-total", 16: "YX16 OC-I", 17: "YX17 OC-II",
|
||||
18: "YX18 OC-III", 23: "YX23 overload", 31: "YX31 prot-block"}
|
||||
|
||||
T0 = time.time()
|
||||
t_start = time.time()
|
||||
|
||||
|
||||
def log(msg):
|
||||
print("[%9.3fs] %s" % (time.time() - T0, msg), flush=True)
|
||||
print("[%9.3fs] %s" % (time.time() - t_start, msg), flush=True)
|
||||
|
||||
|
||||
def hexs(b):
|
||||
|
||||
Reference in New Issue
Block a user