mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-11 19:25:06 +00:00
Domain/ 根目录原有 62 个平铺源文件,无法从目录读出主题划分。 按「目录即主题」重组为 11 个目录(Rules/Custom 为嵌套子目录):Catalog / Subscription / Rules / Runtime / Activation / Settings / SystemProxy / Plugin / Credentials / LegacyImport / Diagnostics。纯移动:类型名、模块名 与 import 均未改动,Domain/ 根下不再有散落文件。目录口径取自 GLOSSARY.md 的章节划分(配置与订阅、代理规则、代理控制与网络、设置、 凭据与诊断),而非新造分类。 配套改动: - project.yml:wrapper 与 helper 两个 target 按文件引用的 15 条显式路径 随目录改名,并补注释固定这一约定——这 15 条指向不存在的文件时, xcodegen generate 以 "missing source directory" 直接失败(实测,不静默)。 - SkeletonTests 新增 DomainLayoutTests:断言 Domain/ 根下无平铺 .swift、 树下只有 .swift。后者防的是与 App/ 同源的坑——Domain/ 整目录是 app 与 Core 的 source path,任何非源码文件都会被 XcodeGen 收进 Resources 阶段 并封进签名后的 bundle。 - README 工程结构说明同步;docs/design 与 docs/research 属历史文档不改。 验证:xcodegen generate 后 app 164 / Core 163 源文件数与整理前一致;Agent 恰好 9 个、Helper 恰好 6 个 Domain 文件(无缺失无多出);app 与 Core 各覆盖 全部 62 个。clean build 0 error;task test 1024 用例全通过(整理前 1022, +2 为新增守卫);task format 未改写任何被移动文件(证明纯移动);task lint 与整理前同为 21 条内容型 warning;packaging-gate.sh ALL CHECKS PASSED。 布局守卫已做变异验证:临时投放松散 .swift 与非 .swift 文件时两个用例均 失败并点名违规文件,清理后复验为绿。
76 lines
3.2 KiB
Swift
76 lines
3.2 KiB
Swift
import Foundation
|
||
|
||
/// GUI 与特权系统代理 helper 的共享 XPC 契约(issue #71)。类型同时编入 GUI、
|
||
/// helper 与测试 target;payload 以 JSON 编码保持 closed typed 语义。
|
||
@objc protocol SystemProxyHelperControlling {
|
||
/// 应用 closed typed 配置到活动网络位置的每个服务。
|
||
func apply(_ payload: Data, withReply reply: @escaping (Data) -> Void)
|
||
/// 无条件清除全部网络位置全部服务的完整 Proxies 字典。
|
||
func clear(withReply reply: @escaping (Data) -> Void)
|
||
}
|
||
|
||
/// helper 的固定身份:MachService 名、LaunchDaemon plist 名与客户端校验基准。
|
||
/// 客户端只按 2.0 的 bundle identifier(代码签名 identifier)接受,不限
|
||
/// Team ID 或账号(issue #71)。
|
||
enum SystemProxyHelperIdentity {
|
||
static let machServiceName = "com.qiuyuzhou.ShadowsocksX-NG2.systemproxy"
|
||
static let plistName = "com.qiuyuzhou.ShadowsocksX-NG2.systemproxy.plist"
|
||
static let launchdLabel = "com.qiuyuzhou.ShadowsocksX-NG2.systemproxy"
|
||
static let clientCodeSigningIdentifier = "com.qiuyuzhou.ShadowsocksX-NG2"
|
||
|
||
/// App bundle 内 LaunchDaemon 清单内容(注册漂移指纹的基准)。helper 进程
|
||
/// 内没有 bundle,返回 nil,调用方按「无基准不动作」处理。Contents/Library
|
||
/// 不是资源目录,Bundle 资源 API 搜不到,按固定路径直读。bundle 参数生产
|
||
/// 默认 Bundle.main;去宿主化(ADR 0021)后单测经控制器的 appBundle 缝注入
|
||
/// 构建产物 bundle。
|
||
static func launchDaemonPlistData(in bundle: Bundle = .main) -> Data? {
|
||
let url = bundle.bundleURL
|
||
.appendingPathComponent("Contents/Library/LaunchDaemons")
|
||
.appendingPathComponent(plistName)
|
||
return try? Data(contentsOf: url)
|
||
}
|
||
}
|
||
|
||
/// helper XPC 应答:成功携带 typed 结果,失败携带 typed 错误族。
|
||
enum SystemProxyHelperResponse: Equatable, Sendable, Codable {
|
||
case applied(SystemProxyWriteOutcome)
|
||
case cleared
|
||
case failure(SystemProxyError)
|
||
}
|
||
|
||
enum SystemProxyHelperWireError: Error, Equatable, Sendable {
|
||
case undecodableResponse(String)
|
||
}
|
||
|
||
enum SystemProxyHelperWire {
|
||
/// SystemProxyHelperResponse 全部由简单可编码类型组成,JSON 编码不可失败;
|
||
/// 若未来加入不可编码载荷,显式失败好过发出无法解码的应答。
|
||
static func encode(_ response: SystemProxyHelperResponse) -> Data {
|
||
do {
|
||
return try JSONEncoder().encode(response)
|
||
} catch {
|
||
preconditionFailure("system proxy helper response encode failed: \(error)")
|
||
}
|
||
}
|
||
|
||
static func decode(_ payload: Data) throws -> SystemProxyHelperResponse {
|
||
do {
|
||
return try JSONDecoder().decode(SystemProxyHelperResponse.self, from: payload)
|
||
} catch {
|
||
throw SystemProxyHelperWireError.undecodableResponse(String(describing: error))
|
||
}
|
||
}
|
||
|
||
static func encodeConfiguration(_ configuration: SystemProxyConfiguration) throws -> Data {
|
||
try JSONEncoder().encode(configuration)
|
||
}
|
||
|
||
static func decodeConfiguration(_ payload: Data) throws -> SystemProxyConfiguration {
|
||
do {
|
||
return try JSONDecoder().decode(SystemProxyConfiguration.self, from: payload)
|
||
} catch {
|
||
throw SystemProxyError.invalidRequest(String(describing: error))
|
||
}
|
||
}
|
||
}
|