修复Trap23:异常释放后复监听隔离并排空RX残渣,上传中止截断消除(RST10/10+FIN5/5通过,正常50/50)

This commit is contained in:
2026-09-23 01:31:07 +08:00
parent 5a41b966fc
commit 7d70445c16
3 changed files with 100 additions and 1 deletions
+80
View File
@@ -1240,6 +1240,46 @@ static int net_recv_locked(net_sock_t *p_sock, void *buf, int len, int flags,
* 函数说明:1. 调用 ch395f_close_socket 关闭 CH395F 硬件 Socket
* 2. 清空整个控制块(memset 0),释放该 Socket 资源
*/
/* Trap 23(2026-09-23 生产路径实测):异常释放(芯片 TIMEOUT,例如客户端中止上传)
* 后的**隔离期**。实测时序:中止时对端仍有在途数据 → 芯片 TIMEOUT(此时 MCU 侧 recv=0)
* → 在途段随后落进芯片 RX 缓冲(约 2KB 残渣)→ 若立即 open+listen,残渣被下一条连接
* 当作自己的数据读走:新上传只收 2KB 就被判定结束、回报成功(静默截断)。
* 处置:异常释放的 socket 先隔离 NET_RELISTEN_QUARANTINE_MS:期间持续排空 RX、主动
* close 并排空中断、等芯片回到 CLOSED/TCP_CLOSED;隔离期满才 open+listen。上限
* NET_RELISTEN_SETTLE_MS 后强制放行,保证监听器不会永久失效。
* 正常 FIN 释放(handle_disconnect_event)不走此路径——既有行为零改动。
* 声明须早于 net_relisten_locked(其余重试状态见其后区块)。 */
#define NET_RELISTEN_QUARANTINE_MS 400U /* 隔离时长(等在途数据落尽 + 排空残渣) */
#define NET_RELISTEN_SETTLE_MS 800U /* 隔离上限(须 < NET_RELISTEN_DEADLINE_MS,
* 否则隔离耗尽重试预算 → 监听被放弃,2026-09-23 实测) */
static uint8_t s_relisten_quarantine[NET_MAX_SOCKETS]; /* 1 = 本次释放为异常,需隔离 */
static uint32_t s_relisten_settle_start[NET_MAX_SOCKETS]; /* 隔离起点(0 = 未开始) */
static uint32_t s_relisten_settle_dead[NET_MAX_SOCKETS]; /* 隔离上限到期时刻 */
/*
* 函数功能:清空芯片该 socket 的 RX 残留(Trap 23)
* 入口参数:sockfd - Socket 描述符 (0~7) int
* 返回值:无
* 限定条件:netTask 上下文;socket 即将 close/open(数据已无意义,丢弃)
* 函数说明:中止/异常断开时芯片 RX 缓冲可能残留上一条连接的数据(实测残留约一个
* 缓冲 = 2048B);残渣带入下一条连接会使其在约 2KB 处被芯片拆链(上传被
* 静默截断)。关闭前主动读空即清除。分块读避免新增静态缓冲。
*/
static void net_drain_chip_rx(int sockfd) {
uint8_t scratch[256];
for (int guard = 0; guard < 16; guard++) { /* 上限 16×256 = 4KB(缓冲仅 2KB),防死循环 */
int n = (int)ch395f_get_recv_len((uint8_t)sockfd);
if (n <= 0) {
break;
}
if (n > (int)sizeof(scratch)) {
n = (int)sizeof(scratch);
}
ch395f_read_recv_buf((uint8_t)sockfd, scratch, (uint16_t)n);
}
}
/*
* 函数功能:单连接模式断连后自动重新进入 LISTEN(不清空控制块,保留 fd)
* 入口参数:p_sock - 已断开(CLOSED)的 TCP 监听型 Socket 控制块 net_sock_t *
@@ -1256,6 +1296,36 @@ static int net_relisten_locked(net_sock_t *p_sock) {
uint8_t status;
int sockfd = (int)(p_sock - s_net_socks);
if (s_relisten_quarantine[sockfd] != 0U) {
uint8_t st[2] = {0, 0};
uint32_t now = HAL_GetTick();
if (s_relisten_settle_start[sockfd] == 0U) {
s_relisten_settle_start[sockfd] = now;
s_relisten_settle_dead[sockfd] = now + NET_RELISTEN_SETTLE_MS;
}
net_drain_chip_rx(sockfd); /* 隔离期内持续排空 RX 残渣 */
ch395f_close_socket((uint8_t)sockfd); /* 主动关:清旧连接收尾状态 */
(void)ch395f_get_sock_int_status((uint8_t)sockfd);
(void)ch395f_get_glob_int_status_all();
ch395f_get_socket_status((uint8_t)sockfd, st);
if (((st[0] != CH395F_SOCKET_CLOSED) || (st[1] != CH395F_TCP_CLOSED) ||
((uint32_t)(now - s_relisten_settle_start[sockfd]) < NET_RELISTEN_QUARANTINE_MS))) {
if ((int32_t)(now - s_relisten_settle_dead[sockfd]) < 0) {
DBG_INFO("sock%d relisten quarantine (sock=0x%02X tcp=0x%02X)",
sockfd, st[0], st[1]);
s_net_errno = NET_ERR_BUSY;
return -1; /* 交重试轮询(30ms 后复检) */
}
DBG_INFO("sock%d relisten quarantine timeout, force open (sock=0x%02X tcp=0x%02X)",
sockfd, st[0], st[1]);
}
s_relisten_quarantine[sockfd] = 0U; /* 隔离完成(或强制放行) */
s_relisten_settle_start[sockfd] = 0U;
s_relisten_settle_dead[sockfd] = 0U;
}
ch395f_set_proto_type((uint8_t)sockfd, CH395F_PROTO_TYPE_TCP);
ch395f_set_sour_port((uint8_t)sockfd, p_sock->local_port);
@@ -1319,6 +1389,8 @@ static void net_relisten_clear(int sockfd) {
s_relisten_wait[sockfd] = 0U;
s_relisten_next[sockfd] = 0U;
s_relisten_dead[sockfd] = 0U;
s_relisten_settle_dead[sockfd] = 0U; /* Trap 23:一并清沉降/隔离状态 */
s_relisten_settle_start[sockfd] = 0U;
}
/*
@@ -2570,6 +2642,14 @@ static void handle_timeout_event(net_sock_t *p_sock) {
p_sock->state = NET_SOCK_STATE_CREATED;
} else if (p_sock->state == NET_SOCK_STATE_ESTABLISHED) {
DBG_ERROR("sock%d TIMEOUT", p_sock->ch395_sock);
/* Trap 23:异常释放(TIMEOUT,例如客户端中止上传)→ 复监听前隔离,
* 等对端在途数据落尽并排空 RX 残渣(详见 net_relisten_locked 区块注释) */
{
int qfd = (int)(p_sock - s_net_socks);
if ((qfd >= 0) && (qfd < NET_MAX_SOCKETS)) {
s_relisten_quarantine[qfd] = 1U;
}
}
p_sock->state = NET_SOCK_STATE_CLOSED;
} else if (p_sock->state == NET_SOCK_STATE_LISTENING) {
/* 监听超时(异常情况) */