Skip to main content

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}