ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Madeira TCP状态编号错位根因与修复:一个Linux/BSD兼容bug全记录

Madeira TCP状态编号错位根因与修复:一个Linux/BSD兼容bug全记录 Madeira TCP状态编号错位根因与修复一个Linux/BSD兼容bug全记录【免费下载链接】MadeiraRun x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT项目地址: https://gitcode.com/GitHub_Trending/mad/MadeiraMadeira 是一个在越狱 iOS 上通过 FEX-Emu Wine DXMT 运行 x86-64 Windows 游戏的开源项目。本次排障记录围绕它的 Steam 客户端传输层报错展开Steam 反复弹出 Unexpected Transport Error根因是TCP 连接状态编号错位——一个典型的 Linux/BSD 与 Windows 枚举值不一致的兼容 bug。一、症状Steam 的拒绝连接死循环在 iOS 上运行 Steam 时现象非常典型SteamUI 的 CEFChromium组件发起 loopback 连接后不断收到Rejecting connection attempt from unknown source界面弹出 VGUI Unexpected Transport Error 对话框连接出现 accept/reject 循环登录流程无法推进。Steam 的安全机制是它通过GetExtendedTcpTable查询 TCP 连接表找到对端远端端口对应的行比对dwOwningPid拥有该 socket 的进程 ID是否属于自己或它跟踪的子进程。只要这张表查不到、或状态不对就一律当作未知来源拒绝。二、根因两张 TCP 状态编号表问题出在底层的一个关键差异上——BSDLinux/macOS/iOS和 Windows 对 TCP 状态的编号完全不同状态BSD / Linuxtcp_statesWindowsMIB_TCP_STATELISTEN102ESTABLISHED13这就是错位的含义iOS 上没有nsiproxy.sys没有 winedevice/驱动栈PE 版nsi.dll打开\\.\Nsi设备失败所有 NSI 表读取全部报错于是GetExtendedTcpTable直接失败Steam 的安全检查在 pid 比对之前就退出了——表不可用连接必然被拒修复思路是补上这张表但补表时又踩到第二层坑wineserver 内部记录的状态沿用BSD 编号而 NSI 接口要求的是Windows MIB 编号。直接把 BSD 值原样透传Steam 读到的dwState就是错的ESTAB 表里出现 state1 而不是 3。这是跨系统移植的经典盲区枚举值不是 API 的一部分文档里很少强调但语义全在编号里。三、修复从 wineserver 直供 TCP 连接表修复位置在 NSI 的 unixlib 实现 nsi_unixlib_ios.c按模块 ID 分流TCP 模块NPI_MS_TCP_MODULEID的请求由本文件服务其他模块网卡、地址、路由交给 nsi_network_ios.c 走 Wine 的 BSD provider直接复用 wineserver 的连接数据wineserver 本来就为每个 TCP socket 跟踪了诚实的 owner pidserver/sock.c的get_tcp_connections所以三个 TCP 连接表ALL / ESTAB / LISTEN直接从 server 应答无需伪造状态过滤与编号对齐表类型到过滤条件的映射保证了语义一致——case NSI_TCP_ALL_TABLE: filter 0; break; case NSI_TCP_ESTAB_TABLE: filter MIB_TCP_STATE_ESTAB; break; case NSI_TCP_LISTEN_TABLE: filter MIB_TCP_STATE_LISTEN; break;即 nsi_unixlib_ios.c 中用MIB 编号而非 BSD 编号参与过滤杜绝错位行数据逐字段转换每条连接输出 key本地/远端地址端口、dynamicstate取 MIB 值、staticpid取 wineserver 记录的 owner见 ios_tcp_conns_enumerate_all兼容 32 位调用WoW64 下 32 位nsi.dll传的是 4 字节指针的变体结构体ios_wow64_nsi_enumerate_all_ex 负责把内嵌指针逐个从 guest 地址转换到 host 地址留了排障日志修复过程中revml473/ml474每行连接都会 dump 实际交付给 Steam 的state和pid正是靠这份我们到底给了它什么的日志确认了状态编号已对齐。四、经验总结跨平台移植的 3 条教训枚举值是隐性 ABITCP_ESTABLISHED在 BSD 是 1、在 Windows 是 3任何一层透传都必须显式转换不能假设两边都一样先让接口可用再谈数据正确本例分两步——先补上 NSI 表解决表不可用再核对状态编号解决表数据错位两步各修一个独立 bug给排障留日志修复代码中把实际交付值打出来[nsi-row] ... state%u pid%u比任何推理都直接。五、延伸阅读修复核心文件nsi_unixlib_ios.c网络表 providernsi_network_ios.c、nsi_ip_ios.c32 位 WoW64 指针转换ios_wow64_nsi_enumerate_all_ex项目网络相关测试tests/host/check-nsi-network.py构建说明docs/BUILDING.md【免费下载链接】MadeiraRun x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT项目地址: https://gitcode.com/GitHub_Trending/mad/Madeira创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表