增加policy的更新

This commit is contained in:
anlicheng 2026-05-26 00:47:03 +08:00
parent 0edf2a34c3
commit 4bf1a7160f
7 changed files with 152 additions and 5 deletions

View File

@ -73,7 +73,7 @@ public class SDLConfiguration {
let hostname: String let hostname: String
let accessToken: String let accessToken: String
let identityId: UInt32 let identityId: UInt32
let acl: ACL var acl: ACL
var exitNode: ExitNode? var exitNode: ExitNode?
@ -222,3 +222,22 @@ extension SDLConfiguration {
} }
} }
extension SDLConfiguration.ACL {
init(response: SDLExposedServiceResponse) {
self.init(
tcpPorts: Self.parsePorts(response.tcpPorts),
udpPorts: Self.parsePorts(response.udpPorts)
)
}
private static func parsePorts(_ ports: [UInt32]) -> Set<UInt16> {
return Set(ports.compactMap { port in
guard port > 0, port <= UInt32(UInt16.max) else {
return nil
}
return UInt16(port)
})
}
}

View File

@ -304,6 +304,8 @@ extension SDLContextActor {
case .policyReponse(let policyResponse): case .policyReponse(let policyResponse):
// //
await self.policyService.applyPolicyResponse(policyResponse) await self.policyService.applyPolicyResponse(policyResponse)
case .exposedServiceResponse(let response):
await self.applyExposedServiceResponse(response)
case .arpResponse(let arpResponse): case .arpResponse(let arpResponse):
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)") SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
await self.arpResolver.handleArpResponse(arpResponse: arpResponse) await self.arpResolver.handleArpResponse(arpResponse: arpResponse)
@ -416,6 +418,8 @@ extension SDLContextActor {
for remoteAddress in remoteAddresses { for remoteAddress in remoteAddresses {
await self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress) await self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
} }
case .requestExposedService:
await self.requestExposedService()
case .shutdown(let message): case .shutdown(let message):
self.publishTunnelEvent(message: message) self.publishTunnelEvent(message: message)
@ -445,6 +449,22 @@ extension SDLContextActor {
} }
} }
private func requestExposedService() async {
guard let requestData = await self.policyService.makeExposedServiceRequest() else {
return
}
await self.superServiceProxy.send(type: .exposedServiceRequest, data: requestData)
}
private func applyExposedServiceResponse(_ response: SDLExposedServiceResponse) async {
guard let acl = await self.policyService.applyExposedServiceResponse(response) else {
return
}
self.config.acl = acl
}
} }
// MARK: DNS service events // MARK: DNS service events

View File

@ -12,6 +12,7 @@ final class SDLSuperEventProcessor {
enum ProcessingAction { enum ProcessingAction {
case removeSession(dstMac: Data) case removeSession(dstMac: Data)
case sendRegister(data: Data, remoteAddresses: [SocketAddress]) case sendRegister(data: Data, remoteAddresses: [SocketAddress])
case requestExposedService
case shutdown(message: String) case shutdown(message: String)
case none case none
} }
@ -37,6 +38,11 @@ final class SDLSuperEventProcessor {
) )
case .sendRegister(let sendRegisterEvent): case .sendRegister(let sendRegisterEvent):
return await self.makeSendRegisterPlan(sendRegisterEvent) return await self.makeSendRegisterPlan(sendRegisterEvent)
case .exposedServiceChanged:
return .init(
logMessage: "[SDLContext] exposedServiceChanged event",
action: .requestExposedService
)
case .shutdown(let shutdownEvent): case .shutdown(let shutdownEvent):
return .init(logMessage: nil, action: .shutdown(message: shutdownEvent.message)) return .init(logMessage: nil, action: .shutdown(message: shutdownEvent.message))
case .none: case .none:

View File

