Skip to content

E4 iOS 长轮询中继 + 跨传输互通(决策 D-2 落地,客户端三方齐活) - #13

Merged
webergithub merged 1 commit into
masterfrom
claude/quirky-gates-p9q3du
Aug 11, 2026
Merged

webergithub merged 1 commit into
masterfrom
claude/quirky-gates-p9q3du

Conversation

@webergithub

Copy link
Copy Markdown
Owner

按推荐落地决策 D-2 = iOS 走长轮询 HTTPS,E4 客户端三方(服务端 / Android / iOS)至此齐活。

为什么是长轮询

iOS 12 无 URLSessionWebSocketTask(iOS 13+ 才有)。走 WS 要么手写 ~300 行 RFC 6455、要么引第三方依赖破坏"零依赖"约束;而位置本就 3 秒一报,不需要真长连接。URLSession 长轮询 iOS 12 原生可用、实现量减半。

关键设计:两种传输在服务端同房

房间成员抽象为投递器 {deliver(kind, body)}——WebSocket 连接(Android)与长轮询会话(iOS)落进同一个房间集合,因此 iOS ↔ Android 跨传输天然互通,服务端不必为新传输改逻辑。

  • 服务端:新增 /relay/join|send|poll|leave(与 ws 同端口,ws 改挂 http.Server);join 校验 token、send 必须持 sid、队列上限、空闲会话回收;POLL_HOLD_MS 可配以便确定性测试
  • iOS:NetTransport.swift(纯 URLSession,零依赖)、MeshCrypto.roomId(CC_SHA256)、Identity.relayUrl/relayTokenMeshBus 双通道与 Android 镜像——发只送 roomId+kind+密文(队伍码不出设备),收共用 dispatchSealed() 解密、MAC 不过即丢

验证(夹具 66 项,6 秒)

决定性的新断言用真服务端 + 真 HTTP/WS 客户端双向驱动:

  • iOS(长轮询) → Android(WS) 送达且解密一致
  • Android(WS) → iOS(长轮询) 唤醒挂起的 poll 且解密一致
  • 异队伍会话收不到(挂起超时返回空)、错 token 403、无 sid 不能注入、长轮询上行不含队伍码明文
  • ios12-build #21 / mesh-fixture #19 全绿

未完

G-NET-1 标为"代码完成"而非关闭——按 ③ 纪律需 D-1 部署 + 真机跨距实测方可关。BR-1.5 云端数 UI 未接。

🤖 Generated with Claude Code

https://claude.ai/code/session_01YSg1v3QaS7AYLHz4pfS3zh


Generated by Claude Code

… D-2 decided)

Implements decision D-2 as recommended: iOS 12 uses HTTP long-polling
rather than WebSocket. iOS 12 has no URLSessionWebSocketTask (13+ only),
so WS would mean ~300 hand-rolled RFC 6455 lines or a third-party dep
that breaks the zero-dependency constraint — while positions are only
reported every 3s and never needed a true long connection anyway.

Server: refactored relay rooms to a 'member = deliverer' abstraction so
WebSocket members (Android) and long-poll sessions (iOS) land in the
SAME room set — the two transports interoperate. Added HTTP endpoints
/relay/join|send|poll|leave on the same port (ws now rides an
http.Server), with token check on join, sid required to send, queue cap,
and idle-session GC. POLL_HOLD_MS is env-configurable so the
hold-timeout path can be tested deterministically.

iOS: NetTransport.swift on plain URLSession (zero deps), MeshCrypto
.roomId via CC_SHA256, Identity.relayUrl/relayToken, and MeshBus dual
channel mirroring Android — send() relays roomId+kind+ciphertext only
(team code never leaves the device), receive shares dispatchSealed()
which decrypts with the local team and drops on MAC failure.

Fixture at 66 assertions, runs in 6s. The decisive new ones drive both
transports against one real server: iOS(long-poll) → Android(WS) and
Android(WS) → iOS(long-poll) both deliver and decrypt correctly, a
suspended poll is woken by a WS send, other-team sessions get nothing,
bad token / missing sid are rejected, and the team code never appears
on the long-poll wire.
@webergithub
webergithub merged commit c7f4789 into master Aug 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants