This commit is contained in:
anlicheng 2026-01-30 12:26:10 +08:00
parent df236d4c1f
commit e40a266b13
3 changed files with 49 additions and 12 deletions

View File

@ -5,27 +5,47 @@
// Created by on 2025/7/14. // Created by on 2025/7/14.
// //
import Foundation import Foundation
import Darwin
actor ArpServer { final class ArpServer {
private var known_macs: [UInt32:Data] = [:] private var known_macs: [UInt32:Data] = [:]
private var lock = os_unfair_lock()
init(known_macs: [UInt32:Data]) { init(known_macs: [UInt32:Data]) {
self.known_macs = known_macs self.known_macs = known_macs
} }
func query(ip: UInt32) -> Data? { func query(ip: UInt32) -> Data? {
return self.known_macs[ip] return withLock {
return self.known_macs[ip]
}
} }
func append(ip: UInt32, mac: Data) { func append(ip: UInt32, mac: Data) {
self.known_macs[ip] = mac withLock {
self.known_macs[ip] = mac
}
} }
func remove(ip: UInt32) { func remove(ip: UInt32) {
self.known_macs.removeValue(forKey: ip) withLock {
_ = self.known_macs.removeValue(forKey: ip)
}
} }
func clear() { func clear() {
self.known_macs = [:] withLock {
self.known_macs = [:]
}
} }
private func withLock<T>(_ body: () throws -> T) rethrows -> T {
os_unfair_lock_lock(&lock)
defer{
os_unfair_lock_unlock(&lock)
}
return try body()
}
} }

View File

@ -303,7 +303,7 @@ public class SDLContext {
case .natChanged(let natChangedEvent): case .natChanged(let natChangedEvent):
let dstMac = natChangedEvent.mac let dstMac = natChangedEvent.mac
self.logger.log("[SDLContext] natChangedEvent, dstMac: \(dstMac)", level: .info) self.logger.log("[SDLContext] natChangedEvent, dstMac: \(dstMac)", level: .info)
await sessionManager.removeSession(dstMac: dstMac) sessionManager.removeSession(dstMac: dstMac)
case .sendRegister(let sendRegisterEvent): case .sendRegister(let sendRegisterEvent):
self.logger.log("[SDLContext] sendRegisterEvent, ip: \(sendRegisterEvent)", level: .debug) self.logger.log("[SDLContext] sendRegisterEvent, ip: \(sendRegisterEvent)", level: .debug)
let address = SDLUtil.int32ToIp(sendRegisterEvent.natIp) let address = SDLUtil.int32ToIp(sendRegisterEvent.natIp)
@ -338,7 +338,7 @@ public class SDLContext {
self.udpHole?.send(type: .registerAck, data: try registerAck.serializedData(), remoteAddress: remoteAddress) self.udpHole?.send(type: .registerAck, data: try registerAck.serializedData(), remoteAddress: remoteAddress)
// , super-nodenatudpnat // , super-nodenatudpnat
let session = Session(dstMac: register.srcMac, natAddress: remoteAddress) let session = Session(dstMac: register.srcMac, natAddress: remoteAddress)
await self.sessionManager.addSession(session: session) self.sessionManager.addSession(session: session)
} else { } else {
self.logger.log("SDLContext didReadRegister get a invalid packet, because dst_ip not matched: \(register.dstMac)", level: .warning) self.logger.log("SDLContext didReadRegister get a invalid packet, because dst_ip not matched: \(register.dstMac)", level: .warning)
} }
@ -349,7 +349,7 @@ public class SDLContext {
let networkAddr = config.networkAddress let networkAddr = config.networkAddress
if registerAck.dstMac == networkAddr.mac && registerAck.networkID == networkAddr.networkId { if registerAck.dstMac == networkAddr.mac && registerAck.networkID == networkAddr.networkId {
let session = Session(dstMac: registerAck.srcMac, natAddress: remoteAddress) let session = Session(dstMac: registerAck.srcMac, natAddress: remoteAddress)
await self.sessionManager.addSession(session: session) self.sessionManager.addSession(session: session)
} else { } else {
self.logger.log("SDLContext didReadRegisterAck get a invalid packet, because dst_mac not matched: \(registerAck.dstMac)", level: .warning) self.logger.log("SDLContext didReadRegisterAck get a invalid packet, because dst_mac not matched: \(registerAck.dstMac)", level: .warning)
} }
@ -383,7 +383,7 @@ public class SDLContext {
await self.routeLayerPacket(dstMac: arpPacket.senderMAC, type: .arp, data: response.marshal()) await self.routeLayerPacket(dstMac: arpPacket.senderMAC, type: .arp, data: response.marshal())
case .response: case .response:
self.logger.log("[SDLContext] get arp response packet", level: .debug) self.logger.log("[SDLContext] get arp response packet", level: .debug)
await self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC) self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
} }
} else { } else {
self.logger.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug) self.logger.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug)
@ -469,7 +469,7 @@ public class SDLContext {
} }
// arpmac // arpmac
if let dstMac = await self.arpServer.query(ip: dstIp) { if let dstMac = self.arpServer.query(ip: dstIp) {
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data) await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
} }
else { else {
@ -504,7 +504,7 @@ public class SDLContext {
} }
else { else {
// session // session
if let session = await self.sessionManager.getSession(toAddress: dstMac) { if let session = self.sessionManager.getSession(toAddress: dstMac) {
self.logger.log("[SDLContext] send packet by session: \(session)", level: .debug) self.logger.log("[SDLContext] send packet by session: \(session)", level: .debug)
self.udpHole?.send(type: .data, data: data, remoteAddress: session.natAddress) self.udpHole?.send(type: .data, data: data, remoteAddress: session.natAddress)
await self.flowTracer.inc(num: data.count, type: .p2p) await self.flowTracer.inc(num: data.count, type: .p2p)

View File

@ -6,6 +6,7 @@
// //
import Foundation import Foundation
import NIOCore import NIOCore
import Darwin
struct Session { struct Session {
// ip, // ip,
@ -27,13 +28,19 @@ struct Session {
} }
} }
actor SessionManager { final class SessionManager {
private var sessions: [Data:Session] = [:] private var sessions: [Data:Session] = [:]
private var lock = os_unfair_lock()
// session // session
private let ttl: Int32 = 10 private let ttl: Int32 = 10
func getSession(toAddress: Data) -> Session? { func getSession(toAddress: Data) -> Session? {
os_unfair_lock_lock(&lock)
defer{
os_unfair_lock_unlock(&lock)
}
let timestamp = Int32(Date().timeIntervalSince1970) let timestamp = Int32(Date().timeIntervalSince1970)
if let session = self.sessions[toAddress] { if let session = self.sessions[toAddress] {
if session.lastTimestamp >= timestamp + ttl { if session.lastTimestamp >= timestamp + ttl {
@ -47,10 +54,20 @@ actor SessionManager {
} }
func addSession(session: Session) { func addSession(session: Session) {
os_unfair_lock_lock(&lock)
defer{
os_unfair_lock_unlock(&lock)
}
self.sessions[session.dstMac] = session self.sessions[session.dstMac] = session
} }
func removeSession(dstMac: Data) { func removeSession(dstMac: Data) {
os_unfair_lock_lock(&lock)
defer{
os_unfair_lock_unlock(&lock)
}
self.sessions.removeValue(forKey: dstMac) self.sessions.removeValue(forKey: dstMac)
} }