fix Tun/Punchnet/SDLIPV6AssistClient.swift

This commit is contained in:
anlicheng 2026-04-16 17:08:32 +08:00
parent 66721ce7b1
commit 67110d4e60
2 changed files with 64 additions and 48 deletions

View File

@ -52,12 +52,12 @@ struct SDLV6Info: @unchecked Sendable {
} }
/// ipv6 assist /// ipv6 assist
struct SDLV6AssistProbe: @unchecked Sendable { struct SDLV6AssistProbe: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the // SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages. // methods supported on all messages.
var assistToken: Data = Data() var pktID: UInt32 = 0
var unknownFields = SwiftProtobuf.UnknownStorage() var unknownFields = SwiftProtobuf.UnknownStorage()
@ -69,6 +69,8 @@ struct SDLV6AssistProbeReply: Sendable {
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages. // methods supported on all messages.
var pktID: UInt32 = 0
var v6Info: SDLV6Info { var v6Info: SDLV6Info {
get {return _v6Info ?? SDLV6Info()} get {return _v6Info ?? SDLV6Info()}
set {_v6Info = newValue} set {_v6Info = newValue}
@ -85,7 +87,7 @@ struct SDLV6AssistProbeReply: Sendable {
fileprivate var _v6Info: SDLV6Info? = nil fileprivate var _v6Info: SDLV6Info? = nil
} }
struct SDLWelcome: @unchecked Sendable { struct SDLWelcome: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the // SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages. // methods supported on all messages.
@ -111,8 +113,6 @@ struct SDLWelcome: @unchecked Sendable {
/// Clears the value of `ipv6Assist`. Subsequent reads from it will return its default value. /// Clears the value of `ipv6Assist`. Subsequent reads from it will return its default value.
mutating func clearIpv6Assist() {self._ipv6Assist = nil} mutating func clearIpv6Assist() {self._ipv6Assist = nil}
var assistToken: Data = Data()
var unknownFields = SwiftProtobuf.UnknownStorage() var unknownFields = SwiftProtobuf.UnknownStorage()
init() {} init() {}
@ -699,7 +699,7 @@ extension SDLV6Info: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
extension SDLV6AssistProbe: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { extension SDLV6AssistProbe: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "SDLV6AssistProbe" static let protoMessageName: String = "SDLV6AssistProbe"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "assist_token"), 1: .standard(proto: "pkt_id"),
] ]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -708,21 +708,21 @@ extension SDLV6AssistProbe: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
// allocates stack space for every case branch when no optimizations are // allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034 // enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber { switch fieldNumber {
case 1: try { try decoder.decodeSingularBytesField(value: &self.assistToken) }() case 1: try { try decoder.decodeSingularUInt32Field(value: &self.pktID) }()
default: break default: break
} }
} }
} }
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws { func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.assistToken.isEmpty { if self.pktID != 0 {
try visitor.visitSingularBytesField(value: self.assistToken, fieldNumber: 1) try visitor.visitSingularUInt32Field(value: self.pktID, fieldNumber: 1)
} }
try unknownFields.traverse(visitor: &visitor) try unknownFields.traverse(visitor: &visitor)
} }
static func ==(lhs: SDLV6AssistProbe, rhs: SDLV6AssistProbe) -> Bool { static func ==(lhs: SDLV6AssistProbe, rhs: SDLV6AssistProbe) -> Bool {
if lhs.assistToken != rhs.assistToken {return false} if lhs.pktID != rhs.pktID {return false}
if lhs.unknownFields != rhs.unknownFields {return false} if lhs.unknownFields != rhs.unknownFields {return false}
return true return true
} }
@ -731,7 +731,8 @@ extension SDLV6AssistProbe: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
extension SDLV6AssistProbeReply: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { extension SDLV6AssistProbeReply: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "SDLV6AssistProbeReply" static let protoMessageName: String = "SDLV6AssistProbeReply"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "v6_info"), 1: .standard(proto: "pkt_id"),
2: .standard(proto: "v6_info"),
] ]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -740,7 +741,8 @@ extension SDLV6AssistProbeReply: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
// allocates stack space for every case branch when no optimizations are // allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034 // enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber { switch fieldNumber {
case 1: try { try decoder.decodeSingularMessageField(value: &self._v6Info) }() case 1: try { try decoder.decodeSingularUInt32Field(value: &self.pktID) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._v6Info) }()
default: break default: break
} }
} }
@ -751,13 +753,17 @@ extension SDLV6AssistProbeReply: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
// allocates stack space for every if/case branch local when no optimizations // allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182 // https://github.com/apple/swift-protobuf/issues/1182
if self.pktID != 0 {
try visitor.visitSingularUInt32Field(value: self.pktID, fieldNumber: 1)
}
try { if let v = self._v6Info { try { if let v = self._v6Info {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1) try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }() } }()
try unknownFields.traverse(visitor: &visitor) try unknownFields.traverse(visitor: &visitor)
} }
static func ==(lhs: SDLV6AssistProbeReply, rhs: SDLV6AssistProbeReply) -> Bool { static func ==(lhs: SDLV6AssistProbeReply, rhs: SDLV6AssistProbeReply) -> Bool {
if lhs.pktID != rhs.pktID {return false}
if lhs._v6Info != rhs._v6Info {return false} if lhs._v6Info != rhs._v6Info {return false}
if lhs.unknownFields != rhs.unknownFields {return false} if lhs.unknownFields != rhs.unknownFields {return false}
return true return true
@ -772,7 +778,6 @@ extension SDLWelcome: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
3: .standard(proto: "max_packet_size"), 3: .standard(proto: "max_packet_size"),
4: .standard(proto: "heartbeat_sec"), 4: .standard(proto: "heartbeat_sec"),
5: .standard(proto: "ipv6_assist"), 5: .standard(proto: "ipv6_assist"),
6: .standard(proto: "assist_token"),
] ]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws { mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -786,7 +791,6 @@ extension SDLWelcome: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.maxPacketSize) }() case 3: try { try decoder.decodeSingularUInt32Field(value: &self.maxPacketSize) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.heartbeatSec) }() case 4: try { try decoder.decodeSingularUInt32Field(value: &self.heartbeatSec) }()
case 5: try { try decoder.decodeSingularMessageField(value: &self._ipv6Assist) }() case 5: try { try decoder.decodeSingularMessageField(value: &self._ipv6Assist) }()
case 6: try { try decoder.decodeSingularBytesField(value: &self.assistToken) }()
default: break default: break
} }
} }
@ -812,9 +816,6 @@ extension SDLWelcome: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
try { if let v = self._ipv6Assist { try { if let v = self._ipv6Assist {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5) try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
} }() } }()
if !self.assistToken.isEmpty {
try visitor.visitSingularBytesField(value: self.assistToken, fieldNumber: 6)
}
try unknownFields.traverse(visitor: &visitor) try unknownFields.traverse(visitor: &visitor)
} }
@ -824,7 +825,6 @@ extension SDLWelcome: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
if lhs.maxPacketSize != rhs.maxPacketSize {return false} if lhs.maxPacketSize != rhs.maxPacketSize {return false}
if lhs.heartbeatSec != rhs.heartbeatSec {return false} if lhs.heartbeatSec != rhs.heartbeatSec {return false}
if lhs._ipv6Assist != rhs._ipv6Assist {return false} if lhs._ipv6Assist != rhs._ipv6Assist {return false}
if lhs.assistToken != rhs.assistToken {return false}
if lhs.unknownFields != rhs.unknownFields {return false} if lhs.unknownFields != rhs.unknownFields {return false}
return true return true
} }

