shiguredo_http3/event.rs
1//! HTTP/3 イベント
2//!
3//! Connection から返されるイベントを定義。
4
5use crate::varint::VarInt;
6
7/// WebTransport セッション終了時にリセットすべきストリームの情報
8///
9/// (draft-ietf-webtrans-http3-15 Section 6 / Section 4.4 / Section 5.4)
10///
11/// `reliable_size` は draft-ietf-quic-reliable-stream-reset の `RESET_STREAM_AT`
12/// に渡す reliable size。WebTransport データストリームの場合は stream header
13/// (stream type / signal value + session_id varint) のバイト数以上である
14/// 必要がある。`reset_stream_at` transport parameter がネゴシエートされていない
15/// 経路 (draft-02/07) では呼び出し側が通常の `RESET_STREAM` にフォールバック
16/// することを想定し、本フィールドは 0 でも構わない。
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct WtStreamReset {
19 /// QUIC ストリーム ID
20 pub stream_id: u64,
21 /// `RESET_STREAM_AT` の reliable size
22 pub reliable_size: u64,
23}
24
25/// WebTransport イベント
26///
27/// WebTransport 関連のイベントを集約した enum。
28/// `Event::WebTransport(WebTransportEvent)` として使用する。
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub enum WebTransportEvent {
31 /// 双方向ストリーム開始
32 /// (draft-ietf-webtrans-http3-15 Section 4.3)
33 BidiStreamOpen {
34 /// QUIC ストリーム ID
35 stream_id: u64,
36 /// WebTransport セッション ID
37 session_id: u64,
38 },
39 /// 双方向ストリームデータ受信
40 BidiStreamData {
41 /// QUIC ストリーム ID
42 stream_id: u64,
43 /// データ
44 data: Vec<u8>,
45 },
46 /// 双方向ストリーム終了 (FIN 受信)
47 BidiStreamEnd {
48 /// QUIC ストリーム ID
49 stream_id: u64,
50 },
51 /// 単方向ストリーム開始
52 /// (draft-ietf-webtrans-http3-15 Section 4.2)
53 UniStreamOpen {
54 /// QUIC ストリーム ID
55 stream_id: u64,
56 /// WebTransport セッション ID
57 session_id: u64,
58 },
59 /// 単方向ストリームデータ受信
60 UniStreamData {
61 /// QUIC ストリーム ID
62 stream_id: u64,
63 /// データ
64 data: Vec<u8>,
65 },
66 /// 単方向ストリーム終了 (FIN 受信)
67 UniStreamEnd {
68 /// QUIC ストリーム ID
69 stream_id: u64,
70 },
71 /// セッション終了
72 /// (draft-ietf-webtrans-http3-15 Section 6)
73 ///
74 /// セッションが終了した。`reset_streams` に含まれる全ストリームに対して
75 /// `error_code` を使用して `RESET_STREAM_AT` (reliable_size を伴う) と
76 /// STOP_SENDING を送信すること。`reset_stream_at` transport parameter が
77 /// ネゴシエートされていない経路では通常の `RESET_STREAM` にフォールバックする。
78 SessionClosed {
79 /// セッション ID (CONNECT ストリーム ID)
80 session_id: u64,
81 /// リセットすべきストリーム情報の一覧 (stream_id と reliable_size)
82 reset_streams: Vec<WtStreamReset>,
83 /// RESET_STREAM / STOP_SENDING に使用するエラーコード
84 /// (WT_SESSION_GONE / WT_ALPN_ERROR 等)
85 error_code: u64,
86 /// WT_CLOSE_SESSION カプセルのアプリケーションエラーコード
87 /// (draft-ietf-webtrans-http3-15 Section 6)
88 /// WT_CLOSE_SESSION なしの終了 (FIN / RESET_STREAM) の場合は 0
89 close_error_code: u32,
90 /// WT_CLOSE_SESSION カプセルのエラーメッセージ
91 /// (draft-ietf-webtrans-http3-15 Section 6)
92 /// WT_CLOSE_SESSION なしの終了の場合は空文字列
93 close_message: String,
94 },
95 /// セッション確立
96 /// (draft-ietf-webtrans-http3-15 Section 3)
97 ///
98 /// CONNECT ストリームに 200 OK が返された。
99 /// バッファリングされていたストリーム/データグラムがあれば配送される。
100 SessionEstablished {
101 /// セッション ID (CONNECT ストリーム ID)
102 session_id: u64,
103 /// フロー制御が有効かどうか (Section 5.1)
104 ///
105 /// 両端が SETTINGS でフロー制御を宣言した場合に `true`。
106 /// `true` の場合、接続層がストリーム数/データ量の超過を検知し、
107 /// WT_MAX_STREAMS / WT_MAX_DATA カプセルの生成を行う。
108 flow_control_enabled: bool,
109 },
110 /// セッション draining
111 /// (draft-ietf-webtrans-http3-15 Section 4.7)
112 ///
113 /// WT_DRAIN_SESSION カプセルを受信した。
114 /// Section 4.7 では MAY continue だが、本実装はアプリ層の早期終了を促すため
115 /// 新規ストリームやデータグラムの送信を拒否する。
116 /// セッションは即座に終了しないが、グレースフルシャットダウンを開始する。
117 SessionDraining {
118 /// セッション ID (CONNECT ストリーム ID)
119 session_id: u64,
120 },
121 /// フロー制御カプセル受信
122 /// (draft-ietf-webtrans-http3-15 Section 5.6)
123 ///
124 /// CONNECT ストリーム上でフロー制御カプセルを受信した。
125 /// 上位層は `webtransport::Session::process_capsule` に渡すこと。
126 Capsule {
127 /// WebTransport セッション ID
128 session_id: u64,
129 /// 受信した Capsule
130 capsule: crate::webtransport::Capsule,
131 },
132 /// データグラム受信
133 /// (draft-ietf-webtrans-http3-15 Section 4.5)
134 ///
135 /// QUIC DATAGRAM フレームから WebTransport データグラムを受信した。
136 Datagram {
137 /// WebTransport セッション ID
138 session_id: u64,
139 /// データグラムペイロード
140 payload: Vec<u8>,
141 },
142 /// データストリームのリセット受信
143 /// (draft-ietf-webtrans-http3-15 Section 4.4)
144 ///
145 /// WebTransport セッションに属するデータストリームに対して RESET_STREAM を
146 /// 受信した。アプリケーション層はセッション ID と application error code を
147 /// 元にアプリへ通知すること。
148 StreamReset {
149 /// WebTransport セッション ID
150 session_id: u64,
151 /// QUIC ストリーム ID
152 stream_id: u64,
153 /// QUIC application error code
154 error_code: u64,
155 /// QUIC RESET_STREAM の final size (RFC 9000 Section 19.4)
156 ///
157 /// `reset_stream_at` transport parameter がネゴシエートされている場合、
158 /// この値は stream header (stream type / signal value + session_id varint)
159 /// のバイト数以上であることが期待される (draft-ietf-webtrans-http3-15
160 /// Section 4.4)。
161 final_size: u64,
162 },
163 /// データストリームへの STOP_SENDING 受信
164 /// (draft-ietf-webtrans-http3-15 Section 4.4)
165 StreamStopSending {
166 /// WebTransport セッション ID
167 session_id: u64,
168 /// QUIC ストリーム ID
169 stream_id: u64,
170 /// QUIC application error code
171 error_code: u64,
172 },
173 /// バッファリング拒否
174 /// (draft-ietf-webtrans-http3-15 Section 4.6)
175 ///
176 /// バッファリング上限を超えたため、`error_code` を使用して
177 /// RESET_STREAM / STOP_SENDING を送信すること。
178 BufferedStreamRejected {
179 /// 拒否されたストリーム ID
180 stream_id: u64,
181 /// RESET_STREAM / STOP_SENDING に使用するエラーコード (WT_BUFFERED_STREAM_REJECTED)
182 error_code: u64,
183 },
184}
185
186impl WebTransportEvent {
187 /// ストリーム ID を取得 (存在する場合)
188 pub fn stream_id(&self) -> Option<u64> {
189 match self {
190 Self::BidiStreamOpen { stream_id, .. }
191 | Self::BidiStreamData { stream_id, .. }
192 | Self::BidiStreamEnd { stream_id }
193 | Self::UniStreamOpen { stream_id, .. }
194 | Self::UniStreamData { stream_id, .. }
195 | Self::UniStreamEnd { stream_id }
196 | Self::StreamReset { stream_id, .. }
197 | Self::StreamStopSending { stream_id, .. }
198 | Self::BufferedStreamRejected { stream_id, .. } => Some(*stream_id),
199 Self::SessionClosed { session_id, .. }
200 | Self::SessionEstablished { session_id, .. }
201 | Self::SessionDraining { session_id }
202 | Self::Capsule { session_id, .. }
203 | Self::Datagram { session_id, .. } => Some(*session_id),
204 }
205 }
206}
207
208/// HTTP/3 イベント
209#[derive(Debug, Clone, PartialEq, Eq)]
210pub enum Event {
211 /// SETTINGS フレーム受信
212 SettingsReceived {
213 /// ピアから受信した H3 設定
214 settings: crate::settings::Settings,
215 /// ピアから受信した WebTransport 設定
216 wt_settings: Option<crate::webtransport::settings::Settings>,
217 },
218 /// ヘッダー受信開始
219 HeadersBegin {
220 /// ストリーム ID
221 stream_id: u64,
222 },
223 /// 個別ヘッダー受信
224 Header {
225 /// ストリーム ID
226 stream_id: u64,
227 /// ヘッダー名
228 name: Vec<u8>,
229 /// ヘッダー値
230 value: Vec<u8>,
231 },
232 /// ヘッダー受信完了
233 HeadersEnd {
234 /// ストリーム ID
235 stream_id: u64,
236 },
237 /// データ受信
238 Data {
239 /// ストリーム ID
240 stream_id: u64,
241 /// データ
242 data: Vec<u8>,
243 },
244 /// ストリーム終了
245 StreamEnd {
246 /// ストリーム ID
247 stream_id: u64,
248 },
249 /// ストリームリセット (RESET_STREAM 受信)
250 StreamReset {
251 /// ストリーム ID
252 stream_id: u64,
253 /// エラーコード
254 error_code: u64,
255 },
256 /// 送信停止要求 (STOP_SENDING 受信)
257 StopSending {
258 /// ストリーム ID
259 stream_id: u64,
260 /// エラーコード
261 error_code: u64,
262 },
263 /// GOAWAY 受信
264 GoawayReceived {
265 /// GOAWAY で指定された ID (RFC 9000 Section 16 の VarInt)
266 ///
267 /// ロール依存: クライアント受信なら request stream ID、
268 /// サーバー受信なら push ID。
269 id: VarInt,
270 },
271 /// WebTransport イベント
272 WebTransport(WebTransportEvent),
273 /// 接続エラー
274 ConnectionError {
275 /// エラーコード
276 error_code: u64,
277 /// エラー理由
278 reason: String,
279 },
280}
281
282impl Event {
283 /// ストリーム ID を取得 (存在する場合)
284 pub fn stream_id(&self) -> Option<u64> {
285 match self {
286 Self::HeadersBegin { stream_id }
287 | Self::Header { stream_id, .. }
288 | Self::HeadersEnd { stream_id }
289 | Self::Data { stream_id, .. }
290 | Self::StreamEnd { stream_id }
291 | Self::StreamReset { stream_id, .. }
292 | Self::StopSending { stream_id, .. } => Some(*stream_id),
293 Self::WebTransport(wt) => wt.stream_id(),
294 _ => None,
295 }
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302
303 #[test]
304 fn test_event_stream_id() {
305 let event = Event::HeadersBegin { stream_id: 4 };
306 assert_eq!(event.stream_id(), Some(4));
307
308 let event = Event::SettingsReceived {
309 settings: crate::settings::Settings::new(),
310 wt_settings: None,
311 };
312 assert_eq!(event.stream_id(), None);
313 }
314
315 #[test]
316 fn test_webtransport_event_stream_id() {
317 // stream_id フィールドを持つバリアント
318 let wt = WebTransportEvent::BidiStreamOpen {
319 stream_id: 10,
320 session_id: 0,
321 };
322 assert_eq!(wt.stream_id(), Some(10));
323
324 // session_id フィールドを持つバリアント
325 let wt = WebTransportEvent::SessionEstablished {
326 session_id: 20,
327 flow_control_enabled: false,
328 };
329 assert_eq!(wt.stream_id(), Some(20));
330
331 // Event::WebTransport 経由で取得
332 let event = Event::WebTransport(WebTransportEvent::UniStreamEnd { stream_id: 30 });
333 assert_eq!(event.stream_id(), Some(30));
334 }
335}