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
}
// , superClient
func batUpdatePolicy(using superClient: SDLSuperClient?, dstIdentityID: UInt32) async {
guard let superClient else {
return
}
for identityId in self.identityMap.keys {
var policyRequest = SDLPolicyRequest()
policyRequest.srcIdentityID = identityId
policyRequest.dstIdentityID = dstIdentityID
policyRequest.version = self.nextVersion(identityId: identityId)
//
if let queryData = try? policyRequest.serializedData() {
await superClient.send(type: .policyRequest, data: queryData)
}
}
}
//
func policyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32, using superClient: SDLSuperClient?) async {
guard let superClient, !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() {
await superClient.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
}
}