Repository navigation
相对 v0.5.2,这一版主要动三件事:大文件派发的调度模型、内容域的兜底路径,以及一批「失败了却不说」的地方。
一、大文件派发:段是可缩的边界,不是一条命的连接
- 让位取代掐流:空闲下来的连接把「预计最晚下完」那段的后半切走,父段只把
end缩到切点,父流读到新边界自然收工。旧版是「比你慢就掐断重来」,掐一次留一个洞,补发上限用完整个响应体就结束——九段被砍成一段就是这么来的。 - 两道闸防震荡:全局 2.5 秒最多让位一次,刀口不超过帮手速度×3(钳 512KB–64MB)。切得太频是消息风暴,刀口太大下一轮又被判慢再切一刀。
- 补发按「没有进展」计数:删掉全局 2 次上限,有进展就清零,连续多次一个字节都没下到才认输;停滞只把没收到的那截转补发,缓冲里的字节不丢。
- 收尾冻结速率:连接断了
begin还在走,均速会一路衰减成「假慢」,然后被更快的段抢走尾巴——越抢越慢。现在段一收尾速率立即定格。 - 测速改 500ms 时间槽:三个原子量加一次除法,删掉 EWMA 的时间戳/帧距机器;没有样本的候选不再靠猜。
二、内容域全灭时,借 assets 已建好的通道
头像、raw、camo 只有 .133 段的默认证书覆盖,这批 IP 一死整族直连就失败。但 Fastly 的路由依据是 :authority 而不是 SNI——同一条 githubassets 连接,换个 :authority 就能取内容域(实测 avatars/raw 都是 200 整包)。
- 只借池里现成的连接,绝不为此新建:新建要么真名暴露、要么伪装证书过不了内容域校验,两条都是死路。
- 按通道负载挑:这条上还挂着几条借出的流优先,同负载再取快的;借出计数挂在响应体上,体走完或丢弃自动归还。
- 一条坏了只冷藏这一条(30 秒),同一次请求里换另一条重试,不让请求陪死通道一起落到镜像链。
- 服务端若回 421(不收跨
:authority),停整条借道路径 30 秒,不冤枉连接。
三、顺带挖出的老 bug:双通道其实只有一条
冷启动竞速里每个拨号任务成功时已经入过一次库,收尾任务收到「晚成者」又存了一遍。MAX_CONNS_PER_HOST=2,第三次 push 把先成的那条挤掉了——github.com、api.github.com、raw、avatars、githubassets 这五个「双通道」域名,池里其实一直是同一个连接的两个副本。
修好后实测:6 个并发 raw 文件按 3/3 落在两条通道上。
四、证书 / 系统代理 / 开机自启 / 托盘:从「静默失败」到「看得见」
- 装根证书不再调
certutil(它把错误打在 stdout,程序只读 stderr,所以报错只有一个空冒号),改为直接调证书存储 API,失败带 Win32 错误码。 - 系统代理:
Internet Settings键只按读权限打开(普通进程对该键取KEY_SET_VALUE会拒绝访问,PAC 一直卡在这一步),写系统代理统一走InternetSetOption。 - 托盘自己建窗、自己泵消息,
Shell_NotifyIcon的返回值和Shell_NotifyIconGetRect的真实坐标都写进日志。根因是 exe 带完整性标签时进程会被压到该级别,Medium 进程被 High 的 explorer 用 UIPI 拒掉(err=5)——所以重新编译覆盖 exe 后要清一次完整性标签,否则托盘会消失。 - 三者各打一行启动日志,不再靠猜。
五、其余
- 本地 MITM 从 rustls 迁到 boring,跟直连腿同一套指纹,rustls 降为测试依赖;二进制 8.5MB → 8.35MB。
- codeload 并入小文件域:直连优先,失败按校准链序逐家,撤掉整包竞速。
- 日志降噪:启动成功不出声,每 host 只留首条,复用按分钟聚合成一行;事故、决策和失败原因全保留。
- 测试集中到
src/tests/,生产文件不再夹测试代码。
升级方式:用新 exe 覆盖旧版即可,plans.json / settings.json / 根证书全部保留,无需重新配置。覆盖后如果托盘图标不出现,先确认 exe 上没有完整性标签(icacls 输出里不该有 Mandatory Label)。