Files
mtgodot-poc/audit/contracts/network.error-timeout-server-state.md
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

7.6 KiB
Raw Blame History

network.error_timeout_server_state

Scope

对比认证失败、连接失败、超时、频道状态检查、服务器状态通知和恢复/回到登录界面的完整分支。

Reference call chain

  • UserInterface/AccountConnector.cpp
  • UserInterface/ServerStateChecker.cpp
  • UserInterface/PythonNetworkStreamPhaseLogin.cpp
  • EterLib/NetStream.cpp

Current call chain

  • extension/src/net/auth_client.h
  • extension/src/net/classic/classic_session.cpp
  • project/net/channel_status.gd
  • project/net/serverinfo.gd
  • project/app_flow.gd
  • project/ui/reconnect_ui.gd

Branch matrix

场景 40250 当前端 结论
auth 失败 AccountConnector 消费错误并通知 login UI,断开 auth/game 状态 login_failed 返回 AppFlow 登录页;旧 session 清理顺序未完全证明 PARTIAL
连接超时 Process/connector failure 进入 offline/disconnect ClassicStreamNetStream 均保留 3 秒 non-blocking deadline,并在 socket 可写后再用 SO_ERROR 确认连接完成 MAPPED:仍缺少所有上层失败通知组合证明
channel status ServerStateChecker 请求首 channel,解析 count 和 {port,status},逐频道通知 当前查询首频道,解析 classic 210;失败时 fallback TCP probe PARTIAL:功能相近但多了 approximation
部分响应 NetStream 保留接收缓存等待完整状态包 当前已缓存状态 body,遇到半条记录会继续等待后续 TCP 数据 MAPPED:分片行为已补回归测试
空/非法 count 由包长度和状态处理逻辑拒绝 _try_parse_classic 检查范围;body 内仍需完善负值/超大值保护 PARTIAL
恢复 失败后按 connector/server state 回调回到正确 phase 当前由 AppFlow signal 和 ReconnectUI timer 驱动 PARTIAL

Equivalence matrix

项目 状态 证据
Preconditions PARTIAL 认证/连接和状态请求有检查;完整失败通知、远端关闭与上层重入仍需补齐
Branch structure PARTIAL auth/channel/fallback 主分支存在,失败通知和超时分支不同
Algorithms/formulas MAPPED classic count/record 解析和分片 body 累积已有实现与测试
State transition order PARTIAL 当前 signal/UI retry,参考 connector/phase offline 回调顺序不同
Constants/units MAPPED classic/m2dev socket 与 channel probe 均为 3 秒;状态 count 上限为 4096,仍需边界夹具覆盖
Timing/event sources PARTIAL timer/fallback probe 与参考 network process/state checker 不同
Resource/data sources PARTIAL serverinfo 推导端口,参考接收显式 channel entries
Protocol side effects PARTIAL 206/210 classic 包存在;fallback TCP probe 是当前扩展副作用
Interruption/failure/cleanup PARTIAL 连接中断、重复 probe、重试终止仍缺少测试

Deep audit round 2026-09-20

