punchnet-macos/Tun/Policy/PolicyService.swift
2026-05-25 21:54:20 +08:00

77 lines
2.5 KiB
Swift

//
// PolicyService.swift
// punchnet
//
// Created by on 2026/5/19.
//
import Foundation
actor PolicyService {
//
private let policyRuleStore: PolicyRuleStore
nonisolated private let snapshotPublisher: SnapshotPublisher<PolicyRuleSnapshot>
nonisolated private let flowSessionTable = FlowSessionTable()
// identityId
let identityId: UInt32
init(identityId: UInt32) {
self.identityId = identityId
//
let snapshotPublisher = SnapshotPublisher(initial: PolicyRuleSnapshot.empty())
self.policyRuleStore = PolicyRuleStore(publisher: snapshotPublisher)
self.snapshotPublisher = snapshotPublisher
}
nonisolated func policyRuntime() -> PolicyRuntime {
return PolicyRuntime(policyRuleSnapshot: self.snapshotPublisher.current(), flowSessionTable: self.flowSessionTable)
}
nonisolated func recordOutboundFlow(ipPacket: IPPacketView) {
guard let flowSession = ipPacket.flowSession() else {
return
}
switch ipPacket.transportPacket {
case .tcp(_, _, let flags):
self.flowSessionTable.recordOutboundTCP(flowSession, flags: flags)
case .udp(_, let dstPort, _):
self.flowSessionTable.recordOutboundUDP(flowSession, isDNS: dstPort == 53)
default:
return
}
}
func makePolicyRequest(srcIdentityID: UInt32) async -> Data? {
return await self.policyRuleStore.makePolicyRequest(srcIdentityId: srcIdentityID, dstIdentityId: self.identityId)
}
func updatePolicy(superServiceProxy: SDLSuperServiceProxy) async {
let requests = await self.policyRuleStore.makeBatchPolicyRequests(dstIdentityID: self.identityId)
for request in requests {
await superServiceProxy.send(type: .policyRequest, data: request)
}
}
func applyPolicyResponse(_ policyResponse: SDLPolicyResponse) async {
guard policyResponse.dstIdentityID == self.identityId else {
SDLLogger.log("[PolicyService] ignore policy response, dstIdentityID mismatch: \(policyResponse.dstIdentityID), expected: \(self.identityId)", for: .debug)
return
}
await self.policyRuleStore.applyPolicyResponse(policyResponse)
}
func clear() async {
self.flowSessionTable.clear()
await self.policyRuleStore.clear()
}
deinit {
SDLLogger.log("[PolicyService] deinit")
}
}