统一消息传递机制

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.
Task {
do {
let message = try NEMessage(serializedBytes: messageData)
let replyData = try await self.handleAppEvent(message: message)
let message = try AppRequest(serializedBytes: messageData)
let replyData = try await self.handleAppRequest(message: message)
completionHandler?(replyData)
} catch let err {
var reply = NEReply()
var reply = TunnelResponse()
reply.code = 1
reply.message = err.localizedDescription
@ -83,26 +83,33 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
// Add code here to wake up.
}
private func handleAppEvent(message: NEMessage) async throws -> Data? {
switch message.message {
case .exitNodeIpChanged(let exitNodeIpChanged):
let exitNodeIp = exitNodeIpChanged.ip
private func handleAppRequest(message: AppRequest) async throws -> Data? {
guard let contextActor = self.contextActor else {
throw TunnelError.invalidContext
}
switch message.command {
case .changeExitNode(let changeExitNode):
let exitNodeIp = changeExitNode.ip
do {
try await self.contextActor?.updateExitNode(exitNodeIp: exitNodeIp)
var reply = NEReply()
try await contextActor.updateExitNode(exitNodeIp: exitNodeIp)
var reply = TunnelResponse()
reply.code = 0
reply.message = "操作成功"
return try reply.serializedData()
} catch let err {
var reply = NEReply()
var reply = TunnelResponse()
reply.code = 1
reply.message = err.localizedDescription
return try reply.serializedData()
}
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
}
private func publishTunnelEvent(level: SDLTunnelAppNotifier.Event.Level = .error,
code: Int? = nil,
private func publishTunnelEvent(code: Int? = nil,
message: String) {
SDLTunnelAppNotifier.shared.publish(level: level, code: code, message: message)
SDLTunnelAppNotifier.shared.publish(code: code, message: message)
}
private func setNatType(natType: SDLNATProberActor.NatType) {
@ -706,7 +705,7 @@ extension SDLContextActor {
switch errorCode {
case .invalidToken, .nodeDisabled:
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)
self.failReady(error)
@ -714,7 +713,7 @@ extension SDLContextActor {
case .noIpAddress, .networkFault, .internalFault:
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")
@ -735,7 +734,7 @@ extension SDLContextActor {
self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
}
case .shutdown(let message):
self.publishTunnelEvent(level: .fatal, message: message)
self.publishTunnelEvent(message: message)
// 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)

View File

@ -8,21 +8,6 @@
import Foundation
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()
private let suiteName: String
@ -34,20 +19,18 @@ final class SDLTunnelAppNotifier {
self.eventKey = eventKey
}
func publish(level: Event.Level = .error, code: Int? = nil, message: String) {
let event = Event(
id: UUID().uuidString,
timestamp: Date().timeIntervalSince1970,
level: level,
code: code,
message: message
)
func publish(code: Int? = nil, message: String) {
var event = TunnelEvent()
event.id = UUID().uuidString
event.timestampMs = UInt64(Date().timeIntervalSince1970 * 1000)
event.code = Int32(clamping: code ?? 0)
event.message = message
self.publish(event)
}
func publish(_ event: Event) {
func publish(_ event: TunnelEvent) {
guard let shared = UserDefaults(suiteName: self.suiteName),
let data = try? JSONEncoder().encode(event) else {
let data = try? event.serializedData() else {
return
}

View File

@ -8,25 +8,12 @@
import Foundation
struct SDLTunnelAppEventStore {
struct Event: Codable, Sendable, Identifiable {
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
}
typealias Event = TunnelEvent
static func loadLatestEvent() -> Event? {
guard let shared = UserDefaults(suiteName: SDLNotificationCenter.Configuration.appGroupSuiteName),
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
}

View File

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

View File

@ -163,7 +163,7 @@ struct NetworkStatusBar: View {
Button {
Task {
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)")
}
} label: {