Files

120 lines
4.5 KiB
Swift

import Foundation
import Darwin
struct CertificateAuthority: Equatable {
let certPEM: String
let keyPEM: String
}
enum CoreBridgeError: LocalizedError {
case generationFailed
case serverStartFailed
var errorDescription: String? {
switch self {
case .generationFailed: return String(localized: "无法生成本地证书")
case .serverStartFailed: return String(localized: "无法启动本地证书服务")
}
}
}
enum CoreBridge {
static func isValidCertificateAuthority(_ authority: CertificateAuthority) -> Bool {
authority.certPEM.withCString { certificate in
authority.keyPEM.withCString { key in
wloccore_validateca(UnsafeMutablePointer(mutating: certificate), UnsafeMutablePointer(mutating: key)) != 0
}
}
}
static func generateCertificateAuthority() throws -> CertificateAuthority {
RuntimeLogger.info("APP", "Core.CA", "调用 Go Core 生成 CA")
let result = wloccore_generateca()
guard let certPointer = result.r0, let keyPointer = result.r1 else {
flushLogs(category: "CA")
throw CoreBridgeError.generationFailed
}
defer { free(certPointer); free(keyPointer) }
RuntimeLogger.info("APP", "Core.CA", "Go Core CA 生成成功")
flushLogs(category: "CA")
return CertificateAuthority(certPEM: String(cString: certPointer), keyPEM: String(cString: keyPointer))
}
/// 调用 Go Core 做一次模拟 wloc 响应改写测试,验证定位数据是否会被改成目标坐标。
static func testWlocPatch(lat: Double, lon: Double, accuracy: Int) -> String {
guard let ptr = wloccore_testpatch(CDouble(lat), CDouble(lon), CInt(accuracy)) else {
return "error: null result"
}
defer { free(ptr) }
return String(cString: ptr)
}
static func flushLogs(category: String) {
guard let pointer = wloccore_drainlogs() else { return }
defer { free(pointer) }
String(cString: pointer).split(separator: "\n").forEach {
RuntimeLogger.info("CORE", category, String($0))
}
}
static func refreshVerifyToken() -> String {
guard let ptr = wloccore_refreshverifytoken() else { return "" }
defer { free(ptr) }
return String(cString: ptr)
}
}
final class LocalCertificateServer {
private var handle: UInt = 0
private(set) var downloadURL: URL?
private(set) var probeURL: URL?
private(set) var leafHash = ""
deinit { stop() }
func start(authority: CertificateAuthority) throws {
if handle != 0 {
RuntimeLogger.debug("APP", "Certificate.server", "本地证书服务已在运行")
return
}
RuntimeLogger.info("APP", "Certificate.server", "调用 Go Core 启动本地证书服务")
let newHandle: UInt = authority.certPEM.withCString { certPointer in
authority.keyPEM.withCString { keyPointer in
UInt(wloccore_startcertserver(UnsafeMutablePointer(mutating: certPointer), UnsafeMutablePointer(mutating: keyPointer)))
}
}
guard newHandle != 0 else {
CoreBridge.flushLogs(category: "CertificateServer")
throw CoreBridgeError.serverStartFailed
}
let httpPort = Int(wloccore_certserver_httpport(newHandle))
let httpsPort = Int(wloccore_certserver_httpsport(newHandle))
guard httpPort > 0, httpsPort > 0, let hashPointer = wloccore_certserver_leafsha256(newHandle) else {
_ = wloccore_stopcertserver(newHandle)
throw CoreBridgeError.serverStartFailed
}
defer { free(hashPointer) }
handle = newHandle
downloadURL = URL(string: "http://127.0.0.1:\(httpPort)/ca.cer")
probeURL = URL(string: "https://127.0.0.1:\(httpsPort)/health")
leafHash = String(cString: hashPointer)
RuntimeLogger.info("APP", "Certificate.server", "本地证书服务启动成功", details: [
"httpPort": String(httpPort),
"httpsPort": String(httpsPort),
"leafHash": leafHash
])
CoreBridge.flushLogs(category: "CertificateServer")
}
func stop() {
guard handle != 0 else { return }
let result = wloccore_stopcertserver(handle)
RuntimeLogger.info("APP", "Certificate.server", "停止本地证书服务", details: ["result": String(result)])
CoreBridge.flushLogs(category: "CertificateServer")
handle = 0
downloadURL = nil
probeURL = nil
leafHash = ""
}
}