

Swiftの Network.frameworkにあるNWProtocolQUICを使って複数のQUIC
Streamを用意しそれぞれ別のデータをサーバーに送信したいです。

以下は参考にしたサイトやAppleの発表、公式のドキュメントです。これらを参考にしてコードを書いたのですが、QUICトンネルの接続はできても個々のストリームを張ってデータを送信することができません。  
<https://developer.apple.com/videos/play/wwdc2021/10094/>  
<https://developer.apple.com/documentation/network/nwprotocolquic>  
<https://qiita.com/fuziki/items/5cec50ec45b188069f18>  
<https://qiita.com/fuziki/items/93d86457afc5d72185a8#nwconnection-%E3%81%AE%E4%BD%9C%E6%88%90>

[code]

    class QuicConnection {
        var acceptConnection: NWConnection?
        var openConnection: NWConnection?
        var acceptConnectionState: NWConnection.State?
        var openConnectionState: NWConnection.State?
        var receiveFromAcceptConnection: String?
        
        static func makeNWParameters() -> NWParameters {
            let options = NWProtocolQUIC.Options(alpn: ["echo"])
            options.direction = .bidirectional
            let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions
            sec_protocol_options_set_verify_block(securityProtocolOptions,
                                                  { (_: sec_protocol_metadata_t,
                                                     _: sec_trust_t,
                                                     complete: @escaping sec_protocol_verify_complete_t) in
                complete(true)
            }, DispatchQueue.main)
            return NWParameters(quic: options)
        }
    
        let group: NWConnectionGroup
    
        init() {
            print("init")
            let parameters = Self.makeNWParameters()
            let descriptor = NWMultiplexGroup(to: .hostPort(host: "192.168.0.20", port: 4242))
            group = NWConnectionGroup(with: descriptor, using: parameters)
    
            //subscribe()
            group.stateUpdateHandler = { (state: NWConnectionGroup.State) in
                print("state: \(state)")
                switch state {
                case .ready:
                    print("quic connected!")
                default:
                    break
                }
            }
            
            group.newConnectionHandler = { [weak self] (connection: NWConnection) in
                print("new connection: \(connection)")
                self?.acceptConnection = connection
                self?.acceptConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in
                    self?.acceptConnectionState = state
                }
                self?.subscribeAcceptConnection()
                self?.acceptConnection?.start(queue: DispatchQueue.main)
            }
            
            group.start(queue: DispatchQueue.main)
        }
        
        func createStream() {
            //guard let group else { return }
    
            let options = NWProtocolQUIC.Options()
            options.direction = .bidirectional
            let securityProtocolOptions: sec_protocol_options_t = options.securityProtocolOptions
            sec_protocol_options_set_verify_block(securityProtocolOptions,
                                                  { (_: sec_protocol_metadata_t,
                                                     _: sec_trust_t,
                                                     complete: @escaping sec_protocol_verify_complete_t) in
                complete(true) // Insecure !!!
            }, DispatchQueue.main)
            openConnection = NWConnection(from: group)
    
            openConnectionState = openConnection?.state
    
            openConnection?.stateUpdateHandler = { [weak self] (state: NWConnection.State) in
                self?.openConnectionState = state
                print("state: \(state)")
                switch state {
                case .ready:
                    print("stream connected!")
                    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                        self?.send(message: "marker1")
                    }
                default:
                    break
                }
            }
    
            openConnection?.start(queue: DispatchQueue.main)
        }
        
        func send(message: String) {
            print("send start")
            let completion: NWConnection.SendCompletion = .contentProcessed { (error: Error?) in
                if let error = error {
                    print("send error: \(error)")
                } else {
                    print("send successful")
                }
            }
            openConnection?.send(content: message.data(using: .utf8)!,
                             contentContext: .defaultMessage,
                             isComplete: true,
                            completion: completion)
            
            print("message: \(message)")
        }
    }
    
[/code]

アプリが起動したら、このQuicConnectionクラスのinit関数を呼び出してインスタンスを作成し、QUICトンネルを構築します。"quic
connected"のログが表示され、アプリ内で特定のアクションが動くとcreatStream関数を呼び出しストリームを張ります。"stream
connected"のログが表示されるまではいいのですが、その後send関数を用いてデータを送ろうとすると”send
successful"の表示がされるのですが、サーバー側にはクライアントからメッセージが届いたという出力はされません。

NQConnectionGroupを使わずNWConnectionのみの時は上手く通信できるのでサーバー側に問題はないと思います。サーバーはquic-
goを用いています。

SwiftでQUICのストリームを扱ったことのある方の知識をお借りしたいです。


CC BY-SA 4.0
2023-10-03T11:41:12.910
96411
2023-10-03T11:41:12.910
59983
question
swift
SwiftのNWProtocolQUICでQUIC Streamを使いたい