91 lines
2.9 KiB
Swift
91 lines
2.9 KiB
Swift
//
|
|
// IdentityStore.swift
|
|
// punchnet
|
|
//
|
|
// Created by 安礼成 on 2026/2/5.
|
|
//
|
|
import Foundation
|
|
import NIO
|
|
|
|
actor IdentityStore {
|
|
typealias IdentityID = UInt32
|
|
|
|
// 处理权限的请求问题
|
|
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: [IdentityID: IdentityRuleMap] = [:]
|
|
|
|
init(publisher: SnapshotPublisher<IdentitySnapshot>) {
|
|
self.publisher = publisher
|
|
}
|
|
|
|
// 提交权限请求
|
|
func policyRequest(using quicClient: SDLQUICClient?, request: inout SDLPolicyRequest) {
|
|
let identityId = request.srcIdentityID
|
|
guard let quicClient, !coolingDown.contains(identityId) else {
|
|
return
|
|
}
|
|
|
|
// 触发一次打洞
|
|
coolingDown.insert(identityId)
|
|
|
|
let version = self.versions[identityId, default: 1]
|
|
request.version = version
|
|
// 更新请求的版本问题
|
|
self.versions[identityId] = version + 1
|
|
// 发送请求
|
|
if let queryData = try? request.serializedData() {
|
|
quicClient.send(type: .policyRequest, data: queryData)
|
|
}
|
|
|
|
Task {
|
|
// 启动冷却期
|
|
try? await Task.sleep(for: .seconds(5))
|
|
self.endCooldown(for: identityId)
|
|
}
|
|
}
|
|
|
|
func apply(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)
|
|
|
|
SDLLogger.shared.log("[IdentitySession] get compile Snapshot rules nums: \(self.identityMap[id]?.ruleMap.count), success: \(self.identityMap[id]?.isAllow(proto: 1, port: 80))")
|
|
|
|
// 发布新的快照信息
|
|
let snapshot = compileSnapshot()
|
|
publisher.publish(snapshot)
|
|
}
|
|
|
|
private func compileSnapshot() -> IdentitySnapshot {
|
|
return IdentitySnapshot(identityMap: identityMap)
|
|
}
|
|
|
|
private func endCooldown(for key: UInt32) {
|
|
self.coolingDown.remove(key)
|
|
}
|
|
|
|
}
|