本轮沿 40250 AccountConnector::Connect/ProcessCServerStateChecker::Request/UpdateCPythonNetworkStream::LoginPhaseCNetworkStream::Process/Connect 逐分支核对,得到以下结论:

  1. 40250 的认证连接通过 CNetworkStream::Connect 建立非阻塞 socketProcess 用 socket 可写事件确认连接成功,并使用 m_connectLimitTime 超时清理;当前 NetStreamClassicStream 现在都保留 3 秒 deadline,且只有可写事件后才用 SO_ERROR 确认完成。连接超时/远端错误的上层通知组合仍需扩展测试。
  2. 40250 CAccountConnector::__AuthState_RecvPhase 发送 CG_LOGIN3 后立即 ClearLoginInfo() 清掉密码;当前 AuthClient 在构造登录包后清零并清空 m_pwM2Client::pump_auth() 同步丢弃 host-side cfg_pw,没有 login key 时的空密码重连会被拒绝。该边界已有 loopback 断言。
  3. 40250 的 ServerStateChecker::Request 只连接首频道并发送一次 HEADER_CG_STATE_CHECKER,连接/发送失败时将所有已登记频道通知为关闭;Update 收到 HEADER_GC_RESPOND_CHANNELSTATUS 后按端口通知并 Initialize()。当前 AppFlow::_probe_channels 使用 ChannelStatus 查询首频道,未知端口则逐频道做额外 TCP probe,属于当前端的 approximation,不是 1:1 分支;多个“检测频道”点击可以并行创建查询节点,未见 in-flight/cancel/generation 保护。
  4. 当前状态查询的 206/210 classic 解析已累积 body,负数和大于 4096 的 count 会拒绝;ChannelStatus 现在会先取消旧 probe,并在回调重入时固定旧 callback,避免旧结果投递给新请求。自动测试仍未覆盖连接后无响应超时、count=0/截断/尾随包及远端关闭。默认协议和 MT_PROTOCOL=classic 两次测试均通过。
  5. 当前 AppFlow 登录失败/断线的 signal 分类存在,但账号/游戏连接失败后由 M2Client 直接 reset session,再由 AppFlow 重建 Login;这与 40250 的统一 Offline phase / SetLoginPhase 顺序不同。p10_test 还暴露了 Loading→Game 未隐藏和无 SceneTree 时 char-select timer 空树的测试/生命周期问题,恢复链不能标记为完成。

Required tests

  • auth success/failure、connect refusal、connect timeout、remote close。
  • 206/210 完整包、分片包、半条 record、count=0、负值和超大 count。
  • channel status 失败后的 fallback、重试上限和回到登录页。
  • 同一 session 同时 login/reconnect/probe 的竞态与清理。

Evidence run

  • godot --headless --path project --script channel_status_test.gdPASS。
  • MT_PROTOCOL=classic godot --headless --path project --script channel_status_test.gdPASS,覆盖 40250 classic 的 206 请求和 210 响应夹具。
  • 认证 loopback 成功路径、密码清除、挂起连接 deadline 已在 extension/tests/net_loopback_test.cpp 覆盖;classic transport 的同等 deadline/可写门禁在 extension/tests/net_classic_stream_test.cpp 覆盖。
  • 当前合同继续 PARTIAL:通过的状态包解析测试不能替代 40250 的认证失败、远端关闭、失败通知顺序、count 边界和完整恢复链证据。

Active UserInterface server-state checker review

  • ServerStateChecker.h/ServerStateCheckerModule.cpp 维护独立 CNetworkStream、channel 地址/端口表、Create/AddChannel/Request/Update/Initialize 和 Python window 回调;它是登录前服务器状态探测链,不等同于游戏 session 的重连。
  • 当前端 channel status 有 classic packet smoke test,且单个 ChannelStatus 的旧 socket/重入 callback 已有清理逻辑;仍没有证明多 channel 请求的超时、远端关闭、失败通知顺序、窗口销毁后回调和与 login phase 的竞态清理一致;本轮纳入 active source 证据,合同仍为 PARTIAL

Implementation fix round 2026-09-20

  • AuthClient::on_phase(PHASE_AUTH) 先把密码拷贝进 CG_LOGIN3,随后显式清零并清空 m_pw,再检查 send_packet()M2Client::pump_auth() 看到同一边界后清空 cfg_pwreconnect() 在没有 login key 时拒绝空凭据重试。
  • NetStreamClassicStream 都增加 3000ms non-blocking connect deadlineclassic 路径改为 select 可写后再 SO_ERROR,修复第一次 process 把仍在连接中的 socket 误报 Online 的差异。
  • ChannelStatus 取消旧 probe、清空 mutable callback 后再发 done,支持 callback 内启动下一次查询;AppFlow 增加 channel probe in-flight guard。
  • 新增/扩展 net_loopback_testnet_classic_stream_testchannel_status_test.gd,覆盖凭据清除、挂起连接 deadline 和 re-entrant probe callback;成功路径及默认/classic 两套状态包夹具通过。

Status

PARTIAL