punchnet-macos/Tun/Punchnet/Policy/IdentityStore.swift

114 lines
3.8 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.

//
// IdentityStore.swift
// punchnet
// 1.
// Created by on 2026/2/5.
//
import Foundation
import NIO
actor IdentityStore {
//
nonisolated private let cooldown: Duration = .seconds(5)
// identityId
private var coolingDown: Set<UInt32> = []
// , map[identityId] = version
private var versions: [UInt32: UInt32] = [:]
nonisolated private let alloctor = ByteBufferAllocator()
private let publisher: SnapshotPublisher<IdentitySnapshot>
private var identityMap: [UInt32: IdentityRuleMap] = [:]
init(publisher: SnapshotPublisher<IdentitySnapshot>) {
self.publisher = publisher
}
// , quicClient
func batUpdatePolicy(using quicClient: SDLQUICClient?, dstIdentityID: UInt32) {
guard let quicClient else {
return
}
self.identityMap.keys.forEach { identityId in
var policyRequest = SDLPolicyRequest()
policyRequest.srcIdentityID = identityId
policyRequest.dstIdentityID = dstIdentityID
policyRequest.version = self.nextVersion(identityId: identityId)
//
if let queryData = try? policyRequest.serializedData() {
quicClient.send(type: .policyRequest, data: queryData)
}
}
}
//
func policyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32, using quicClient: SDLQUICClient?) {
guard let quicClient, !coolingDown.contains(srcIdentityId) else {
return
}
var policyRequest = SDLPolicyRequest()
policyRequest.srcIdentityID = srcIdentityId
policyRequest.dstIdentityID = dstIdentityId
policyRequest.version = self.nextVersion(identityId: srcIdentityId)
//
coolingDown.insert(srcIdentityId)
//
if let queryData = try? policyRequest.serializedData() {
quicClient.send(type: .policyRequest, data: queryData)
}
Task {
//
try? await Task.sleep(for: .seconds(5))
self.endCooldown(for: srcIdentityId)
}
}
//
func applyPolicyResponse(_ policyResponse: SDLPolicyResponse) {
let id = policyResponse.srcIdentityID
let version = policyResponse.version
guard self.identityMap[id] == nil || ((self.identityMap[id]?.version ?? 0) < version) else {
return
}
//
var buffer = alloctor.buffer(bytes: policyResponse.rules)
var ruleMap: [UInt8: [UInt16: Bool]] = [:]
while true {
guard let proto = buffer.readInteger(endianness: .big, as: UInt8.self),
let port = buffer.readInteger(endianness: .big, as: UInt16.self) else {
break
}
ruleMap[proto, default: [:]][port] = true
}
self.identityMap[id] = IdentityRuleMap(version: version, ruleMap: ruleMap)
//
let snapshot = compileSnapshot()
publisher.publish(snapshot)
}
private func compileSnapshot() -> IdentitySnapshot {
return IdentitySnapshot(identityMap: identityMap)
}
private func endCooldown(for key: UInt32) {
self.coolingDown.remove(key)
}
private func nextVersion(identityId: UInt32) -> UInt32 {
let version = self.versions[identityId, default: 1]
//
self.versions[identityId] = version + 1
return version
}
}