feat(ncm): MUSIC_U 临期主动续期 — 启动查龄超阈值后台静默刷新/eapi 会话锚点/cookie 合并+冷却
用户定案:失效前用当前 cookie 换新登录态(用户无感);仅刷新失败才退扫码重登。 - core/ncm_req.c|h:eapi Cookie 头补齐会话锚点 MUSIC_U/MUSIC_A(对齐 request.rs, 补 §36.5 遗留——登录刷新/song_url 会员档依赖);新增 ncm_req_cookie_merge (patch 覆盖 base 同名 cookie,MUSIC_A/__remember_me 等不丢)。 - core/ncm_login.c|h:ncm_login_refresh(eapi /api/login/token/refresh 空体, code200+set-cookie→merge;code!=200→NCM_ERR_AUTH 退扫码;网络/TLS→负码退避)。 - app/logic/account.c:account.json 增 last_refresh_ts + 拆分 cvip/svip; account_cookie_maybe_refresh(年龄阈值 12h 可配 ncm.cookie_refresh_h,单飞/boot, 失败冷却 30min 跨 boot 持久化,AUTH 置回登录页标志)+ mark_fresh/need_relogin。 - app/ui/home.c:home_worker 先续期再拉歌单;app/ui/login.c:803 落盘后 mark_fresh; app/app.c:UI tick 消费回登录标志 → logout+切登录页。 - 新增测试:test_ncm_core 的 cookie_merge + eapi_musicu_hdr;bench/cookie_refresh_sim (端点语义,0 网络);bench/account_cookie_sim(临期/未临期/退避/失效/冷却,0 网络)。 验证:host+qemu 核心测试 PASS;build_ncm_sims.sh 全家桶 PASS;build_ncm.sh 0 warning。 真机只读探针 2 次(设备 10.78.193.50,不写回):refresh 走 eapi 域 interface.music.163.com 在当前网络被 TLS reset(alert 80)→ rc=-5 瞬断退避, session.enc/deviceId md5 前后一致(登录态零损伤)。新 ncm md5 c960244b。
This commit is contained in:
1 parent
de18cef02c
commit
cd7329d141
17 files changed
+673
-13
No files matched your search
@@ -3246,5 +3246,50 @@ d102c64f7fab73e981a789c5960e6bd9 ncm_host # 宿主调试二进
|
||||
|
||||
- **缓存 TTL=120s 的内存槽上限 4×128KB**:大歌单 `playlist_detail`(trackIds >128KB)不入内存、仅盘缓存(内存瘦身口径 REPORT §32);命中读盘+重解析,避免把上千首 trackIds 常驻内存。
|
||||
- **手刷只标详情接口**:歌单手动刷新只绕过 `v6/playlist/detail`(列表结构),`song_detail` 批 2 分钟内走缓存(改动歌曲为新键自然 miss,元数据 ≤2min 旧可接受);home 刷新绕过 `user/playlist`。
|
||||
- **eapi 分支未注入 MUSIC_U**(登录态 eapi 播放接口仍走原有的非-cookie 鉴权路径)——本次仅按任务补游客 MUSIC_A;MUSIC_U 头注入留后续(超范围)。
|
||||
- **eapi 分支未注入 MUSIC_U**(登录态 eapi 播放接口仍走原有的非-cookie 鉴权路径)——本次仅按任务补游客 MUSIC_A;**已由 §37 补齐**(eapi Cookie 头现注入 MUSIC_U/MUSIC_A,且 `ncm_login_refresh` 依赖此会话锚点)。
|
||||
- **盘缓存读路径未在真机/宿主整链实测**(内存命中优先,盘仅在内存 miss/大体时兜底)——代码审查 + 文件存在性断言验证;真机可观察 `ncm_api_cache/` 落盘与热更后命中。
|
||||
|
||||
## 37. MUSIC_U 临期主动续期(用户定案:失效前用当前 cookie 换新登录态,用户无感;仅刷新失败才退扫码)(2026-09-02)
|
||||
|
||||
覆盖 WORK_STATE 会话定案「MUSIC_U 有时效——失效前主动续期」。语义(用户定案):
|
||||
- **时机**:App 启动查 cookie 年龄(`account.json last_refresh_ts`,默认阈值 12h 可配 `ncm.cookie_refresh_h` 小时);临期且已登录 → home_worker 后台静默刷一次(worker 线程,不卡 UI、不打断播)。
|
||||
- **刷新**:带当前 cookie 调 `/api/login/token/refresh`(eapi,NCM_API_NOTES §2.2 L117 = CNMPlayer `login_refresh.rs` / Node `login_refresh.js`)→ 响应 set-cookie 提取新 MUSIC_U/__csrf,`ncm_req_cookie_merge` patch 进现存 cookie(MUSIC_A/__remember_me 等不丢)→ `ncm_ctx_set_cookie` 加密落盘(同登录机制)→ 更新 `last_refresh_ts`。
|
||||
- **失败**:网络/TLS/HTTP 瞬断 → 记 `ncm.cookie_refresh_fail_ts` 冷却 30 分钟(跨 boot 持久化),保持旧 cookie(用户仍用旧会话,下次启动再试);响应 `code!=200`(301/-460/会话失效)→ `NCM_ERR_AUTH` → UI 线程 `appstate_logout()`+切登录页(复用 settings 登出→扫码路径)。
|
||||
- **风控**:同一 boot 单飞只刷一次(`s_cookie_refreshed`);失败冷却 30 分钟。
|
||||
|
||||
### 37.1 实现(全部在 `patch_v2/ncm_app/`)
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `core/ncm_req.c` / `.h` | ① eapi Cookie 头补齐**会话锚点**:注入 `MUSIC_U`(登录态识别——login_refresh/song_url 会员档依赖)与 `MUSIC_A`(游客);游客无 MUSIC_U/A 时补 `MUSIC_A=anonymous_token`(逻辑保留)。**补齐 §36.5 遗留**。② 新增 `ncm_req_cookie_merge(base,patch,out)`:patch 的同名 cookie 覆盖 base(无则追加),其余保留——登录续期合并新 MUSIC_U 用。 |
|
||||
| `core/ncm_login.c` / `.h` | 新增 `ncm_login_refresh(device,cookie,out,sz)`:eapi `/api/login/token/refresh` 空体;`code==200`→`ncm_req_cookie_merge` 合并响应 set-cookie 到 `out` 返 NCM_OK;`code!=200`→`NCM_ERR_AUTH`;HTTP 非 2xx/网络/TLS/超时→负错误码(调用方退避);JSON 解析失败→`NCM_ERR_JSON`。 |
|
||||
| `app/logic/account.c` | ① `account.json` 增 `last_refresh_ts`(cookie 年龄)+ 拆分持久化 `cvip_expire_ms`/`svip_expire_ms`(vip 字段,防 cookie 刷新落盘覆盖)。② 新增 `account_cookie_maybe_refresh()`(决策:登录+cookie 非空+年龄超阈值+单飞+不在冷却 → `ncm_login_refresh`→成功应用+更新 ts+清冷却;AUTH→置回登录页标志;瞬断→冷却+保持旧 cookie)。③ `account_cookie_need_relogin/consume/mark_fresh`。 |
|
||||
| `app/ui/login.c` | 803 落盘新 cookie 后调 `account_cookie_mark_fresh()`(年龄=now,重置单飞/冷却)。 |
|
||||
| `app/ui/home.c` | `home_worker` 先调 `account_cookie_maybe_refresh()` 再拉歌单(后续 eapi/weapi 用新 cookie);AUTH→跳过歌单加载。 |
|
||||
| `app/app.c` | `app_on_tick` 消费 `account_cookie_need_relogin()`:`appstate_logout()`+`meow_view_page_replace(ACT_LOGIN)`(UI 线程——视图栈非线程安全)。 |
|
||||
| `app/ncm_app_internal.h` | `ncm_app_state_t` 增 `cookie_last_refresh_ts`、`vip_cvip_exp_ms`、`vip_svip_exp_ms`;account_* 新声明。 |
|
||||
|
||||
### 37.2 验证(宿主 + qemu + 真机只读)
|
||||
|
||||
| 项 | 结果 |
|
||||
|---|---|
|
||||
| 新增 `test_ncm_core` `test_cookie_merge`(合并/空 patch)+ `test_eapi_musicu_hdr`(eapi Cookie 头带 MUSIC_U、游客 anonymous) | host + mipsel **PASS** |
|
||||
| 新增 `bench/cookie_refresh_sim.c`(真实 core + ncm_http 计数桩,0 网络) | **ALL PASS**:code200+set-cookie→新 MUSIC_U/__csrf 替换+旧字段保留 / code301→NCM_ERR_AUTH / 网络瞬断→NCM_ERR_NET / code200 无 set-cookie→原样 / 无 cookie 优雅 |
|
||||
| 新增 `bench/account_cookie_sim.c`(真实 account.c + 外围桩,0 网络) | **ALL PASS**:临期触发 / 未临期不刷 / 旧会话(last=0)视为临期 / 瞬断退避(负码+冷却持久化) / 失效→AUTH+回登录标志 / 冷却(31min>30min 重刷, 10min<30min 不刷) / mark_fresh 后不刷 |
|
||||
| `stream_sim` / `player_flow_sim` / `window_sim` / `search_sim` / `cache_evict_sim` / `apicache_sim` / `pagination_sim` / `playlist_race_sim` | 全 PASS(`build_ncm_sims.sh` suite exit=0) |
|
||||
| `test_ncm_core_host` + `qemu test_ncm_core_mipsel` | host + mipsel **PASS** |
|
||||
| `build_ncm.sh`(-Wall -Wextra) | **0 warning**;`text 1031970 / data 1664 / bss 1364516` |
|
||||
| `build_ncm_host.sh` | 通过(仅 SDK `meow_ui_vol.c` 存量 `system()` 告警,非本批) |
|
||||
| **真机只读探针**(设备 10.78.193.50,真实 cookie,不写回) | 连续 2 次 `refresh_rc=-5`(NCM_ERR_TLS);`session.enc`/`deviceId` md5 前后一致(`a86c9448…`/`5af2657a…`),**登录态零损伤**。 |
|
||||
|
||||
### 37.3 md5(本批产物)
|
||||
|
||||
`ncm` = `c960244b44dd8c7b08bb29a44a65fad7`(`md5sum ncm`,首 8 位 `c960244b`);`text 1031970 / bss 1364516 / dec 2398150`。未部署(留主会话上卡)。
|
||||
|
||||
### 37.4 诚实出入 / 遗留
|
||||
|
||||
- **真机 refresh 端点未能拿到 `code 200 + 新 MUSIC_U` 的正向结论**:`/api/login/token/refresh` 走 eapi `https://interface.music.163.com/eapi/…`,而设备当前网络/环境对 `interface.music.163.com:443` TLS 握手被对端 reset(busybox `alert code 80`;`music.163.com` weapi 域 `200 OK` 正常)→ 连续 2 次探针均 `-5`。即**该设备网络屏蔽了 eapi 域名**,refresh(以及 song_detail/lyric/song_url/扫码等全部 eapi)在当下不可达。**这不是本批代码问题**——正因如此,本批把 `-5(TLS)` 归为「瞬断→退避+保持旧 cookie+不清登录态」,正是为了在该网络下不把用户登出;换到 `interface.music.163.com` 可达的网络(如家用 WiFi),refresh 应能返回 200 并轮换 cookie。**建议主会话在 eapi 可达网络下再做 1 次只读探针确认正向**。
|
||||
- **冷却跨 boot 持久化用 `meow_config`(`ncm.cookie_refresh_fail_ts`)**,不随 `account.json` 清空——登出/换账号不影响冷却(无副作用;仅防重刷)。
|
||||
- **`account.json` 旧账号首次升级**:旧文件无 `last_refresh_ts` 字段 → `cookie_last_refresh_ts=0` → 视为临期,开机续期一次;成功即落盘,避免反复判临期。
|
||||
- **eapi 会员播放(song_url 等)因 MUSIC_U 头注入而改变行为**:此前 eapi 请求不带 MUSIC_U(§36.5 遗留),登录态 eapi 播放按游客鉴权;本批起带真实 MUSIC_U,会员档/登录态更准确——需在 eapi 可达网络下观察歌单/播放回归(`music.163.com` 域不受影响)。
|
||||
- **未部署**:`ncm` 产物未上卡;真机仅做了只读探针(不动 App 二进制),`app.json`/`ncm` 未替换。
|
||||
Reference in new issue
Block a user