View File

@ -7,6 +7,10 @@
import Foundation import Foundation
import Network import Network
enum SDLIPV6AssistError: Error {
case lostConnection
}
actor SDLIPV6AssistClient { actor SDLIPV6AssistClient {
private enum State { private enum State {
@ -20,10 +24,8 @@ actor SDLIPV6AssistClient {
private var receiveTask: Task<Void, Never>? private var receiveTask: Task<Void, Never>?
private let assistServerAddress: NWEndpoint private let assistServerAddress: NWEndpoint
// IP private var packetId: UInt32 = 1
let packetFlow: AsyncStream<SDLV6AssistProbeReply> private var pendingRequests: [UInt32: CheckedContinuation<SDLV6AssistProbeReply, Error>] = [:]
private let packetContinuation: AsyncStream<SDLV6AssistProbeReply>.Continuation
private var didFinishPacketFlow = false
// //
private let closeStream: AsyncStream<Void> private let closeStream: AsyncStream<Void>
@ -35,10 +37,6 @@ actor SDLIPV6AssistClient {
return nil return nil
} }
let (packetStream, packetContinuation) = AsyncStream.makeStream(of: SDLV6AssistProbeReply.self, bufferingPolicy: .bufferingNewest(256))
self.packetFlow = packetStream
self.packetContinuation = packetContinuation
let (closeStream, closeContinuation) = AsyncStream.makeStream(of: Void.self, bufferingPolicy: .bufferingNewest(1)) let (closeStream, closeContinuation) = AsyncStream.makeStream(of: Void.self, bufferingPolicy: .bufferingNewest(1))
self.closeStream = closeStream self.closeStream = closeStream
self.closeContinuation = closeContinuation self.closeContinuation = closeContinuation
@ -106,15 +104,36 @@ actor SDLIPV6AssistClient {
} }
} }
func probe() { func probe() async throws -> SDLV6AssistProbeReply {
guard case .running = self.state, let connection = self.connection, connection.state == .ready else { guard case .running = self.state, let connection = self.connection, connection.state == .ready else {
return throw SDLIPV6AssistError.lostConnection
} }
var assistProbe = SDLV6AssistProbe()
assistProbe.assistToken = Data()
if let data = try? assistProbe.serializedData() { return try await withCheckedThrowingContinuation { cont in
connection.send(content: data, completion: .contentProcessed { _ in}) let pktId = self.nextPacketId()
var assistProbe = SDLV6AssistProbe()
assistProbe.pktID = pktId
do {
let data = try assistProbe.serializedData()
connection.send(content: data, completion: .contentProcessed { error in
if let error {
Task {
await self.handleProcesseError(packetId: pktId, error: error)
}
}
})
self.pendingRequests[pktId] = cont
} catch let err {
cont.resume(throwing: err)
}
}
}
private func handleProcesseError(packetId: UInt32, error: NWError) {
if let cont = self.pendingRequests.removeValue(forKey: packetId) {
cont.resume(throwing: error)
} }
} }
@ -128,7 +147,6 @@ actor SDLIPV6AssistClient {
self.receiveTask = nil self.receiveTask = nil
self.connection?.cancel() self.connection?.cancel()
self.connection = nil self.connection = nil
self.finishPacketFlowIfNeeded()
self.finishCloseStreamIfNeeded() self.finishCloseStreamIfNeeded()
} }
@ -170,13 +188,12 @@ actor SDLIPV6AssistClient {
} }
private func handleReceivedPacket(_ data: Data) { private func handleReceivedPacket(_ data: Data) {
guard case .running = self.state else {
return
}
do { do {
let packet = try SDLV6AssistProbeReply(serializedBytes: data) let packet = try SDLV6AssistProbeReply(serializedBytes: data)
self.packetContinuation.yield(packet) let pktId = packet.pktID
if let cont = self.pendingRequests.removeValue(forKey: pktId) {
cont.resume(returning: packet)
}
} catch { } catch {
SDLLogger.log("[SDLIPV6AssistClient] Receive error: \(error)", for: .debug) SDLLogger.log("[SDLIPV6AssistClient] Receive error: \(error)", for: .debug)
} }
@ -194,15 +211,6 @@ actor SDLIPV6AssistClient {
} }
} }
private func finishPacketFlowIfNeeded() {
guard !self.didFinishPacketFlow else {
return
}
self.didFinishPacketFlow = true
self.packetContinuation.finish()
}
private func finishCloseStreamIfNeeded() { private func finishCloseStreamIfNeeded() {
guard !self.didFinishCloseStream else { guard !self.didFinishCloseStream else {
return return
@ -212,7 +220,15 @@ actor SDLIPV6AssistClient {
self.closeContinuation.finish() self.closeContinuation.finish()
} }
private func nextPacketId() -> UInt32 {
let packetId = self.packetId
self.packetId &+= 1
return packetId
}
deinit { deinit {
self.connection?.cancel() self.connection?.cancel()
} }
} }