1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
//! HTTP/2 ストリーム管理
//!
//! ストリームの状態、フロー制御、バッファを管理する。
pub mod buffer;
pub mod state;
pub use buffer::{RecvBuffer, SendBuffer};
pub use state::{StateMachine, StreamState};
use crate::flow_control::FlowControl;
use crate::frame::StreamId;
use crate::hpack::HeaderField;
/// ストリーム
#[derive(Debug)]
pub struct Stream {
/// ストリーム ID
id: StreamId,
/// 状態機械
state: StateMachine,
/// フロー制御
flow_control: FlowControl,
/// 受信したヘッダー
headers: Vec<HeaderField>,
/// 受信データバッファ
recv_buffer: RecvBuffer,
/// 送信データバッファ
send_buffer: SendBuffer,
/// 送信待ちの END_STREAM フラグ
pending_end_stream: bool,
/// 初回ヘッダー受信済みフラグ (RFC 9113 Section 8.1)
///
/// 最終ヘッダー(サーバーではリクエスト、クライアントでは非 1xx レスポンス)を
/// 受信した場合に true になる。以降の疑似ヘッダーを含む HEADERS を拒否するために使用する。
initial_headers_received: bool,
/// 期待される Content-Length (RFC 9113 Section 8.1.1)
///
/// Content-Length ヘッダーが存在する場合、その値を保持する。
expected_content_length: Option<u64>,
/// 受信した Content-Length (累積)
received_content_length: u64,
/// CONNECT トンネル確立済みフラグ (RFC 9113 Section 8.5)
///
/// 通常の CONNECT (:protocol なし) で 2xx レスポンスが送受信された場合に true になる。
/// 確立後は DATA/RST_STREAM/WINDOW_UPDATE/PRIORITY のみ許可され、HEADERS は拒否される。
connect_established: bool,
/// リクエストメソッド
///
/// Content-Length チェック (204/304/HEAD の例外) と CONNECT 判定に使用する。
request_method: Option<Vec<u8>>,
/// Extended CONNECT (:protocol 付き) かどうか
///
/// Extended CONNECT は通常の HTTP/2 ストリームとして動作するため、
/// CONNECT トンネルのフレーム種別制限の対象外。
has_protocol: bool,
/// Extended CONNECT の :protocol 擬似ヘッダー値
///
/// RFC 8441 Section 4: Extended CONNECT で指定されたプロトコル名を保持する。
/// `has_protocol` が true の場合に設定される。
protocol: Option<Vec<u8>>,
/// コンテンツを持たないレスポンス (RFC 9110 Section 6.4.1)
///
/// 204/304 レスポンスおよび HEAD リクエストへのレスポンスは
/// コンテンツを持たないため、DATA フレームを受信してはならない。
no_content: bool,
/// 最終レスポンス送信済みフラグ (RFC 9113 Section 8.1)
///
/// 非 1xx の最終レスポンス HEADERS を送信した場合に true になる。
/// 以降の最終レスポンス送信を拒否し、trailer 送信の前提条件として使用する。
final_response_sent: bool,
}
impl Stream {
/// 新しいストリームを生成する
///
/// RFC 9113 Section 6.5.2 / Section 6.9.2: 送信ウィンドウはリモートの initial_window_size、
/// 受信ウィンドウはローカルの initial_window_size で初期化する。
#[must_use]
pub fn new(id: StreamId, send_initial_window_size: u32, recv_initial_window_size: u32) -> Self {
Self {
id,
state: StateMachine::new(),
flow_control: FlowControl::with_separate_windows(
send_initial_window_size,
recv_initial_window_size,
),
headers: Vec::new(),
recv_buffer: RecvBuffer::new(recv_initial_window_size as usize),
send_buffer: SendBuffer::new(send_initial_window_size as usize),
pending_end_stream: false,
initial_headers_received: false,
expected_content_length: None,
received_content_length: 0,
connect_established: false,
request_method: None,
has_protocol: false,
protocol: None,
no_content: false,
final_response_sent: false,
}
}
/// ストリーム ID を取得する
#[must_use]
pub const fn id(&self) -> StreamId {
self.id
}
/// 状態を取得する
#[must_use]
pub const fn state(&self) -> StreamState {
self.state.state()
}
/// 状態機械への参照を取得する
#[must_use]
pub const fn state_machine(&self) -> &StateMachine {
&self.state
}
/// 状態機械への可変参照を取得する
pub fn state_machine_mut(&mut self) -> &mut StateMachine {
&mut self.state
}
/// フロー制御への参照を取得する
#[must_use]
pub const fn flow_control(&self) -> &FlowControl {
&self.flow_control
}
/// フロー制御への可変参照を取得する
pub fn flow_control_mut(&mut self) -> &mut FlowControl {
&mut self.flow_control
}
/// ヘッダーを設定する
pub fn set_headers(&mut self, headers: Vec<HeaderField>) {
self.headers = headers;
}
/// ヘッダーを取得する
#[must_use]
pub fn headers(&self) -> &[HeaderField] {
&self.headers
}
/// 受信バッファへの参照を取得する
#[must_use]
pub const fn recv_buffer(&self) -> &RecvBuffer {
&self.recv_buffer
}
/// 受信バッファへの可変参照を取得する
pub fn recv_buffer_mut(&mut self) -> &mut RecvBuffer {
&mut self.recv_buffer
}
/// 送信バッファへの参照を取得する
#[must_use]
pub const fn send_buffer(&self) -> &SendBuffer {
&self.send_buffer
}
/// 送信バッファへの可変参照を取得する
pub fn send_buffer_mut(&mut self) -> &mut SendBuffer {
&mut self.send_buffer
}
/// 送信待ちの END_STREAM フラグを取得する
#[must_use]
pub const fn pending_end_stream(&self) -> bool {
self.pending_end_stream
}
/// 送信待ちの END_STREAM フラグを設定する
pub fn set_pending_end_stream(&mut self, value: bool) {
self.pending_end_stream = value;
}
/// ストリームがオープンかどうかを返す
#[must_use]
pub const fn is_open(&self) -> bool {
self.state.state().is_open()
}
/// ストリームがクローズドかどうかを返す
#[must_use]
pub const fn is_closed(&self) -> bool {
self.state.state().is_closed()
}
/// 初回ヘッダーを受信済みかどうかを返す
#[must_use]
pub const fn initial_headers_received(&self) -> bool {
self.initial_headers_received
}
/// 初回ヘッダー受信済みフラグを設定する
pub fn set_initial_headers_received(&mut self, received: bool) {
self.initial_headers_received = received;
}
/// 期待される Content-Length を設定する
pub fn set_expected_content_length(&mut self, length: Option<u64>) {
self.expected_content_length = length;
}
/// 期待される Content-Length を取得する
#[must_use]
pub const fn expected_content_length(&self) -> Option<u64> {
self.expected_content_length
}
/// 受信した Content-Length を取得する
#[must_use]
pub const fn received_content_length(&self) -> u64 {
self.received_content_length
}
/// 受信した Content-Length を加算する
pub fn add_received_content_length(&mut self, length: u64) {
self.received_content_length += length;
}
/// CONNECT トンネルが確立済みかどうかを返す
#[must_use]
pub const fn connect_established(&self) -> bool {
self.connect_established
}
/// CONNECT トンネル確立済みフラグを設定する
pub fn set_connect_established(&mut self, established: bool) {
self.connect_established = established;
}
/// リクエストメソッドを取得する
#[must_use]
pub fn request_method(&self) -> Option<&[u8]> {
self.request_method.as_deref()
}
/// リクエストメソッドを設定する
pub fn set_request_method(&mut self, method: Vec<u8>) {
self.request_method = Some(method);
}
/// Extended CONNECT (:protocol 付き) かどうかを返す
#[must_use]
pub const fn has_protocol(&self) -> bool {
self.has_protocol
}
/// Extended CONNECT フラグを設定する
pub fn set_has_protocol(&mut self, has_protocol: bool) {
self.has_protocol = has_protocol;
}
/// Extended CONNECT の :protocol 擬似ヘッダー値を取得する
#[must_use]
pub fn protocol(&self) -> Option<&[u8]> {
self.protocol.as_deref()
}
/// Extended CONNECT の :protocol 擬似ヘッダー値を設定する
pub fn set_protocol(&mut self, protocol: Vec<u8>) {
self.protocol = Some(protocol);
}
/// コンテンツを持たないレスポンスかどうかを返す
#[must_use]
pub const fn no_content(&self) -> bool {
self.no_content
}
/// コンテンツを持たないレスポンスフラグを設定する
pub fn set_no_content(&mut self, no_content: bool) {
self.no_content = no_content;
}
/// 最終レスポンスを送信済みかどうかを返す
#[must_use]
pub const fn final_response_sent(&self) -> bool {
self.final_response_sent
}
/// 最終レスポンス送信済みフラグを設定する
pub fn set_final_response_sent(&mut self, sent: bool) {
self.final_response_sent = sent;
}
}