fix superControlPlane

This commit is contained in:
anlicheng 2026-05-28 00:59:08 +08:00
parent 83bd5dce7e
commit eca022cae0
3 changed files with 273 additions and 263 deletions

View File

@ -22,9 +22,6 @@ actor SDLContextActor {
// AES // AES
private var dataCipher: CCDataCipher? private var dataCipher: CCDataCipher?
// session token
private var sessionToken: Data?
// rsa, public_key // rsa, public_key
// //
nonisolated let rsaCipher: RSACipher nonisolated let rsaCipher: RSACipher
@ -32,6 +29,7 @@ actor SDLContextActor {
private let dnsCloudService: DNSCloudService private let dnsCloudService: DNSCloudService
private let dnsLocalService: DNSLocalService private let dnsLocalService: DNSLocalService
private let superService: SDLSuperService private let superService: SDLSuperService
private let superControlPlane: SDLSuperControlPlane
private let udpHoleService: SDLUDPHoleService private let udpHoleService: SDLUDPHoleService
private let udpHoleV6Service: SDLUDPHoleV6Service private let udpHoleV6Service: SDLUDPHoleV6Service
private let packetOutboundActor: PacketOutboundActor private let packetOutboundActor: PacketOutboundActor
@ -77,6 +75,7 @@ actor SDLContextActor {
let udpHoleV6Service = SDLUDPHoleV6Service() let udpHoleV6Service = SDLUDPHoleV6Service()
let dnsCloudService = DNSCloudService(serverIP: config.serverEndpoint.ip) let dnsCloudService = DNSCloudService(serverIP: config.serverEndpoint.ip)
let dnsLocalService = DNSLocalService(publicDnsServers: Self.publicDnsServers) let dnsLocalService = DNSLocalService(publicDnsServers: Self.publicDnsServers)
let superControlPlane = SDLSuperControlPlane(config: config, rsaCipher: rsaCipher)
let tunNetworkManager = SDLTunNetworkManager(provider: provider) let tunNetworkManager = SDLTunNetworkManager(provider: provider)
let ipv6AssistPair = AsyncStream.makeStream(of: Optional<SDLV6Info>.self, bufferingPolicy: .bufferingNewest(1)) let ipv6AssistPair = AsyncStream.makeStream(of: Optional<SDLV6Info>.self, bufferingPolicy: .bufferingNewest(1))
let packetOutboundActor = PacketOutboundActor( let packetOutboundActor = PacketOutboundActor(
@ -122,6 +121,7 @@ actor SDLContextActor {
self.dnsCloudService = dnsCloudService self.dnsCloudService = dnsCloudService
self.dnsLocalService = dnsLocalService self.dnsLocalService = dnsLocalService
self.superService = superService self.superService = superService
self.superControlPlane = superControlPlane
self.udpHoleService = udpHoleService self.udpHoleService = udpHoleService
self.udpHoleV6Service = udpHoleV6Service self.udpHoleV6Service = udpHoleV6Service
self.packetOutboundActor = packetOutboundActor self.packetOutboundActor = packetOutboundActor
@ -138,7 +138,17 @@ actor SDLContextActor {
} }
let rootTask = Task { let rootTask = Task {
try await self.runRoot() do {
try await self.runRootBody()
await self.cleanupRoot()
} catch is CancellationError {
await self.cleanupRoot()
throw CancellationError()
} catch {
await self.readySignal.fail(error)
await self.cleanupRoot()
throw error
}
} }
self.rootTask = rootTask self.rootTask = rootTask
@ -163,20 +173,6 @@ actor SDLContextActor {
await self.cleanupRoot() await self.cleanupRoot()
} }
private func runRoot() async throws {
do {
try await self.runRootBody()
await self.cleanupRoot()
} catch is CancellationError {
await self.cleanupRoot()
throw CancellationError()
} catch {
await self.readySignal.fail(error)
await self.cleanupRoot()
throw error
}
}
private func runRootBody() async throws { private func runRootBody() async throws {
self.prepareTunnelNotifier() self.prepareTunnelNotifier()
@ -188,8 +184,13 @@ actor SDLContextActor {
await self?.handleDNSEvent(event) await self?.handleDNSEvent(event)
} }
await self.superService.updateMessageHandler { [weak self] message in await self.superControlPlane.updateDecisionHandler { [weak self] decision in
await self?.handleSuperMessage(message: message) await self?.handleSuperDecision(decision)
}
let superControlPlane = self.superControlPlane
await self.superService.updateMessageHandler { message in
await superControlPlane.handle(message)
} }
let packetInboundActor = self.packetInboundActor let packetInboundActor = self.packetInboundActor
@ -392,8 +393,8 @@ actor SDLContextActor {
await self.dnsLocalService.stop() await self.dnsLocalService.stop()
await self.superService.stop() await self.superService.stop()
await self.superControlPlane.reset()
self.sessionToken = nil
self.dataCipher = nil self.dataCipher = nil
self.natType = .blocked self.natType = .blocked
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: nil) await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: nil)
@ -436,11 +437,6 @@ extension SDLContextActor {
// MARK: // MARK:
extension SDLContextActor { extension SDLContextActor {
// super/stun
private func sendSuperPacket(type: SDLPacketType, data: Data) async {
await self.sendPacket(type: type, data: data, remoteAddress: self.config.stunSocketAddress)
}
// peer // peer
private func sendPeerPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async { private func sendPeerPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async {
await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress) await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress)
@ -460,160 +456,64 @@ extension SDLContextActor {
// MARK: Super // MARK: Super
extension SDLContextActor { extension SDLContextActor {
private func handleSuperMessage(message: SDLSuperMessage) async { private func handleSuperDecision(_ decision: SuperDecision) async {
switch message { switch decision {
case .welcome(let welcome): case .updateIPv6Assist(let assistInfo):
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
await self.stopCurrentIPv6AssistClient() await self.stopCurrentIPv6AssistClient()
// v6 self.ipv6AssistContinuation.yield(assistInfo)
if welcome.hasIpv6Assist { case .completeRegistration(let cipher):
self.ipv6AssistContinuation.yield(welcome.ipv6Assist) await self.completeSuperRegistration(cipher: cipher)
} else { case .failTunnel(let error):
self.ipv6AssistContinuation.yield(nil) await self.failTunnel(error)
} case .publishTunnelEvent(let code, let message):
self.publishTunnelEvent(code: code, message: message)
// case .sendSuper(let type, let data):
await self.doRegisterSuper() await self.superService.send(type: type, data: data)
SDLLogger.log("[SDLContext] quic doRegisterSuper") case .sendPacket(let type, let data, let remoteAddress):
case .pong: await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress)
//SDLLogger.shared.log("[SDLContext] quic pong") case .resolvePeerInfo(let peerInfo):
()
case .registerSuperAck(let registerSuperAck):
await self.handleRegisterSuperAck(registerSuperAck: registerSuperAck)
case .registerSuperNak(let registerSuperNak):
await self.handleRegisterSuperNak(nakPacket: registerSuperNak)
case .peerInfo(let peerInfo):
SDLLogger.log("[SDLContext] peer message: \(peerInfo)")
let packets = await self.puncherActor.makeRegisterPackets(peerInfo: peerInfo) let packets = await self.puncherActor.makeRegisterPackets(peerInfo: peerInfo)
for packet in packets { for packet in packets {
await self.sendPacket(type: .register, data: packet.data, remoteAddress: packet.remoteAddress) await self.sendPacket(type: .register, data: packet.data, remoteAddress: packet.remoteAddress)
} }
case .event(let event):
await self.handleEvent(event: event)
case .policyReponse(let policyResponse):
//
await self.policyService.applyPolicyResponse(policyResponse)
case .exposedServiceResponse(let response):
await self.applyExposedServiceResponse(response)
case .arpResponse(let arpResponse):
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
await self.arpResolver.handleArpResponse(arpResponse: arpResponse)
}
}
private func makeSuperEventProcessor() -> SDLSuperEventProcessor {
return .init(networkAddress: self.config.networkAddress)
}
private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async {
// rsa
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
let error = SDLError.invalidKey
await self.readySignal.fail(error)
self.provider.cancelTunnelWithError(error)
return
}
let algorithm = registerSuperAck.algorithm.lowercased()
let regionId = registerSuperAck.regionID
self.sessionToken = registerSuperAck.sessionToken
switch algorithm {
case "aes":
self.dataCipher = CCAESChiper(key: key)
case "chacha20":
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
default:
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
await self.readySignal.fail(error)
self.provider.cancelTunnelWithError(error)
return
}
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: self.dataCipher)
SDLLogger.log("[SDLContext] registerSuperAck, use algorithm \(algorithm), key len: \(key.count)")
// tun
do {
try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer)
SDLLogger.log("[SDLContext] setNetworkSettings successed")
await self.readySignal.succeed(())
} catch let err {
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
await self.readySignal.fail(err)
self.provider.cancelTunnelWithError(err)
}
}
private func handleRegisterSuperNak(nakPacket: SDLRegisterSuperNak) async {
let errorMessage = nakPacket.errorMessage
guard let errorCode = SDLNAKErrorCode(rawValue: UInt8(nakPacket.errorCode)) else {
return
}
switch errorCode {
case .invalidToken, .nodeDisabled:
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
// 退
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
await self.readySignal.fail(error)
self.provider.cancelTunnelWithError(error)
case .noIpAddress, .networkFault, .internalFault:
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
}
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
}
private func handleEvent(event: SDLEvent) async {
let processor = self.makeSuperEventProcessor()
let plan = await processor.makeProcessingPlan(event: event)
if let logMessage = plan.logMessage {
SDLLogger.log(logMessage)
}
switch plan.action {
case .removeSession(let dstMac): case .removeSession(let dstMac):
await self.sessionManager.removeSession(dstMac: dstMac) await self.sessionManager.removeSession(dstMac: dstMac)
case .sendRegister(let registerData, let remoteAddresses):
for remoteAddress in remoteAddresses {
await self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
}
case .requestExposedService: case .requestExposedService:
await self.requestExposedService() await self.requestExposedService()
case .shutdown(let message): case .shutdown(let message):
self.publishTunnelEvent(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)
self.provider.cancelTunnelWithError(error) self.provider.cancelTunnelWithError(error)
case .none: case .applyPolicyResponse(let policyResponse):
() await self.policyService.applyPolicyResponse(policyResponse)
case .applyExposedServiceResponse(let response):
await self.applyExposedServiceResponse(response)
case .handleARPResponse(let arpResponse):
await self.arpResolver.handleArpResponse(arpResponse: arpResponse)
} }
} }
private func doRegisterSuper() async { private func completeSuperRegistration(cipher: CCDataCipher) async {
// self.dataCipher = cipher
var registerSuper = SDLRegisterSuper() await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: cipher)
registerSuper.clientID = self.config.clientId await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: cipher)
registerSuper.networkID = self.config.networkAddress.networkId
registerSuper.mac = self.config.networkAddress.mac do {
registerSuper.ip = self.config.networkAddress.ip try await self.tunNetworkManager.apply(settings: .init(config: self.config), dnsServer: DNSHelper.dnsServer)
registerSuper.maskLen = UInt32(self.config.networkAddress.maskLen) SDLLogger.log("[SDLContext] setNetworkSettings successed")
registerSuper.hostname = self.config.hostname await self.readySignal.succeed(())
registerSuper.pubKey = self.rsaCipher.pubKey } catch {
registerSuper.accessToken = self.config.accessToken SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(error)")
await self.failTunnel(error)
if let registerSuperData = try? registerSuper.serializedData() {
SDLLogger.log("[SDLContext] will send register super")
await self.superService.send(type: .registerSuper, data: registerSuperData)
} }
} }
private func failTunnel(_ error: Error) async {
await self.readySignal.fail(error)
self.provider.cancelTunnelWithError(error)
}
private func requestExposedService() async { private func requestExposedService() async {
guard let requestData = await self.policyService.makeExposedServiceRequest() else { guard let requestData = await self.policyService.makeExposedServiceRequest() else {
return return
@ -735,29 +635,7 @@ extension SDLContextActor {
SDLLogger.log("[SDLContext] probe ipv6 address: empty") SDLLogger.log("[SDLContext] probe ipv6 address: empty")
} }
await self.sendStunRequest(v6Info: probeReply?.v6Info) await self.superControlPlane.sendStunRequest(natType: self.natType, v6Info: probeReply?.v6Info)
}
private func sendStunRequest(v6Info: SDLV6Info?) async {
guard let sessionToken = self.sessionToken else {
return
}
var stunRequest = SDLStunRequest()
stunRequest.clientID = self.config.clientId
stunRequest.networkID = self.config.networkAddress.networkId
stunRequest.ip = self.config.networkAddress.ip
stunRequest.mac = self.config.networkAddress.mac
stunRequest.natType = UInt32(self.natType.rawValue)
stunRequest.sessionToken = sessionToken
if let v6Info {
stunRequest.v6Info = v6Info
}
if let stunData = try? stunRequest.serializedData() {
await self.sendSuperPacket(type: .stunRequest, data: stunData)
}
} }
} }

View File

@ -0,0 +1,210 @@
//
// SDLSuperControlPlane.swift
// Tun
//
// Created by Codex on 2026/5/28.
//
import Foundation
import NIOCore
enum SuperDecision {
case updateIPv6Assist(SDLV6Info?)
case completeRegistration(cipher: CCDataCipher)
case failTunnel(Error)
case publishTunnelEvent(code: Int?, message: String)
case sendSuper(type: SDLPacketType, data: Data)
case sendPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress)
case resolvePeerInfo(SDLPeerInfo)
case removeSession(dstMac: Data)
case requestExposedService
case shutdown(message: String)
case applyPolicyResponse(SDLPolicyResponse)
case applyExposedServiceResponse(SDLExposedServiceResponse)
case handleARPResponse(SDLArpResponse)
}
actor SDLSuperControlPlane {
typealias DecisionHandler = @Sendable (SuperDecision) async -> Void
private let config: SDLConfiguration
private let rsaCipher: RSACipher
private var sessionToken: Data?
private var onDecision: DecisionHandler = { _ in }
init(config: SDLConfiguration, rsaCipher: RSACipher) {
self.config = config
self.rsaCipher = rsaCipher
}
func updateDecisionHandler(_ onDecision: @escaping DecisionHandler) {
self.onDecision = onDecision
}
func reset() {
self.sessionToken = nil
}
func handle(_ message: SDLSuperMessage) async {
switch message {
case .welcome(let welcome):
await self.handleWelcome(welcome)
case .pong:
()
case .registerSuperAck(let registerSuperAck):
await self.handleRegisterSuperAck(registerSuperAck)
case .registerSuperNak(let registerSuperNak):
await self.handleRegisterSuperNak(registerSuperNak)
case .peerInfo(let peerInfo):
SDLLogger.log("[SDLContext] peer message: \(peerInfo)")
await self.onDecision(.resolvePeerInfo(peerInfo))
case .event(let event):
await self.handleEvent(event)
case .policyReponse(let policyResponse):
await self.onDecision(.applyPolicyResponse(policyResponse))
case .exposedServiceResponse(let response):
await self.onDecision(.applyExposedServiceResponse(response))
case .arpResponse(let arpResponse):
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
await self.onDecision(.handleARPResponse(arpResponse))
}
}
func sendStunRequest(natType: SDLNATProberActor.NatType, v6Info: SDLV6Info?) async {
guard let sessionToken else {
return
}
var stunRequest = SDLStunRequest()
stunRequest.clientID = self.config.clientId
stunRequest.networkID = self.config.networkAddress.networkId
stunRequest.ip = self.config.networkAddress.ip
stunRequest.mac = self.config.networkAddress.mac
stunRequest.natType = UInt32(natType.rawValue)
stunRequest.sessionToken = sessionToken
if let v6Info {
stunRequest.v6Info = v6Info
}
if let stunData = try? stunRequest.serializedData() {
await self.onDecision(.sendPacket(type: .stunRequest, data: stunData, remoteAddress: self.config.stunSocketAddress))
}
}
private func handleWelcome(_ welcome: SDLWelcome) async {
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
if welcome.hasIpv6Assist {
await self.onDecision(.updateIPv6Assist(welcome.ipv6Assist))
} else {
await self.onDecision(.updateIPv6Assist(nil))
}
await self.doRegisterSuper()
SDLLogger.log("[SDLContext] quic doRegisterSuper")
}
private func handleRegisterSuperAck(_ registerSuperAck: SDLRegisterSuperAck) async {
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
await self.onDecision(.failTunnel(SDLError.invalidKey))
return
}
let algorithm = registerSuperAck.algorithm.lowercased()
let regionId = registerSuperAck.regionID
self.sessionToken = registerSuperAck.sessionToken
let cipher: CCDataCipher
switch algorithm {
case "aes":
cipher = CCAESChiper(key: key)
case "chacha20":
cipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
default:
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
await self.onDecision(.failTunnel(SDLError.unsupportedAlgorithm(algorithm: algorithm)))
return
}
SDLLogger.log("[SDLContext] registerSuperAck, use algorithm \(algorithm), key len: \(key.count)")
await self.onDecision(.completeRegistration(cipher: cipher))
}
private func handleRegisterSuperNak(_ nakPacket: SDLRegisterSuperNak) async {
let errorMessage = nakPacket.errorMessage
guard let errorCode = SDLNAKErrorCode(rawValue: UInt8(nakPacket.errorCode)) else {
return
}
switch errorCode {
case .invalidToken, .nodeDisabled:
await self.onDecision(.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage))
await self.onDecision(.failTunnel(NSError(domain: "com.jihe.punchnet.tun", code: -1)))
case .noIpAddress, .networkFault, .internalFault:
await self.onDecision(.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage))
}
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
}
private func handleEvent(_ event: SDLEvent) async {
switch event.event {
case .natChanged(let natChangedEvent):
let dstMac = natChangedEvent.mac
SDLLogger.log("[SDLContext] natChangedEvent, dstMac: \(dstMac)")
await self.onDecision(.removeSession(dstMac: dstMac))
case .sendRegister(let sendRegisterEvent):
await self.handleSendRegisterEvent(sendRegisterEvent)
case .exposedServiceChanged:
SDLLogger.log("[SDLContext] exposedServiceChanged event")
await self.onDecision(.requestExposedService)
case .shutdown(let shutdownEvent):
await self.onDecision(.shutdown(message: shutdownEvent.message))
case .none:
()
}
}
private func handleSendRegisterEvent(_ event: SDLEvent.SendRegister) async {
var register = SDLRegister()
register.networkID = self.config.networkAddress.networkId
register.srcMac = self.config.networkAddress.mac
register.dstMac = event.dstMac
guard let registerData = try? register.serializedData() else {
return
}
SDLLogger.log("[SDLContext] sendRegisterEvent, ip: \(event)")
if event.natIp > 0 && event.natPort > 0 {
let address = SDLUtil.int32ToIp(event.natIp)
if let remoteAddress = try? SocketAddress(ipAddress: address, port: Int(event.natPort)) {
await self.onDecision(.sendPacket(type: .register, data: registerData, remoteAddress: remoteAddress))
}
}
if event.hasV6Info, let remoteAddress = try? await event.v6Info.socketAddress() {
await self.onDecision(.sendPacket(type: .register, data: registerData, remoteAddress: remoteAddress))
}
}
private func doRegisterSuper() async {
var registerSuper = SDLRegisterSuper()
registerSuper.clientID = self.config.clientId
registerSuper.networkID = self.config.networkAddress.networkId
registerSuper.mac = self.config.networkAddress.mac
registerSuper.ip = self.config.networkAddress.ip
registerSuper.maskLen = UInt32(self.config.networkAddress.maskLen)
registerSuper.hostname = self.config.hostname
registerSuper.pubKey = self.rsaCipher.pubKey
registerSuper.accessToken = self.config.accessToken
if let registerSuperData = try? registerSuper.serializedData() {
SDLLogger.log("[SDLContext] will send register super")
await self.onDecision(.sendSuper(type: .registerSuper, data: registerSuperData))
}
}
}