@ -7,28 +7,37 @@
import Foundation import Foundation
final class ExposedServiceSnapshot: Snapshot {
let acl: SDLConfiguration.ACL
init(acl: SDLConfiguration.ACL) {
self.acl = acl
}
}
actor PolicyService { actor PolicyService {
// //
private let policyRuleStore: PolicyRuleStore private let policyRuleStore: PolicyRuleStore
nonisolated private let snapshotPublisher: SnapshotPublisher<PolicyRuleSnapshot> nonisolated private let snapshotPublisher: SnapshotPublisher<PolicyRuleSnapshot>
nonisolated private let aclPublisher: SnapshotPublisher<ExposedServiceSnapshot>
nonisolated private let flowSessionTable = FlowSessionTable() nonisolated private let flowSessionTable = FlowSessionTable()
// identityId // identityId
let identityId: UInt32 let identityId: UInt32
private let acl: SDLConfiguration.ACL private var latestExposedServiceRequestVersion: UInt32 = 0
init(identityId: UInt32, acl: SDLConfiguration.ACL) { init(identityId: UInt32, acl: SDLConfiguration.ACL) {
self.identityId = identityId self.identityId = identityId
self.acl = acl
// //
let snapshotPublisher = SnapshotPublisher(initial: PolicyRuleSnapshot.empty()) let snapshotPublisher = SnapshotPublisher(initial: PolicyRuleSnapshot.empty())
self.policyRuleStore = PolicyRuleStore(publisher: snapshotPublisher) self.policyRuleStore = PolicyRuleStore(publisher: snapshotPublisher)
self.snapshotPublisher = snapshotPublisher self.snapshotPublisher = snapshotPublisher
self.aclPublisher = SnapshotPublisher(initial: ExposedServiceSnapshot(acl: acl))
} }
nonisolated func policyRuntime() -> PolicyRuntime { nonisolated func policyRuntime() -> PolicyRuntime {
return PolicyRuntime(policyRuleSnapshot: self.snapshotPublisher.current(), flowSessionTable: self.flowSessionTable, acl: self.acl) return PolicyRuntime(policyRuleSnapshot: self.snapshotPublisher.current(), flowSessionTable: self.flowSessionTable, acl: self.aclPublisher.current().acl)
} }
nonisolated func recordOutboundFlow(ipPacket: IPPacketView) { nonisolated func recordOutboundFlow(ipPacket: IPPacketView) {
@ -66,6 +75,26 @@ actor PolicyService {
await self.policyRuleStore.applyPolicyResponse(policyResponse) await self.policyRuleStore.applyPolicyResponse(policyResponse)
} }
func makeExposedServiceRequest() -> Data? {
var request = SDLExposedServiceRequest()
self.latestExposedServiceRequestVersion = Self.nextVersion(after: self.latestExposedServiceRequestVersion)
request.version = self.latestExposedServiceRequestVersion
SDLLogger.log("[PolicyService] make exposed service request, version: \(request.version)", for: .debug)
return try? request.serializedData()
}
func applyExposedServiceResponse(_ response: SDLExposedServiceResponse) -> SDLConfiguration.ACL? {
guard response.version == self.latestExposedServiceRequestVersion else {
SDLLogger.log("[PolicyService] ignore exposed service response, version: \(response.version), latest request version: \(self.latestExposedServiceRequestVersion)", for: .debug)
return nil
}
let acl = SDLConfiguration.ACL(response: response)
self.aclPublisher.publish(ExposedServiceSnapshot(acl: acl))
SDLLogger.log("[PolicyService] apply exposed service response, version: \(response.version), tcp: \(acl.tcpPorts.count), udp: \(acl.udpPorts.count)", for: .debug)
return acl
}
func clear() async { func clear() async {
self.flowSessionTable.clear() self.flowSessionTable.clear()
await self.policyRuleStore.clear() await self.policyRuleStore.clear()
@ -75,4 +104,11 @@ actor PolicyService {
SDLLogger.log("[PolicyService] deinit") SDLLogger.log("[PolicyService] deinit")
} }
private static func nextVersion(after version: UInt32) -> UInt32 {
if version == UInt32.max {
return 1
}
return version + 1
}
} }

View File

@ -367,12 +367,21 @@ struct SDLEvent: Sendable {
set {event = .shutdown(newValue)} set {event = .shutdown(newValue)}
} }
var exposedServiceChanged: SDLEvent.ExposedServiceChanged {
get {
if case .exposedServiceChanged(let v)? = event {return v}
return SDLEvent.ExposedServiceChanged()
}
set {event = .exposedServiceChanged(newValue)}
}
var unknownFields = SwiftProtobuf.UnknownStorage() var unknownFields = SwiftProtobuf.UnknownStorage()
enum OneOf_Event: Equatable, Sendable { enum OneOf_Event: Equatable, Sendable {
case natChanged(SDLEvent.NatChanged) case natChanged(SDLEvent.NatChanged)
case sendRegister(SDLEvent.SendRegister) case sendRegister(SDLEvent.SendRegister)
case shutdown(SDLEvent.NetworkShutdown) case shutdown(SDLEvent.NetworkShutdown)
case exposedServiceChanged(SDLEvent.ExposedServiceChanged)
} }
@ -421,6 +430,16 @@ struct SDLEvent: Sendable {
fileprivate var _v6Info: SDLV6Info? = nil fileprivate var _v6Info: SDLV6Info? = nil
} }
struct ExposedServiceChanged: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
/// ///
struct NetworkShutdown: Sendable { struct NetworkShutdown: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the // SwiftProtobuf.Message conformance is added in an extension below. See the
@ -1370,6 +1389,7 @@ extension SDLEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
1: .standard(proto: "nat_changed"), 1: .standard(proto: "nat_changed"),
2: .standard(proto: "send_register"), 2: .standard(proto: "send_register"),
3: .same(proto: "shutdown"), 3: .same(proto: "shutdown"),
4: .standard(proto: "exposed_service_changed"),
] ]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1417,6 +1437,19 @@ extension SDLEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
self.event = .shutdown(v) self.event = .shutdown(v)
} }
}() }()
case 4: try {
var v: SDLEvent.ExposedServiceChanged?
var hadOneofValue = false
if let current = self.event {
hadOneofValue = true
if case .exposedServiceChanged(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.event = .exposedServiceChanged(v)
}
}()
default: break default: break
} }
} }
@ -1440,6 +1473,10 @@ extension SDLEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
guard case .shutdown(let v)? = self.event else { preconditionFailure() } guard case .shutdown(let v)? = self.event else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 3) try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
}() }()
case .exposedServiceChanged?: try {
guard case .exposedServiceChanged(let v)? = self.event else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
}()
case nil: break case nil: break
} }
try unknownFields.traverse(visitor: &visitor) try unknownFields.traverse(visitor: &visitor)
@ -1550,6 +1587,25 @@ extension SDLEvent.SendRegister: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
} }
} }
extension SDLEvent.ExposedServiceChanged: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = SDLEvent.protoMessageName + ".ExposedServiceChanged"
static let _protobuf_nameMap = SwiftProtobuf._NameMap()
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
// Load everything into unknown fields
while try decoder.nextFieldNumber() != nil {}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: SDLEvent.ExposedServiceChanged, rhs: SDLEvent.ExposedServiceChanged) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension SDLEvent.NetworkShutdown: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { extension SDLEvent.NetworkShutdown: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = SDLEvent.protoMessageName + ".NetworkShutdown" static let protoMessageName: String = SDLEvent.protoMessageName + ".NetworkShutdown"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ static let _protobuf_nameMap: SwiftProtobuf._NameMap = [

View File

@ -45,6 +45,9 @@ enum SDLPacketType: UInt8 {
case policyRequest = 0xb0 case policyRequest = 0xb0
case policyResponse = 0xb1 case policyResponse = 0xb1
case exposedServiceRequest = 0xb2
case exposedServiceResponse = 0xb3
// //
case welcome = 0x4F case welcome = 0x4F
@ -137,6 +140,7 @@ enum SDLQUICInboundMessage {
case peerInfo(SDLPeerInfo) case peerInfo(SDLPeerInfo)
case event(SDLEvent) case event(SDLEvent)
case policyReponse(SDLPolicyResponse) case policyReponse(SDLPolicyResponse)
case exposedServiceResponse(SDLExposedServiceResponse)
case arpResponse(SDLArpResponse) case arpResponse(SDLArpResponse)
} }

View File

@ -47,6 +47,12 @@ enum SDLSuperCodec {
return nil return nil
} }
return .policyReponse(policyResponse) return .policyReponse(policyResponse)
case .exposedServiceResponse:
guard let bytes = buffer.readBytes(length: buffer.readableBytes),
let response = try? SDLExposedServiceResponse(serializedBytes: bytes) else {
return nil
}
return .exposedServiceResponse(response)
case .arpResponse: case .arpResponse:
guard let bytes = buffer.readBytes(length: buffer.readableBytes), guard let bytes = buffer.readBytes(length: buffer.readableBytes),
let arpResponse = try? SDLArpResponse(serializedBytes: bytes) else { let arpResponse = try? SDLArpResponse(serializedBytes: bytes) else {