Files
ShadowsocksX-NG/ShadowsocksX-NG2/App/ProxyControlWorkflow/LocalInterfaceFacts.swift
T
Qiu Yuzhou b26954dd20 feat(app): home terminal command address picker for #72
非「仅本机」监听方式下,首页命令卡在复制按钮上方提供单选 IP 下拉框:
候选仅含回环与当前启用 Wi‑Fi/Ethernet 接口单播地址(严格 SCNetworkInterface
类型白名单,排除 VPN/虚拟/未知类型),按监听地址族过滤(双栈含两个回环,
127.0.0.1 置顶;仅 IPv6 默认 ::1),标签 {IP} - {name}(本地化名称缺失回退
BSD 名)。两种 shell 的 HTTP/HTTPS/SOCKS 端点共用选中地址,端口取已保存
监听事实,IPv6 URL 方括号;选择会话内有效(跨首页返回保留、重启重置),
失效自动回退默认回环。进入首页、网络变化(SCDynamicStore 监视+去抖)与
复制前刷新。

- 新缝 LocalInterfaceFactsReading:原始接口事实(地址/类型/名称)+ 变化
  通知;生产适配器封装 getifaddrs/SCNetworkInterface/SCDynamicStore 细节
- 运行时缝以 listenFacts 替换 terminalProxyEnvironmentCommands;命令派生
  移至工作流层(监听事实 + 生效选择)
- 替身测试证明策略行为;真实主机非视觉验证证明系统适配器整合
  (回环识别/类型映射/地址规范化/链路本地判定)
2026-10-01 10:06:52 +08:00

49 lines
2.0 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 Combine
import Foundation
// MARK: - 原始接口事实(issue #72)
/// 单个本机接口单播地址的原始事实:族与 IPv6 链路本地标记已判明,过滤、
/// 排序与取舍全部由工作流层策略完成。
struct LocalInterfaceAddress: Equatable, Sendable {
enum Family: Equatable, Sendable {
case ipv4
case ipv6
}
/// 规范化 IP 文本(inet_ntop 呈现形,无作用域后缀)。
let address: String
let family: Family
/// IPv6 链路本地(fe80::/10);IPv4 链路本地不置位(属于允许接口的单播
/// 地址时可以列出)。
let isIPv6LinkLocal: Bool
}
/// 单个本机接口的原始事实(issue #72):系统适配器逐接口提供,类型白名单、
/// 地址族过滤、名称回退与排序均不在适配器内发生。
struct LocalInterfaceFacts: Equatable, Sendable {
/// BSD 接口名(lo0/en0/…):地址关联与地址身份的锚点。
let bsdName: String
/// IFF_LOOPBACK。
let isLoopback: Bool
/// SCNetworkInterfaceGetInterfaceType 原文;无 SystemConfiguration 映射
/// (如回环)为 nil。
let interfaceType: String?
/// SCNetworkInterfaceGetLocalizedDisplayName;缺失为 nil。
let localizedName: String?
/// 该接口的全部单播地址(未过滤)。
let addresses: [LocalInterfaceAddress]
}
/// 本机接口事实来源缝(issue #72):唯一的工作流层可注入事实来源,统一
/// 提供接口地址、类型、名称及变化通知;系统 API 查询细节封装于生产适配器,
/// 不为每个底层 API 另设 mock 协议。测试注入可编程替身。
@MainActor
protocol LocalInterfaceFactsReading: AnyObject {
/// 当前全部本机接口的原始事实(未过滤、未排序);枚举失败为 nil,
/// 调用方按「仅兼容回环候选」退化。
var interfaces: [LocalInterfaceFacts]? { get }
/// 接口事实变化通知(网络变化后发值);生产实现去抖,fake 同步手动。
var changes: AnyPublisher<Void, Never> { get }
}