fix arpServer
This commit is contained in:
parent
48bb011e54
commit
cb33d81428
@ -56,7 +56,7 @@ actor SDLContextActor {
|
|||||||
private var readTask: Task<(), Never>?
|
private var readTask: Task<(), Never>?
|
||||||
|
|
||||||
nonisolated private let sessionManager = SessionManager()
|
nonisolated private let sessionManager = SessionManager()
|
||||||
nonisolated private let arpServer = ArpServer()
|
nonisolated private let arpServer: ArpServer
|
||||||
|
|
||||||
// 网络状态变化的健康
|
// 网络状态变化的健康
|
||||||
private var monitor: SDLNetworkMonitor?
|
private var monitor: SDLNetworkMonitor?
|
||||||
@ -93,6 +93,8 @@ actor SDLContextActor {
|
|||||||
self.puncherActor = SDLPuncherActor()
|
self.puncherActor = SDLPuncherActor()
|
||||||
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
||||||
|
|
||||||
|
self.arpServer = ArpServer()
|
||||||
|
|
||||||
// 权限控制
|
// 权限控制
|
||||||
let snapshotPublisher = SnapshotPublisher(initial: IdentitySnapshot.empty())
|
let snapshotPublisher = SnapshotPublisher(initial: IdentitySnapshot.empty())
|
||||||
self.identifyStore = IdentityStore(publisher: snapshotPublisher)
|
self.identifyStore = IdentityStore(publisher: snapshotPublisher)
|
||||||
@ -102,6 +104,9 @@ actor SDLContextActor {
|
|||||||
public func start() async {
|
public func start() async {
|
||||||
self.startMonitor()
|
self.startMonitor()
|
||||||
|
|
||||||
|
// 启动arp的定时清理任务
|
||||||
|
await self.arpServer.start()
|
||||||
|
|
||||||
// 启动puncher的定期扫描任务
|
// 启动puncher的定期扫描任务
|
||||||
await self.puncherActor.start()
|
await self.puncherActor.start()
|
||||||
|
|
||||||
@ -172,7 +177,7 @@ actor SDLContextActor {
|
|||||||
await self.identifyStore.applyPolicyResponse(policyResponse)
|
await self.identifyStore.applyPolicyResponse(policyResponse)
|
||||||
case .arpResponse(let arpResponse):
|
case .arpResponse(let arpResponse):
|
||||||
SDLLogger.shared.log("[SDLContext] get arp response: \(arpResponse)")
|
SDLLogger.shared.log("[SDLContext] get arp response: \(arpResponse)")
|
||||||
self.arpServer.handleArpResponse(arpResponse: arpResponse)
|
await self.arpServer.handleArpResponse(arpResponse: arpResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -536,7 +541,7 @@ actor SDLContextActor {
|
|||||||
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:
|
||||||
SDLLogger.shared.log("[SDLContext] get arp response packet", level: .debug)
|
SDLLogger.shared.log("[SDLContext] get arp response packet", level: .debug)
|
||||||
self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
|
await self.arpServer.append(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SDLLogger.shared.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug)
|
SDLLogger.shared.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(networkAddr.ip))", level: .debug)
|
||||||
@ -660,7 +665,7 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查找arp缓存中是否有目标mac地址
|
// 查找arp缓存中是否有目标mac地址
|
||||||
if let dstMac = self.arpServer.query(ip: dstIp) {
|
if let dstMac = await self.arpServer.query(ip: dstIp) {
|
||||||
SDLLogger.shared.log("[SDLContext] dstIp: \(dstIp.asIpAddress()), dst_mac is: \(SDLUtil.formatMacAddress(mac: dstMac))", level: .debug)
|
SDLLogger.shared.log("[SDLContext] dstIp: \(dstIp.asIpAddress()), dst_mac is: \(SDLUtil.formatMacAddress(mac: dstMac))", level: .debug)
|
||||||
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
|
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
|
||||||
}
|
}
|
||||||
@ -670,7 +675,7 @@ actor SDLContextActor {
|
|||||||
// let arpReqeust = ARPPacket.arpRequest(senderIP: networkAddr.ip, senderMAC: networkAddr.mac, targetIP: dstIp)
|
// let arpReqeust = ARPPacket.arpRequest(senderIP: networkAddr.ip, senderMAC: networkAddr.mac, targetIP: dstIp)
|
||||||
// await self.routeLayerPacket(dstMac: ARPPacket.broadcastMac , type: .arp, data: arpReqeust.marshal())
|
// await self.routeLayerPacket(dstMac: ARPPacket.broadcastMac , type: .arp, data: arpReqeust.marshal())
|
||||||
|
|
||||||
try? self.arpServer.arpRequest(targetIp: dstIp, use: self.quicClient)
|
try? await self.arpServer.arpRequest(targetIp: dstIp, use: self.quicClient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,35 +1,46 @@
|
|||||||
//
|
//
|
||||||
// ArpServer.swift
|
// ArpServer.swift
|
||||||
// sdlan
|
// sdlan
|
||||||
//
|
// 1. 通过ip地址查找mac地址
|
||||||
|
// 2. 要限制单位时间内,同一个ip的查询
|
||||||
// Created by 安礼成 on 2025/7/14.
|
// Created by 安礼成 on 2025/7/14.
|
||||||
//
|
//
|
||||||
import Foundation
|
import Foundation
|
||||||
import Darwin
|
import Darwin
|
||||||
|
|
||||||
final class ArpServer {
|
actor ArpServer {
|
||||||
// 增加缓存时间逻辑
|
// 增加缓存时间逻辑
|
||||||
struct ArpEntry {
|
struct ArpEntry {
|
||||||
var mac: Data
|
var mac: Data
|
||||||
var expireTime: TimeInterval
|
var expireTime: TimeInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
private let locker = NSLock()
|
private var coolingDown: [UInt32: Date] = [:]
|
||||||
|
|
||||||
private var packetId: UInt32 = 1
|
private var packetId: UInt32 = 1
|
||||||
private var known_macs: [UInt32: ArpEntry] = [:]
|
private var known_macs: [UInt32: ArpEntry] = [:]
|
||||||
private let arpTTL: TimeInterval
|
private let arpTTL: TimeInterval
|
||||||
|
|
||||||
|
private var cleanupTask: Task<Void, Never>?
|
||||||
|
|
||||||
init(arpTTL: TimeInterval = 300) {
|
init(arpTTL: TimeInterval = 300) {
|
||||||
self.arpTTL = arpTTL
|
self.arpTTL = arpTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
func query(ip: UInt32) -> Data? {
|
func start() {
|
||||||
locker.lock()
|
guard self.cleanupTask == nil else {
|
||||||
defer {
|
return
|
||||||
locker.unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.cleanupTask = Task {
|
||||||
|
while !Task.isCancelled {
|
||||||
|
try? await Task.sleep(for: .seconds(1))
|
||||||
|
self.cleanup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func query(ip: UInt32) -> Data? {
|
||||||
guard let entry = known_macs[ip] else {
|
guard let entry = known_macs[ip] else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -43,47 +54,32 @@ final class ArpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func append(ip: UInt32, mac: Data) {
|
func append(ip: UInt32, mac: Data) {
|
||||||
locker.lock()
|
|
||||||
defer {
|
|
||||||
locker.unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
let expireAt = Date().timeIntervalSince1970 + arpTTL
|
let expireAt = Date().timeIntervalSince1970 + arpTTL
|
||||||
self.known_macs[ip] = ArpEntry(mac: mac, expireTime: expireAt)
|
self.known_macs[ip] = ArpEntry(mac: mac, expireTime: expireAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func remove(ip: UInt32) {
|
func remove(ip: UInt32) {
|
||||||
locker.lock()
|
|
||||||
defer {
|
|
||||||
locker.unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
self.known_macs.removeValue(forKey: ip)
|
self.known_macs.removeValue(forKey: ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dropMacs(macs: [Data]) {
|
func dropMacs(macs: [Data]) {
|
||||||
locker.lock()
|
|
||||||
defer {
|
|
||||||
locker.unlock()
|
|
||||||
}
|
|
||||||
self.known_macs = self.known_macs.filter { !macs.contains($0.value.mac) }
|
self.known_macs = self.known_macs.filter { !macs.contains($0.value.mac) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func clear() {
|
func clear() {
|
||||||
locker.lock()
|
|
||||||
self.known_macs = [:]
|
self.known_macs = [:]
|
||||||
locker.unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func arpRequest(targetIp: UInt32, use quicClient: SDLQUICClient?) throws {
|
func arpRequest(targetIp: UInt32, use quicClient: SDLQUICClient?) throws {
|
||||||
guard let quicClient else {
|
guard let quicClient, self.coolingDown[targetIp] == nil else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
locker.lock()
|
|
||||||
let pktID = self.packetId
|
let pktID = self.packetId
|
||||||
self.packetId += 1
|
self.packetId &+= 1
|
||||||
locker.unlock()
|
|
||||||
|
// 单位时间内指允许提交一次
|
||||||
|
self.coolingDown[targetIp] = Date().addingTimeInterval(3)
|
||||||
|
|
||||||
// 进行arp查询
|
// 进行arp查询
|
||||||
var arpRequest = SDLArpRequest()
|
var arpRequest = SDLArpRequest()
|
||||||
@ -98,10 +94,17 @@ final class ArpServer {
|
|||||||
let targetMac = arpResponse.targetMac
|
let targetMac = arpResponse.targetMac
|
||||||
if !targetMac.isEmpty {
|
if !targetMac.isEmpty {
|
||||||
let expireAt = Date().timeIntervalSince1970 + arpTTL
|
let expireAt = Date().timeIntervalSince1970 + arpTTL
|
||||||
locker.lock()
|
|
||||||
self.known_macs[targetIp] = ArpEntry(mac: targetMac, expireTime: expireAt)
|
self.known_macs[targetIp] = ArpEntry(mac: targetMac, expireTime: expireAt)
|
||||||
locker.unlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func cleanup() {
|
||||||
|
let now = Date()
|
||||||
|
self.coolingDown = self.coolingDown.filter { $0.value > now }
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.cleanupTask?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,9 +87,12 @@ enum SDLNAKErrorCode: UInt8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension SDLV4Info {
|
extension SDLV4Info {
|
||||||
func socketAddress() async throws -> SocketAddress {
|
func socketAddress() async throws -> SocketAddress? {
|
||||||
let address = "\(v4[0]).\(v4[1]).\(v4[2]).\(v4[3])"
|
guard self.v4.count == 4 else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let address = "\(v4[0]).\(v4[1]).\(v4[2]).\(v4[3])"
|
||||||
return try await SDLAddressResolver.shared.resolve(host: address, port: Int(port))
|
return try await SDLAddressResolver.shared.resolve(host: address, port: Int(port))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user