// // PolicyRuleStore.swift // punchnet // 1. 需要增加规则基于轮训更新的逻辑 // Created by 安礼成 on 2026/2/5. // import Foundation import NIO actor PolicyRuleStore { // 处理权限的请求问题 nonisolated private let cooldown: Duration = .seconds(5) // identityId private var coolingDown: Set = [] // 处理各个请求的版本问题, map[identityId] = version private var versions: [UInt32: UInt32] = [:] nonisolated private let alloctor = ByteBufferAllocator() private let publisher: SnapshotPublisher private var ruleMapByIdentity: [UInt32: PolicyRuleMap] = [:] init(publisher: SnapshotPublisher) { self.publisher = publisher } func makeBatchPolicyRequests(dstIdentityID: UInt32) -> [Data] { return self.ruleMapByIdentity.keys.compactMap { identityId in var policyRequest = SDLPolicyRequest() policyRequest.srcIdentityID = identityId policyRequest.dstIdentityID = dstIdentityID policyRequest.version = self.nextVersion(identityId: identityId) return try? policyRequest.serializedData() } } func makePolicyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32) -> Data? { guard !coolingDown.contains(srcIdentityId) else { return nil } var policyRequest = SDLPolicyRequest() policyRequest.srcIdentityID = srcIdentityId policyRequest.dstIdentityID = dstIdentityId policyRequest.version = self.nextVersion(identityId: srcIdentityId) coolingDown.insert(srcIdentityId) Task { [weak self] in try? await Task.sleep(for: .seconds(5)) await self?.endCooldown(for: srcIdentityId) } return try? policyRequest.serializedData() } // 处理权限的响应 func applyPolicyResponse(_ policyResponse: SDLPolicyResponse) { let id = policyResponse.srcIdentityID let version = policyResponse.version guard self.ruleMapByIdentity[id] == nil || ((self.ruleMapByIdentity[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.ruleMapByIdentity[id] = PolicyRuleMap(version: version, ruleMap: ruleMap) // 发布新的快照信息 let snapshot = compileSnapshot() publisher.publish(snapshot) } func clear() { self.coolingDown.removeAll() self.versions.removeAll() self.ruleMapByIdentity.removeAll() self.publisher.publish(PolicyRuleSnapshot.empty()) } private func compileSnapshot() -> PolicyRuleSnapshot { return PolicyRuleSnapshot(ruleMapByIdentity: ruleMapByIdentity) } 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 } }