Files
huya-go/WSS_NOTES.md
T
2026-07-06 18:30:34 +08:00

138 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WSS 协议要点
本文件记录 2026-07-06 手动浏览器 HAR、页面 JS 和 Go 版本当前实现的复核结论。
## 抓包结论
手动浏览器链路是 HTTP + WSS 混合:
- 页面初始化、商品信息、HttpDNS 等有多条 `https://cdnws.api.huya.com/` POST。
- 浏览器同时建立了 3 条 `wss://77bc035c-ws.va.huya.com/` 连接。
- `scoreExchangePrize` 出现在 WSS 连接数据和静态 JS 中,没有出现在 `cdnws` POST 请求中。
- 当前 HTTP 版本可用,是因为 `webActUI` 的 WUP over HTTP 编码已经对齐。
- 当前 WSS 版本会超时,是因为 Go 里的 WSS 外层协议模型不符合浏览器 JS。
## 连接
- WebSocket URL:`wss://<host>/?baseinfo=<base64 taf>`
- 手动 HAR host:`77bc035c-ws.va.huya.com`
- host 来自 `launch.queryHttpDns` 或浏览器抓包,不应长期写死。
- 握手启用 `permessage-deflate`。
- 浏览器请求扩展:`permessage-deflate; client_max_window_bits`
- 服务端返回扩展:`permessage-deflate;server_no_context_takeover;client_no_context_takeover`
## 正确外层结构
浏览器 JS 不是 `1B version + 1B command + 4B sequence + body`。
页面实际构造 TAF/JCE `WebSocketCommand`:
```text
WebSocketCommand {
0: iCmdType int32
1: vData bytes
2: lRequestId int64
3: traceId string
4: iEncryptType int32
5: lTime int64
6: sMD5 string
}
```
WUP 请求发送逻辑:
```text
Wup.setServant(servant)
Wup.setFunc(func)
Wup.setRequestId(requestId)
Wup.writeStruct("tReq", req)
WebSocketCommand.iCmdType = EWSCmd_WupReq(3)
WebSocketCommand.vData = Wup.encode()
WebSocketCommand.traceId = "<trace>:<trace>:0:<enableTrace>"
ws.send(WebSocketCommand.writeTo(JceOutputStream))
```
服务端返回 `EWSCmd_WupRsp(4)`,内部 `vData` 才是 WUP 响应。
## 命令枚举
页面 JS 中可见的关键枚举:
- `3`:`EWSCmd_WupReq`
- `4`:`EWSCmd_WupRsp`
- `5`:`EWSCmdC2S_HeartBeat`
- `6`:`EWSCmdS2C_HeartBeatAck`
- `10`:`EWSCmdC2S_VerifyCookieReq`
- `11`:`EWSCmdS2C_VerifyCookieRsp`
- `20`:`EWSCmdC2S_HeartBeatReq`
- `21`:`EWSCmdS2C_HeartBeatRsp`
- `23`:`EWSCmdC2S_UpdateUserExpsReq`
- `24`:`EWSCmdS2C_UpdateUserExpsRsp`
- `33`:`EWSCmdC2S_UpdateUserInfoReq`
- `34`:`EWSCmdS2C_UpdateUserInfoRsp`
手动 HAR 解出的服务端 WSS 回包包括:
- `EWSCmdS2C_HeartBeatRsp`
- `EWSCmd_WupRsp launch.wsLaunch`
- `EWSCmd_WupRsp mobileui.getConfig`
- `EWSCmd_WupRsp webActUI.getActPrizeList`
- `EWSCmd_WupRsp webActUI.getUserScore`
- `EWSCmd_WupRsp webActUI.scoreExchangePrize`
## 初始化流程
浏览器 WSS session 的关键流程:
1. 连接 `wss://<host>/?baseinfo=<base64 taf>`。
2. 发送 `EWSCmdC2S_HeartBeatReq`。
3. 通过 WSS 调用 `launch.wsLaunch`。
4. `wsLaunch` 后触发 `sendWSUpdateUserInfoReq`。
5. `launch.queryHttpDns` 仍通过 HTTP `cdnws` 调用。
6. 后续 WUP 业务在连接可用时走 `signalSdk.sendWup`,连接不可用时可 fallback 到 `sendWupHttp`。
响应应按 WUP `iRequestId` 匹配回调,不能只用 FIFO。
## 活动接口
当前 Go HTTP 版本已实现:
- `webActUI.getActPrizeList`
- `webActUI.getUserScore`
- `webActUI.getUserPrizeRecords`
- `webActUI.scoreExchangePrize`
WSS 版本仍是实验状态,需要按 `WebSocketCommand` 结构重写。
抢购兑换请求结构:
```text
tReq.user
tReq.sid
tReq.pid
tReq.ip = ""
tReq.clientEnv = {}
tReq.source = ""
tReq.isRole = 1
```
浏览器手动抢购小黄鸭成功回包确认:
- `webActUI.scoreExchangePrize`
- `sid=2203`
- `pid=12889`
- `status=200`
- `msg=请求成功`
- `exchangeInfo.pid=12889`
- `exchangeInfo.exchangeScore=988`
- `exchangeInfo.desc=兑换奖品:套装-潮萌小黄鸭`
## 待完善
- 实现 TAF `WebSocketCommand` 编解码。
- WSS WUP response 按 `iRequestId` 匹配请求。
- 实现 `WSUpdateUserInfoReq`、心跳、verify cookie 等浏览器初始化步骤。
- 自动调用 `launch.queryHttpDns` 获取最新 WSS host。
- 增加基于真实抓包样本的 WSS 编解码单测。