1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SwiftでQUICでDatagramする

Posted at

はじめに

iOS16/macOS13からNetwork.frameworkがQUICのDatagramに対応しました
6分24秒〜あたりで触れられています

試しに、quic-goとDatagramでechoしてみました
iOS16とmacOS13で動作することを確認しました

実装

リポジトリはこちら

Client (Swift)

NWProtocolQUIC.Optionsを作成して、isDatagramを有効にし、maxDatagramFrameSizeを設定します
今回はローカルでテストしたのでオレオレ証明書でも信頼します
NWConnectionGroupを作成して、各種handerを登録してstartします
NWConnectionと違い、NWConnectionGroupはメッセージを受け取る度に、setReceiveHandlerを再帰的に設定する必要はないようです

let options = NWProtocolQUIC.Options(alpn: ["echo"])
options.direction = .bidirectional
options.isDatagram = true
options.maxDatagramFrameSize = 65535
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)
let params = NWParameters(quic: options)
let desc = NWMultiplexGroup(to: .hostPort(host: "xxx.xxx.xxx.xxx", port: 4433))
let group = NWConnectionGroup(with: desc, using: params)

group.setReceiveHandler { (message: NWConnectionGroup.Message,
                           content: Data?,
                           isComplete: Bool) in
    print("receive message: \(message)")
    print("receive content: \(String(describing: content))")
    print("receive isComplete: \(isComplete)")
}

group.stateUpdateHandler = { (state: NWConnectionGroup.State) in
    print("state: \(state)")
}

group.start(queue: queue)

メッセージを送信する際には、NWConnectionGroup.send(content: to:message:completion:)を利用します

group.send(content: "Hello".data(using: .utf8)!) { (error: Error?) in
    print("send error: \(String(describing: error))")
}

Server (Go)

quic.Connectionが作成されるのを待って、受け取ったデータをそのまま返します

package main

import (
	"context"
	"crypto/tls"

	"github.com/alta/insecure"
	"github.com/quic-go/quic-go"
)

func main() {
	cert, _ := insecure.Cert()
	tlsConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		NextProtos:   []string{"echo"},
	}
	quicConfig := &quic.Config{
		EnableDatagrams: true,
	}
	listener, _ := quic.ListenAddr(":4433", tlsConfig, quicConfig)
	for {
		conn, _ := listener.Accept(context.Background())
		go func(conn quic.Connection) {
			for {
				bytes, _ := conn.ReceiveMessage()
				conn.SendMessage(bytes)
			}
		}(conn)
	}
}

終わりに

Network.frameworkを利用することでシンプルに、iOS/macOSでもDatagramを利用できました
ただNetwork.frameworkもquic-goもドキュメントが若干少なく、QUICの予備知識が自分に無かったので、どちらが悪いのか、自分の実装が悪いのか分からず、困る場面もありました
↑結果的に、自分の実装が悪かったようですw
Appleが思いの外?QUICの実装に積極的な印象があるので、このままWebTransportまで実装してくれたら嬉しいななどと思っています

Network.frameworkのQUICのストリームについても書いてます!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?