// // PolicyRuntime.swift // Tun // // Created by Codex on 2026/5/21. // import Foundation struct PolicyRuntime: @unchecked Sendable { enum InboundDecision { case allow case deny case missingPolicy } private let policyRuleSnapshot: PolicyRuleSnapshot private let flowSessionTable: FlowSessionTable init(policyRuleSnapshot: PolicyRuleSnapshot, flowSessionTable: FlowSessionTable) { self.policyRuleSnapshot = policyRuleSnapshot self.flowSessionTable = flowSessionTable } func evaluateInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> InboundDecision { if let reverseFlowSession = ipPacket.flowSession()?.reverse(), self.flowSessionTable.hasSession(reverseFlowSession) { self.flowSessionTable.updateSession(reverseFlowSession) return .allow } if case .icmp = ipPacket.transportPacket { return .allow } guard let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID) else { return .missingPolicy } return self.isAllowedByRule(ruleMap: ruleMap, ipPacket: ipPacket) ? .allow : .deny } private func isAllowedByRule(ruleMap: PolicyRuleMap, ipPacket: IPPacket) -> Bool { let proto = ipPacket.header.proto switch ipPacket.transportPacket { case .tcp(let tcpPacket): return ruleMap.isAllow(proto: proto, port: tcpPacket.header.dstPort) case .udp(let udpPacket): return ruleMap.isAllow(proto: proto, port: udpPacket.dstPort) default: return false } } }