统一消息传递机制

This commit is contained in:
anlicheng 2026-04-15 15:34:45 +08:00
parent c6e79b0e68
commit 721087a223
6 changed files with 39 additions and 63 deletions

View File

@ -60,11 +60,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
// Add code here to handle the message. // Add code here to handle the message.
Task { Task {
do { do {
let message = try NEMessage(serializedBytes: messageData) let message = try AppRequest(serializedBytes: messageData)
let replyData = try await self.handleAppEvent(message: message) let replyData = try await self.handleAppRequest(message: message)
completionHandler?(replyData) completionHandler?(replyData)
} catch let err { } catch let err {
var reply = NEReply() var reply = TunnelResponse()
reply.code = 1 reply.code = 1
reply.message = err.localizedDescription reply.message = err.localizedDescription
@ -83,26 +83,33 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
// Add code here to wake up. // Add code here to wake up.
} }
private func handleAppEvent(message: NEMessage) async throws -> Data? { private func handleAppRequest(message: AppRequest) async throws -> Data? {
switch message.message { guard let contextActor = self.contextActor else {
case .exitNodeIpChanged(let exitNodeIpChanged): throw TunnelError.invalidContext
let exitNodeIp = exitNodeIpChanged.ip }
switch message.command {
case .changeExitNode(let changeExitNode):
let exitNodeIp = changeExitNode.ip
do { do {
try await self.contextActor?.updateExitNode(exitNodeIp: exitNodeIp) try await contextActor.updateExitNode(exitNodeIp: exitNodeIp)
var reply = NEReply() var reply = TunnelResponse()
reply.code = 0 reply.code = 0
reply.message = "操作成功" reply.message = "操作成功"
return try reply.serializedData() return try reply.serializedData()
} catch let err { } catch let err {
var reply = NEReply() var reply = TunnelResponse()
reply.code = 1 reply.code = 1
reply.message = err.localizedDescription reply.message = err.localizedDescription
return try reply.serializedData() return try reply.serializedData()
} }
case .none: case .none:
return nil var reply = TunnelResponse()
reply.code = 1
reply.message = "无效请求"
return try reply.serializedData()
} }
} }

View File

@ -381,10 +381,9 @@ actor SDLContextActor {
self.dataCipher = nil self.dataCipher = nil
} }
private func publishTunnelEvent(level: SDLTunnelAppNotifier.Event.Level = .error, private func publishTunnelEvent(code: Int? = nil,
code: Int? = nil,
message: String) { message: String) {
SDLTunnelAppNotifier.shared.publish(level: level, code: code, message: message) SDLTunnelAppNotifier.shared.publish(code: code, message: message)
} }
private func setNatType(natType: SDLNATProberActor.NatType) { private func setNatType(natType: SDLNATProberActor.NatType) {
@ -706,7 +705,7 @@ extension SDLContextActor {
switch errorCode { switch errorCode {
case .invalidToken, .nodeDisabled: case .invalidToken, .nodeDisabled:
self.superRegistrationStateMachine.handleFailure() self.superRegistrationStateMachine.handleFailure()
self.publishTunnelEvent(level: .fatal, code: Int(errorCode.rawValue), message: errorMessage) self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
// 退 // 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1) let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
self.failReady(error) self.failReady(error)
@ -714,7 +713,7 @@ extension SDLContextActor {
case .noIpAddress, .networkFault, .internalFault: case .noIpAddress, .networkFault, .internalFault:
self.superRegistrationStateMachine.handleRetryableNak() self.superRegistrationStateMachine.handleRetryableNak()
self.publishTunnelEvent(level: .warning, code: Int(errorCode.rawValue), message: errorMessage) self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
} }
SDLLogger.log("[SDLContext] Get a SuperNak message exit") SDLLogger.log("[SDLContext] Get a SuperNak message exit")
@ -735,7 +734,7 @@ extension SDLContextActor {
self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress) self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
} }
case .shutdown(let message): case .shutdown(let message):
self.publishTunnelEvent(level: .fatal, message: message) self.publishTunnelEvent(message: message)
// 退 // 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2) let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)

View File

@ -8,21 +8,6 @@
import Foundation import Foundation
final class SDLTunnelAppNotifier { final class SDLTunnelAppNotifier {
struct Event: Codable, Sendable {
enum Level: String, Codable, Sendable {
case info
case warning
case error
case fatal
}
let id: String
let timestamp: TimeInterval
let level: Level
let code: Int?
let message: String
}
static let shared = SDLTunnelAppNotifier() static let shared = SDLTunnelAppNotifier()
private let suiteName: String private let suiteName: String
@ -34,20 +19,18 @@ final class SDLTunnelAppNotifier {
self.eventKey = eventKey self.eventKey = eventKey
} }
func publish(level: Event.Level = .error, code: Int? = nil, message: String) { func publish(code: Int? = nil, message: String) {
let event = Event( var event = TunnelEvent()
id: UUID().uuidString, event.id = UUID().uuidString
timestamp: Date().timeIntervalSince1970, event.timestampMs = UInt64(Date().timeIntervalSince1970 * 1000)
level: level, event.code = Int32(clamping: code ?? 0)
code: code, event.message = message
message: message
)
self.publish(event) self.publish(event)
} }
func publish(_ event: Event) { func publish(_ event: TunnelEvent) {
guard let shared = UserDefaults(suiteName: self.suiteName), guard let shared = UserDefaults(suiteName: self.suiteName),
let data = try? JSONEncoder().encode(event) else { let data = try? event.serializedData() else {
return return
} }

View File

@ -8,25 +8,12 @@
import Foundation import Foundation
struct SDLTunnelAppEventStore { struct SDLTunnelAppEventStore {
struct Event: Codable, Sendable, Identifiable { typealias Event = TunnelEvent
enum Level: String, Codable, Sendable {
case info
case warning
case error
case fatal
}
let id: String
let timestamp: TimeInterval
let level: Level
let code: Int?
let message: String
}
static func loadLatestEvent() -> Event? { static func loadLatestEvent() -> Event? {
guard let shared = UserDefaults(suiteName: SDLNotificationCenter.Configuration.appGroupSuiteName), guard let shared = UserDefaults(suiteName: SDLNotificationCenter.Configuration.appGroupSuiteName),
let data = shared.data(forKey: SDLNotificationCenter.Configuration.latestEventKey), let data = shared.data(forKey: SDLNotificationCenter.Configuration.latestEventKey),
let event = try? JSONDecoder().decode(Event.self, from: data) else { let event = try? Event(serializedBytes: data) else {
return nil return nil
} }

View File

@ -108,13 +108,13 @@ class AppContext {
throw AppContextError(message: "网络未连接") throw AppContextError(message: "网络未连接")
} }
var exitNodeIpChanged = NEMessage.ExitNodeIpChanged() var changeExitNode = AppRequest.ChangeExitNodeRequest()
exitNodeIpChanged.ip = exitNodeIp changeExitNode.ip = exitNodeIp
var neMessage = NEMessage() var appRequest = AppRequest()
neMessage.message = .exitNodeIpChanged(exitNodeIpChanged) appRequest.command = .changeExitNode(changeExitNode)
let message = try neMessage.serializedData() let message = try appRequest.serializedData()
return try await self.vpnManager.sendMessage(message) return try await self.vpnManager.sendMessage(message)
} }

View File

@ -163,7 +163,7 @@ struct NetworkStatusBar: View {
Button { Button {
Task { Task {
let result = try await self.appContext.changeExitNodeIp(exitNodeIp: self.exitNodeIp) let result = try await self.appContext.changeExitNodeIp(exitNodeIp: self.exitNodeIp)
let reply = try NEReply(serializedBytes: result) let reply = try TunnelResponse(serializedBytes: result)
NSLog("change exit node ip: \(reply)") NSLog("change exit node ip: \(reply)")
} }
} label: { } label: {