fix quic
This commit is contained in:
parent
e54f898c7d
commit
2d6d640a44
@ -144,8 +144,7 @@ actor SDLContextActor {
|
|||||||
SDLLogger.shared.log("[SDLContext] start quic client ready")
|
SDLLogger.shared.log("[SDLContext] start quic client ready")
|
||||||
|
|
||||||
self.quicWorker = Task.detached {
|
self.quicWorker = Task.detached {
|
||||||
let stream = await quicClient.messageStream()
|
for await message in quicClient.messageStream {
|
||||||
for await message in stream {
|
|
||||||
switch message {
|
switch message {
|
||||||
case .welcome(let welcome):
|
case .welcome(let welcome):
|
||||||
SDLLogger.shared.log("[SDLContext] quic welcome: \(welcome)")
|
SDLLogger.shared.log("[SDLContext] quic welcome: \(welcome)")
|
||||||
|
|||||||
@ -19,15 +19,29 @@ enum SDLQUICError: Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class SDLQUICClient {
|
final class SDLQUICClient {
|
||||||
|
private let allocator = ByteBufferAllocator()
|
||||||
|
// 单个包最大64K
|
||||||
|
private let maxPacketSize: Int
|
||||||
|
// 最大缓冲区区为2M
|
||||||
|
private let maxBufferSize: Int
|
||||||
|
|
||||||
|
public var messageStream: AsyncStream<SDLQUICInboundMessage>
|
||||||
|
private let messageCont: AsyncStream<SDLQUICInboundMessage>.Continuation
|
||||||
|
private var readTask: Task<Void, Never>?
|
||||||
|
|
||||||
private let connection: NWConnection
|
private let connection: NWConnection
|
||||||
private let queue = DispatchQueue(label: "com.sdl.QUICClient.queue") // 专用队列保证线程安全
|
private let queue = DispatchQueue(label: "com.sdl.QUICClient.queue") // 专用队列保证线程安全
|
||||||
|
|
||||||
private let (closeStream, closeCont) = AsyncStream.makeStream(of: Void.self)
|
private let (closeStream, closeCont) = AsyncStream.makeStream(of: Void.self)
|
||||||
private let (readyStream, readyCont) = AsyncStream.makeStream(of: Void.self)
|
private let (readyStream, readyCont) = AsyncStream.makeStream(of: Void.self)
|
||||||
|
|
||||||
init(host: String, port: UInt16) {
|
init(host: String, port: UInt16, maxPacketSize: Int = 64 * 1024, maxBufferSize: Int = 2 * 1024 * 1024) {
|
||||||
let options = NWProtocolQUIC.Options(alpn: ["punchnet/1.0"])
|
let options = NWProtocolQUIC.Options(alpn: ["punchnet/1.0"])
|
||||||
|
|
||||||
|
self.maxBufferSize = maxBufferSize
|
||||||
|
self.maxPacketSize = maxPacketSize
|
||||||
|
(self.messageStream, self.messageCont) = AsyncStream.makeStream(of: SDLQUICInboundMessage.self)
|
||||||
|
|
||||||
// TODO 这里设置证书的校验逻辑
|
// TODO 这里设置证书的校验逻辑
|
||||||
sec_protocol_options_set_verify_block(
|
sec_protocol_options_set_verify_block(
|
||||||
options.securityProtocolOptions,
|
options.securityProtocolOptions,
|
||||||
@ -57,13 +71,37 @@ final class SDLQUICClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
connection.start(queue: self.queue)
|
connection.start(queue: self.queue)
|
||||||
|
|
||||||
|
// 启动数据读取任务
|
||||||
|
self.readTask = Task {
|
||||||
|
var buffer = allocator.buffer(capacity: self.maxBufferSize)
|
||||||
|
let threshold = self.maxBufferSize / 10 * 6
|
||||||
|
do {
|
||||||
|
while !Task.isCancelled {
|
||||||
|
let (isComplete, data) = try await self.readOnce()
|
||||||
|
if let data, !data.isEmpty {
|
||||||
|
buffer.writeBytes(data)
|
||||||
|
let frames = try parseFrames(buffer: &buffer)
|
||||||
|
if buffer.readerIndex > threshold {
|
||||||
|
buffer.discardReadBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func messageStream() async -> AsyncStream<SDLQUICInboundMessage> {
|
for frame in frames {
|
||||||
let reader = SDLQUICReader(connection: self.connection)
|
if let message = decode(frame: frame) {
|
||||||
await reader.start()
|
self.messageCont.yield(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await reader.messageStream
|
if isComplete {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.messageCont.finish()
|
||||||
|
} catch {
|
||||||
|
self.messageCont.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(type: SDLPacketType, data: Data) {
|
func send(type: SDLPacketType, data: Data) {
|
||||||
@ -92,60 +130,6 @@ final class SDLQUICClient {
|
|||||||
self.connection.cancel()
|
self.connection.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
actor SDLQUICReader {
|
|
||||||
private let allocator = ByteBufferAllocator()
|
|
||||||
// 单个包最大64K
|
|
||||||
private let maxPacketSize: Int
|
|
||||||
// 最大缓冲区区为2M
|
|
||||||
private let maxBufferSize: Int
|
|
||||||
|
|
||||||
public var messageStream: AsyncStream<SDLQUICInboundMessage>
|
|
||||||
private let messageCont: AsyncStream<SDLQUICInboundMessage>.Continuation
|
|
||||||
|
|
||||||
private var readTask: Task<Void, Never>?
|
|
||||||
private let connection: NWConnection
|
|
||||||
|
|
||||||
init(connection: NWConnection, maxPacketSize: Int = 64 * 1024, maxBufferSize: Int = 2 * 1024 * 1024) {
|
|
||||||
self.connection = connection
|
|
||||||
self.maxBufferSize = maxBufferSize
|
|
||||||
self.maxPacketSize = maxPacketSize
|
|
||||||
(self.messageStream, self.messageCont) = AsyncStream.makeStream(of: SDLQUICInboundMessage.self)
|
|
||||||
}
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
self.readTask = Task {
|
|
||||||
var buffer = allocator.buffer(capacity: self.maxBufferSize)
|
|
||||||
let threshold = self.maxBufferSize / 10 * 6
|
|
||||||
do {
|
|
||||||
while !Task.isCancelled {
|
|
||||||
let (isComplete, data) = try await self.readOnce()
|
|
||||||
if let data, !data.isEmpty {
|
|
||||||
buffer.writeBytes(data)
|
|
||||||
let frames = try parseFrames(buffer: &buffer)
|
|
||||||
if buffer.readerIndex > threshold {
|
|
||||||
buffer.discardReadBytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
for frame in frames {
|
|
||||||
if let message = SDLQUICCodec.decode(frame: frame) {
|
|
||||||
self.messageCont.yield(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isComplete {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.messageCont.finish()
|
|
||||||
} catch {
|
|
||||||
self.messageCont.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试解析数据
|
// 尝试解析数据
|
||||||
private func parseFrames(buffer: inout ByteBuffer) throws -> [ByteBuffer] {
|
private func parseFrames(buffer: inout ByteBuffer) throws -> [ByteBuffer] {
|
||||||
guard buffer.readableBytes >= 2 else {
|
guard buffer.readableBytes >= 2 else {
|
||||||
@ -178,7 +162,7 @@ actor SDLQUICReader {
|
|||||||
// 读取一次数据
|
// 读取一次数据
|
||||||
private func readOnce() async throws -> (Bool, Data?) {
|
private func readOnce() async throws -> (Bool, Data?) {
|
||||||
return try await withCheckedThrowingContinuation { cont in
|
return try await withCheckedThrowingContinuation { cont in
|
||||||
connection.receive(minimumIncompleteLength: 1, maximumLength: maxPacketSize) { data, _, isComplete, error in
|
self.connection.receive(minimumIncompleteLength: 1, maximumLength: maxPacketSize) { data, _, isComplete, error in
|
||||||
if let error {
|
if let error {
|
||||||
cont.resume(throwing: error)
|
cont.resume(throwing: error)
|
||||||
return
|
return
|
||||||
@ -188,16 +172,8 @@ actor SDLQUICReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.readTask?.cancel()
|
|
||||||
self.messageCont.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SDLQUICCodec {
|
|
||||||
// --MARK: 编解码器
|
// --MARK: 编解码器
|
||||||
public static func decode(frame: ByteBuffer) -> SDLQUICInboundMessage? {
|
private func decode(frame: ByteBuffer) -> SDLQUICInboundMessage? {
|
||||||
var buffer = frame
|
var buffer = frame
|
||||||
guard let type = buffer.readInteger(as: UInt8.self),
|
guard let type = buffer.readInteger(as: UInt8.self),
|
||||||
let packetType = SDLPacketType(rawValue: type) else {
|
let packetType = SDLPacketType(rawValue: type) else {
|
||||||
@ -270,4 +246,9 @@ struct SDLQUICCodec {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.readTask?.cancel()
|
||||||
|
self.messageCont.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user