Client WINDOW_UPDATE 泄漏修复
Client WINDOW_UPDATE 泄漏修复
Title
fix(server): stop client window update leak
Target branch
main
Summary
Server 不再把 Client 返回的 WINDOW_UPDATE 镜像给 Agent。该额度只补充 Server→Client 发送窗口;Agent→Server 额度继续由 Server 消费 Agent relay 字节后独立回补。
User impact
本地 TCP 转发加载大体积 JavaScript、下载和其它固定长度响应时,不再因为重复 credit 导致 Agent 冲破 Server 接收缓冲并触发 RESET。该修复与 Client “应用消费后再归还窗口”修复共同解决 ERR_CONTENT_LENGTH_MISMATCH。
API、Schema 与配置影响
无。不修改 API、数据库 Schema、协议 frame、窗口大小、阈值或配置。
安全与授权影响
无。授权、目标策略、审计和传输加密逻辑不变。
测试证据
- 红灯:
go test ./internal/server -run '^TestServeClientSessionRelayHonorsClientWindow$' -count=1失败,输出Client WINDOW_UPDATE leaked to Agent relay。 - 绿灯:同一命令通过。
- 红灯:本地 TCP 转发 1382571 字节固定长度响应的 E2E 用例失败,出现短包和
protocol: stream is reset。 - 绿灯:
go test ./internal/e2e -run '^TestSOCKS5WebPageLatency$/^local_tcp_forward_delivers_large_fixed-length_response$' -count=10通过。 go test ./... -count=1通过。go test -race ./...通过。go vet ./...通过。git diff --check通过。
发布步骤
- 合并后构建并部署新版
tunnelmesh-server。 - 保留或部署包含“应用消费后再归还窗口”修复的
tunnelmesh-client。 - 重启本地转发会话;Agent 无需重启。
回滚步骤
回退本 Server 合并提交并重新部署旧 Server。无需回滚数据库或配置;回滚后本地 Client 大响应会重新偶发截断。
Reviewer 关注点
- Client
WINDOW_UPDATE是否只更新clientRelayStream.sendState。 - Agent→Server 额度是否仍由
agentRelayStream.Read消费后回补。 - E2E 是否校验响应头
Content-Length与响应体逐字节一致。
集成状态
实现与聚焦验证完成;本记录与相关 Client 流控修复同属一个事故修复 MR。