Files

84 lines
3.6 KiB
Swift
Raw Permalink 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
@testable import ShadowsocksX_NG2
/// 测试支持:模拟 wrapper 写入部署收据。生产唯一收据写者是 Agent wrapper
/// (AgentContract.writeRuntimeReceipt),GUI 侧只有读(readRuntimeReceipt);
/// 收据格式知识由 Domain 的 RuntimeDeploymentReceipt 类型承载,此处只复刻
/// wrapper 的「写动作」供夹具布置磁盘状态。
extension RuntimeFileStore {
func writeRuntimeReceipt(for document: SslocalRuntimeDocument, processID: Int32) throws {
guard receiptIdentity(for: document) != nil else {
throw PersistenceError.ioFailure(detail: "Runtime contract digest is unavailable")
}
try writePublishedRuntimeReceipt(processID: processID)
}
}
/// 测试观察真实发布文件;不把上游输出反向重建为 GUI 运行意图。
struct PublishedRuntimeConfiguration: Equatable {
let configuration: SslocalConfigurationDocument
let snapshot: RuntimeSupervision
let intentSHA256: String
var servers: [SslocalServerDocument] { configuration.servers }
var locals: [SslocalLocalDocument] { configuration.locals }
var socksPort: Int { locals.first { $0.inboundProtocol == "socks" }?.localPort ?? 0 }
var httpPort: Int { locals.first { $0.inboundProtocol == "http" }?.localPort ?? 0 }
var aclRuntime: ProxyACLDocument? {
guard let acl = snapshot.acl,
let summary = snapshot.aclVariants.first(where: { $0.value == acl })?.key,
let path = configuration.aclFilePath
else { return nil }
return ProxyACLDocument(path: path, summary: summary, content: "", sha256: acl.sha256)
}
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.configuration == rhs.configuration && lhs.intentSHA256 == rhs.intentSHA256
}
}
extension RuntimeFileStore {
func loadDocument() -> PublishedRuntimeConfiguration? {
guard let snapshot = RuntimePublication.load(at: supervisionFileURL),
let data = try? Data(contentsOf: directoryURL.appendingPathComponent(snapshot.configuration)),
let configuration = try? JSONDecoder().decode(SslocalConfigurationDocument.self, from: data),
let intentData = try? Data(
contentsOf: directoryURL.appendingPathComponent(snapshot.intentMetadata)),
let intent = try? JSONDecoder().decode(PublishedRuntimeIntent.self, from: intentData)
else { return nil }
return PublishedRuntimeConfiguration(
configuration: configuration, snapshot: snapshot, intentSHA256: intent.sha256)
}
func readData() -> Data? {
guard let snapshot = RuntimePublication.load(at: supervisionFileURL) else { return nil }
return try? Data(contentsOf: directoryURL.appendingPathComponent(snapshot.configuration))
}
func receiptIdentity(for document: PublishedRuntimeConfiguration) -> String? {
guard let current = loadDocument(), current.intentSHA256 == document.intentSHA256 else {
return nil
}
return current.snapshot.deploymentID
}
func writeRuntimeReceipt(for document: PublishedRuntimeConfiguration, processID: Int32) throws {
guard receiptIdentity(for: document) != nil else { throw POSIXError(.EINVAL) }
try writePublishedRuntimeReceipt(processID: processID)
}
}
extension RuntimeFileStore {
func writePublishedRuntimeReceipt(processID: Int32) throws {
guard let snapshot = RuntimePublication.load(at: supervisionFileURL) else {
throw POSIXError(.EINVAL)
}
try RuntimePublication.select(snapshot, configurationLink: fileURL, aclLink: aclFileURL)
try AtomicFileWriter.write(
JSONEncoder().encode(
RuntimeDeploymentReceipt(processID: processID, deploymentID: snapshot.deploymentID)),
to: runtimeStatusFileURL)
}
}