增加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 accessToken: String
let identityId: UInt32
let acl: ACL
var acl: ACL
var exitNode: ExitNode?
@ -220,5 +220,24 @@ extension SDLConfiguration {
return UInt16(port)
})
}
}
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):
//
await self.policyService.applyPolicyResponse(policyResponse)
case .exposedServiceResponse(let response):
await self.applyExposedServiceResponse(response)
case .arpResponse(let arpResponse):
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
await self.arpResolver.handleArpResponse(arpResponse: arpResponse)
@ -416,6 +418,8 @@ extension SDLContextActor {
for remoteAddress in remoteAddresses {
await self.sendPeerPacket(type: .register, data: registerData, remoteAddress: remoteAddress)
}
case .requestExposedService:
await self.requestExposedService()
case .shutdown(let message):
self.publishTunnelEvent(message: message)
@ -444,6 +448,22 @@ extension SDLContextActor {
await self.superServiceProxy.send(type: .registerSuper, data: registerSuperData)
}
}
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
}
}

View File

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

View File

@ -7,28 +7,37 @@
import Foundation
final class ExposedServiceSnapshot: Snapshot {
let acl: SDLConfiguration.ACL
init(acl: SDLConfiguration.ACL) {
self.acl = acl
}
}
actor PolicyService {
//
private let policyRuleStore: PolicyRuleStore
nonisolated private let snapshotPublisher: SnapshotPublisher<PolicyRuleSnapshot>
nonisolated private let aclPublisher: SnapshotPublisher<ExposedServiceSnapshot>
nonisolated private let flowSessionTable = FlowSessionTable()
// identityId
let identityId: UInt32
private let acl: SDLConfiguration.ACL
private var latestExposedServiceRequestVersion: UInt32 = 0
init(identityId: UInt32, acl: SDLConfiguration.ACL) {
self.identityId = identityId
self.acl = acl
//
let snapshotPublisher = SnapshotPublisher(initial: PolicyRuleSnapshot.empty())
self.policyRuleStore = PolicyRuleStore(publisher: snapshotPublisher)
self.snapshotPublisher = snapshotPublisher
self.aclPublisher = SnapshotPublisher(initial: ExposedServiceSnapshot(acl: acl))
}
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) {
@ -65,6 +74,26 @@ actor PolicyService {
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 {
self.flowSessionTable.clear()
@ -74,5 +103,12 @@ actor 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)}
}
var exposedServiceChanged: SDLEvent.ExposedServiceChanged {
get {
if case .exposedServiceChanged(let v)? = event {return v}
return SDLEvent.ExposedServiceChanged()
}
set {event = .exposedServiceChanged(newValue)}
}
var unknownFields = SwiftProtobuf.UnknownStorage()
enum OneOf_Event: Equatable, Sendable {
case natChanged(SDLEvent.NatChanged)
case sendRegister(SDLEvent.SendRegister)
case shutdown(SDLEvent.NetworkShutdown)
case exposedServiceChanged(SDLEvent.ExposedServiceChanged)
}
@ -421,6 +430,16 @@ struct SDLEvent: Sendable {
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 {
// 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"),
2: .standard(proto: "send_register"),
3: .same(proto: "shutdown"),
4: .standard(proto: "exposed_service_changed"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -1417,6 +1437,19 @@ extension SDLEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
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
}
}
@ -1440,6 +1473,10 @@ extension SDLEvent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
guard case .shutdown(let v)? = self.event else { preconditionFailure() }
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
}
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 {
static let protoMessageName: String = SDLEvent.protoMessageName + ".NetworkShutdown"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [

View File

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

View File

@ -47,6 +47,12 @@ enum SDLSuperCodec {
return nil
}
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:
guard let bytes = buffer.readBytes(length: buffer.readableBytes),
let arpResponse = try? SDLArpResponse(serializedBytes: bytes) else {