punchnet-macos/Tun/Punchnet/Actors/SDLPuncherActor.swift
2026-04-10 18:23:12 +08:00

87 lines
2.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// SDLPuncherActor.swift
// Tun
//
// Created by on 2026/1/7.
//
import Foundation
import NIOCore
actor SDLPuncherActor {
// 10
nonisolated private let cooldownInterval: TimeInterval = 10
struct RequestContext {
let expireAt: Date
let request: RegisterRequest
func isExpired() -> Bool {
return expireAt < Date()
}
}
// dstMac
private var pendingRequests: [Data: RequestContext] = [:]
struct RegisterRequest {
let srcMac: Data
let dstMac: Data
let networkId: UInt32
}
func submitRegisterRequest(quicClient: SDLQUICClient?, request: RegisterRequest) {
guard let quicClient else {
return
}
//
let dstMac = request.dstMac
guard self.isRequestExpired(dstMac: dstMac) else {
return
}
self.pendingRequests[dstMac] = .init(expireAt: Date().addingTimeInterval(cooldownInterval), request: request)
//
var queryInfo = SDLQueryInfo()
queryInfo.dstMac = request.dstMac
if let queryData = try? queryInfo.serializedData() {
quicClient.send(type: .queryInfo, data: queryData)
}
}
func handlePeerInfo(using udpHole: SDLUDPHole?, peerInfo: SDLPeerInfo) async {
// ;
guard let requestContext = pendingRequests.removeValue(forKey: peerInfo.dstMac) else {
return
}
//
guard let udpHole, peerInfo.hasV4Info else {
return
}
if let remoteAddress = try? await peerInfo.v4Info.socketAddress() {
SDLLogger.log("[SDLContext] hole sock address: \(remoteAddress)", for: .punchnet)
// register
var register = SDLRegister()
register.networkID = requestContext.request.networkId
register.srcMac = requestContext.request.srcMac
register.dstMac = requestContext.request.dstMac
if let registerData = try? register.serializedData() {
udpHole.send(type: .register, data: registerData, remoteAddress: remoteAddress)
}
}
}
//
func isRequestExpired(dstMac: Data) -> Bool {
if let context = pendingRequests[dstMac] {
return context.isExpired()
}
return true
}
}