View File

@ -1,78 +0,0 @@
//
// SDLSuperEventProcessor.swift
// Tun
//
// Created by on 2026/4/15.
//
import Foundation
import NIOCore
final class SDLSuperEventProcessor {
enum ProcessingAction {
case removeSession(dstMac: Data)
case sendRegister(data: Data, remoteAddresses: [SocketAddress])
case requestExposedService
case shutdown(message: String)
case none
}
struct ProcessingPlan {
let logMessage: String?
let action: ProcessingAction
}
private let networkAddress: SDLConfiguration.NetworkAddress
init(networkAddress: SDLConfiguration.NetworkAddress) {
self.networkAddress = networkAddress
}
func makeProcessingPlan(event: SDLEvent) async -> ProcessingPlan {
switch event.event {
case .natChanged(let natChangedEvent):
let dstMac = natChangedEvent.mac
return .init(
logMessage: "[SDLContext] natChangedEvent, dstMac: \(dstMac)",
action: .removeSession(dstMac: dstMac)
)
case .sendRegister(let sendRegisterEvent):
return await self.makeSendRegisterPlan(sendRegisterEvent)
case .exposedServiceChanged:
return .init(
logMessage: "[SDLContext] exposedServiceChanged event",
action: .requestExposedService
)
case .shutdown(let shutdownEvent):
return .init(logMessage: nil, action: .shutdown(message: shutdownEvent.message))
case .none:
return .init(logMessage: nil, action: .none)
}
}
private func makeSendRegisterPlan(_ event: SDLEvent.SendRegister) async -> ProcessingPlan {
// register
var register = SDLRegister()
register.networkID = self.networkAddress.networkId
register.srcMac = self.networkAddress.mac
register.dstMac = event.dstMac
let registerData = try! register.serializedData()
var remoteAddresses: [SocketAddress] = []
if event.natIp > 0 && event.natPort > 0 {
let address = SDLUtil.int32ToIp(event.natIp)
if let remoteAddress = try? SocketAddress(ipAddress: address, port: Int(event.natPort)) {
remoteAddresses.append(remoteAddress)
}
}
if event.hasV6Info, let remoteAddress = try? await event.v6Info.socketAddress() {
remoteAddresses.append(remoteAddress)
}
return .init(
logMessage: "[SDLContext] sendRegisterEvent, ip: \(event)",
action: .sendRegister(data: registerData, remoteAddresses: remoteAddresses)
)
}
}