feat(ncm): 风控加固——接口响应短 TTL 缓存 + 游客 MUSIC_A + track/all 死代码

三(按 NCMAPI_NOTES §2.1/§4/§6):
① 接口级响应缓存(对齐参考 apicache 2 分钟,防风控高频 ip 错误):
   - 新增 core/ncm_apicache.{c,h}——内存 4 槽 LRU(单槽≤128KB,TTL 120s,
     键=md5(path+\x01+json))+ 可选盘缓存 <data_dir>/ncm_api_cache/.json
     (8B 墙钟头+body,超 TTL miss 并删,30s 节流清过期)。自包含模块
     (仅 libc+pthread+clock_gettime),可独立链接无符号冲突。
   - ncm_api.c:api_post 拆「请求+解析」两段,新增 api_post_cached;四个只读
     接口接线:user_playlist/playlist_detail/song_detail/cloudsearch。
     song_url/lyric/vip 不入缓存。
   - 手动刷新绕过:ncm_api_cache_refresh_path(path) 一次性标记;home/歌单
     topbar ↻ 接入;playlist_open/search 不标记(走缓存)。
   - 盘层挂载 appstate_init;登出 appstate_logout 全清(防串账号)。
② 游客 MUSIC_A:ncm_req.c weapi+eapi 无 MUSIC_U 且非 login 路径补
   MUSIC_A=anonymous_token(对齐参考 cookie 伪装)。
③ track/all 死代码清理:移除 ncm_api_playlist_track_all(真实服务器 8 形态全
   404,无调用点);ncm_api_parse_track_all 保留(离线重放/单测),注释标注
   「已验证不存在,勿用于真实请求」。

验证:新 bench/apicache_sim.c(0 网络)①TTL 内不重复请求/②过期重拉/③手动
刷新绕过/④cloudsearch 按键区分/⑤清空重拉/⑥盘缓存写入+clear 全 PASS;stream/
player_flow/window/search/cache_evict(1-9)/pagination/playlist_race sim 全
PASS;test_ncm_core host+mipsel(qemu) PASS;build_ncm.sh -Wall -Wextra 0
warning(text 1026914/data 1664/bss 1363460);0 高频真实请求。新 ncm md5
a69c93538920eba9d42a2ebb42f8fdca(留主会话上卡)。
This commit is contained in:
AskaEth committed 2026-09-02 12:48:34 +08:00
1 parent 9d5301f931
commit ea645ce2a6
17 files changed
+717 -74

No files matched your search

+7
View File
@@ -87,6 +87,10 @@ int appstate_init(void)
else
ncm_ctx_default_cache_dir(g_st.data_dir, g_st.cache_dir, sizeof g_st.cache_dir);
/* 风控加固 §1:接口级 JSON 响应短 TTL 缓存的盘层挂到 <data_dir>/ncm_api_cache/。
* (内存层由 core 初始化默认启用;盘层跨进程/热更保留,启动清一次过期盘文件。) */
ncm_apicache_init(g_st.data_dir);
appstate_load_settings();
g_st.logged_in = (g_st.ctx.cookie[0] != 0);
g_st.active_playlist = -1;
@@ -156,6 +160,9 @@ void appstate_set_logged_in(const char *uid, const char *nickname)
void appstate_logout(void)
{
ncm_ctx_clear_cookie(&g_st.ctx);
/* 风控加固 §1:登出/换账号清接口级响应缓存(防上一账号缓存的 user/playlist/cloudsearch
* 被下一账号复用;盘缓存目录一并清)。 */
ncm_apicache_clear();
g_st.logged_in = 0;
g_st.uid[0] = 0;
g_st.nickname[0] = 0;
+6 -1
View File
@@ -257,7 +257,12 @@ int home_on_tap(int x, int y)
if (g_tb) {
int ah = meow_topappbar_hit(g_tb, x, y);
if (ah == MEOW_TOPBAR_BACK) { home_drag_reset(); return 1; }
if (ah == 0) { home_drag_reset(); home_reload(); return 1; } /* 刷新 */
if (ah == 0) { /* 刷新 */
home_drag_reset();
ncm_api_cache_refresh_path("/api/user/playlist"); /* 手动刷新绕过接口缓存 */
home_reload();
return 1;
}
if (ah == 1) { home_drag_reset(); settings_open(); return 1; } /* 设置 */
if (ah >= 2) { home_drag_reset(); search_open(); return 1; } /* 搜索(最右) */
}
+6 -1
View File
@@ -427,7 +427,12 @@ int playlist_on_tap(int x, int y)
if (g_tb) {
int ah = meow_topappbar_hit(g_tb, x, y);
if (ah == MEOW_TOPBAR_BACK) { pl_drag_reset(); meow_view_page_pop(); return 1; }
if (ah >= 0) { pl_drag_reset(); playlist_refresh(); return 1; }
if (ah >= 0) { /* topbar ↻ 手动刷新:绕过歌单详情接口缓存 */
pl_drag_reset();
ncm_api_cache_refresh_path("/api/v6/playlist/detail");
playlist_refresh();
return 1;
}
}
if (x >= r_plall.x && x < r_plall.x + r_plall.w &&
y >= r_plall.y && y < r_plall.y + r_plall.h) { pl_drag_reset(); player_play_song(0); return 1; }