unasuke (Yusuke Nakamura)
https://www.ruby.or.jp/ja/news/20221027
- PythonでのQUIC実装であるaioquicのRubyへの移植
- aioquic移植によって得られた知見を基にしたRuby-ishな独自実装作成
これまで主流だったHTTP/2は、TCP/IPの上にTLSの層があり、その上にHTTP/2の層があるという構造になっていた。HTTP/2の欠点を解消し、より高速な通信を実現するために作成されたHTTP/3では、その通信プロトコルにQUICを使用する。QUICは、UDPの上にセキュアで完全性のある通信を実現するため、プロコトルの内部でTLSや輻輳制御を取り扱う必要がある。
QUICプロトコルをRubyで実装するにあたり、前述したTLSなどについて全く知見のない状態から実装するのは非常に困難であると考えた。そのため比較的Rubyと似た言語であるPythonによる既存実装を移植することを最初の目的とした。
aioquicはQUICプロトコルのPython実装である。aioquicではPythonのasync/await構文による非同期IOを利用したQUICサーバー、及びクライアントを実装するためのAPIを提供している。その内部には、TLSプロトコルや、TCPが提供する輻輳制御の実装が含まれている。
移植については、aioquic側のQUICプロトコルに関係する src/aioquic/quic/
ディレクトリ以下にある実装と、それが依存している src/aioquic/
直下に存在するいくつかのモジュール、及びそれらのテストについてを対象とした。
移植成果物のGitHub repositoryは以下である。
https://github.com/unasuke/raioquic
また、付随してHTTP/3におけるヘッダ圧縮についての仕様である、QPACKについての実装である litespeedtech/ls-qpack についても、Ruby binding gemを作成した。
https://github.com/unasuke/lsqpack-ruby
現時点で、aioquicの各ファイルの移植状況は以下のとおりである。
── src
└── aioquic
├── about.py
├── asyncio/ <=============== 未移植(対象外)
├── _buffer.c
├── buffer.py <============== 移植済
├── _crypto.c
├── h0/ <==================== 未移植(対象外)
├── h3/ <==================== 未移植(対象外)
├── quic/
│ ├── configuration.py <== 移植済
│ ├── connection.py <===== 移植済
│ ├── crypto.py <========= 移植済
│ ├── events.py <========= 移植済
│ ├── __init__.py
│ ├── logger.py <==========移植済
│ ├── packet_builder.py <= 移植済
│ ├── packet.py <========= 移植済
│ ├── rangeset.py <======= 移植済
│ ├── recovery.py <======= 移植済
│ ├── retry.py <========== 移植済
│ └── stream.py <========= 移植済(テスト未完走)
└── tls.py <================= 移植済
最終報告提出時点で、QUICプロトコルの根幹を成すPacketやTLSなどについてのテストケースを大部分において通過しており、ローカルホストに閉じた場合であればQUICでの通信は部分的に可能な状態となっている。実際に、既存の実装のうち、移植元であるaioquicとの相互通信、Go実装であるquic-goに対しての送信を行うプログラムを作成し、動作させることができている。成果リポジトリの example/interoperability
以下に含めている。
また概要にあるように、今後のRuby-ishなQUIC実装を作成するにあたり、この移植でQUICプロトコル実装の知見を得ることもできた。例を挙げると、QUICプロトコルはTLSを内包しているためにTLSを実装する必要がある。移植作業の際にTLSプロトコルを実装することによって、TLSプロトコルへの理解が深まった。他にも暗号化/複合に関する処理や、輻輳制御についても同様に知見を得ることができた。
aioquicの完全な移植は作成できていない。QUICプロトコルに関係する部分では、connectionモジュールについてはテストケースを完全に通すことができていないので、引き続き移植作業を進めていく。asyncioディレクトリなど、Pythonのasync/await 構文が関係してくるため、そのままの形でRubyへと移植することが難しいコンポーネントについては、一対一での移植は行わない。
また、APIをほぼそのままの形で移植したためにRuby-ishでないAPIになっている現在の実装を参考に、Ruby-ishなAPIを持つQUICプロトコルの実装、ならびにHTTP/3による通信が行えるライブラリの実装を行うことを今後の目標とする。これにより、既存のRuby製アプリケーションサーバーが直接QUICを扱うことが可能となる。
笹田耕一さんにはメンターとして壁打ち相手になっていただいたり、C言語に関わる疑問について教えていただいたりなど、プロジェクトを進めていくにあたり支えとなっていただきました。大変感謝しています。また、このプロジェクトを採択していただいた一般財団法人Rubyアソシエーション様にも感謝いたします。