Files
OpenStats/Packages/OpenStatsKit/Sources/HelperShared/HelperProtocol.swift
T
gentpan 8875b6e709 每项独立菜单栏与详情弹窗、网络详情与 DNS、侧边栏主窗口与统一外观
- 菜单栏可每项独立(点击弹出该项窄详情)或合并为一个(点击打开主窗口),详情区块可在设置中勾选
- 网络详情:镜像流量历史、ICMP 连接探测格子、接口与 Wi-Fi、本地与公网 IPv4 / IPv6、SVG 国旗归属地与 ASN、各进程流量
- DNS:刷新缓存,一键切换自动 / Cloudflare / Google / 腾讯 / 阿里云或手动填写;辅助工具协议升至 3,服务名与地址二次校验
- 主窗口:侧边栏切换仪表盘、各指标详情与工具页,宽高可调,卡片按比例伸缩
- 统一外观:白底蓝 / 黑底蓝,窗口、设置与弹窗共用底色,去掉玻璃效果
- 新增网络解析、DNS 校验与国旗代码校验的单元测试;更新 README、架构文档与隐私说明
2026-09-13 05:39:10 +05:00

63 lines
3.3 KiB
Swift
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.
import Foundation
import Security
public enum HelperConstants {
public static let machServiceName = "com.openstats.helper"
public static let launchdPlistName = "com.openstats.helper.plist"
public static let appBundleIdentifier = "com.openstats.app"
/// 与 App 版本同步;App 发现辅助工具版本不一致时提示重新安装
public static let protocolVersion = 3
/// 辅助工具对调用方的签名要求:与辅助工具自身同一团队签名的 OpenStats。
/// ad-hoc 签名的开发构建没有团队,只能校验 bundle identifier。
public static func clientRequirement(teamIdentifier: String?) -> String {
let identifier = "identifier \"\(appBundleIdentifier)\""
guard let teamIdentifier, !teamIdentifier.isEmpty else { return identifier }
return identifier + " and anchor apple generic and certificate leaf[subject.OU] = \"\(teamIdentifier)\""
}
}
public enum CodeSigningInfo {
/// 当前进程签名所属的 Team ID;ad-hoc 签名时为 nil
public static func currentTeamIdentifier() -> String? {
var code: SecCode?
guard SecCodeCopySelf([], &code) == errSecSuccess, let code else { return nil }
var staticCode: SecStaticCode?
guard SecCodeCopyStaticCode(code, [], &staticCode) == errSecSuccess, let staticCode else { return nil }
var information: CFDictionary?
guard SecCodeCopySigningInformation(staticCode, SecCSFlags(rawValue: kSecCSSigningInformation), &information) == errSecSuccess,
let dictionary = information as? [String: Any] else { return nil }
return dictionary[kSecCodeInfoTeamIdentifier as String] as? String
}
}
/// 辅助工具以 root 运行,只暴露固定的少量操作,不提供任意命令执行能力。
/// 所有回调中的 `String?` 为错误描述,nil 表示成功。
@objc public protocol OpenStatsHelperProtocol {
func protocolVersion(reply: @escaping @Sendable (Int) -> Void)
func setFanTarget(fan: Int, rpm: Double, reply: @escaping @Sendable (String?) -> Void)
func setFanAutomatic(fan: Int, reply: @escaping @Sendable (String?) -> Void)
func resetAllFans(reply: @escaping @Sendable (String?) -> Void)
func setSleepDisabled(_ disabled: Bool, reply: @escaping @Sendable (String?) -> Void)
func flushDNSCache(reply: @escaping @Sendable (String?) -> Void)
func purgeMemory(reply: @escaping @Sendable (String?) -> Void)
/// 为指定网络服务设置 DNS;`servers` 为空表示恢复自动获取。辅助工具会校验服务名与每个地址
func setDNSServers(service: String, servers: [String], reply: @escaping @Sendable (String?) -> Void)
}
/// 需要管理员权限的系统维护命令。辅助工具与未安装辅助工具时的授权回退共用同一份固定命令
public enum MaintenanceCommand: String, Sendable, CaseIterable {
case flushDNS, purgeMemory
public var steps: [(path: String, arguments: [String])] {
switch self {
case .flushDNS: [("/usr/bin/dscacheutil", ["-flushcache"]), ("/usr/bin/killall", ["-HUP", "mDNSResponder"])]
case .purgeMemory: [("/usr/sbin/purge", [])]
}
}
public var shellCommand: String {
steps.map { ([$0.path] + $0.arguments).joined(separator: " ") }.joined(separator: "; ")
}
}