1 // Copyright (C) 2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 //! HTTP/3 wire protocol and QPACK implementation.
28 //!
29 //! This module provides a high level API for sending and receiving HTTP/3
30 //! requests and responses on top of the QUIC transport protocol.
31 //!
32 //! ## Connection setup
33 //!
34 //! HTTP/3 connections require a QUIC transport-layer connection, see
35 //! [Connection setup] for a full description of the setup process.
36 //!
37 //! To use HTTP/3, the QUIC connection must be configured with a suitable
38 //! Application Layer Protocol Negotiation (ALPN) Protocol ID:
39 //!
40 //! ```
41 //! let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
42 //! config.set_application_protos(quiche::h3::APPLICATION_PROTOCOL)?;
43 //! # Ok::<(), quiche::Error>(())
44 //! ```
45 //!
46 //! The QUIC handshake is driven by [sending] and [receiving] QUIC packets.
47 //!
48 //! Once the handshake has completed, the first step in establishing an HTTP/3
49 //! connection is creating its configuration object:
50 //!
51 //! ```
52 //! let h3_config = quiche::h3::Config::new()?;
53 //! # Ok::<(), quiche::h3::Error>(())
54 //! ```
55 //!
56 //! HTTP/3 client and server connections are both created using the
57 //! [`with_transport()`] function, the role is inferred from the type of QUIC
58 //! connection:
59 //!
60 //! ```no_run
61 //! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
62 //! # let scid = [0xba; 16];
63 //! # let mut conn = quiche::connect(None, &scid, &mut config).unwrap();
64 //! # let h3_config = quiche::h3::Config::new()?;
65 //! let h3_conn = quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;
66 //! # Ok::<(), quiche::h3::Error>(())
67 //! ```
68 //!
69 //! ## Sending a request
70 //!
71 //! An HTTP/3 client can send a request by using the connection's
72 //! [`send_request()`] method to queue request headers; [sending] QUIC packets
73 //! causes the requests to get sent to the peer:
74 //!
75 //! ```no_run
76 //! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
77 //! # let scid = [0xba; 16];
78 //! # let mut conn = quiche::connect(None, &scid, &mut config).unwrap();
79 //! # let h3_config = quiche::h3::Config::new()?;
80 //! # let mut h3_conn = quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;
81 //! let req = vec![
82 //! quiche::h3::Header::new(":method", "GET"),
83 //! quiche::h3::Header::new(":scheme", "https"),
84 //! quiche::h3::Header::new(":authority", "quic.tech"),
85 //! quiche::h3::Header::new(":path", "/"),
86 //! quiche::h3::Header::new("user-agent", "quiche"),
87 //! ];
88 //!
89 //! h3_conn.send_request(&mut conn, &req, true)?;
90 //! # Ok::<(), quiche::h3::Error>(())
91 //! ```
92 //!
93 //! An HTTP/3 client can send a request with additional body data by using
94 //! the connection's [`send_body()`] method:
95 //!
96 //! ```no_run
97 //! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
98 //! # let scid = [0xba; 16];
99 //! # let mut conn = quiche::connect(None, &scid, &mut config).unwrap();
100 //! # let h3_config = quiche::h3::Config::new()?;
101 //! # let mut h3_conn = quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;
102 //! let req = vec![
103 //! quiche::h3::Header::new(":method", "GET"),
104 //! quiche::h3::Header::new(":scheme", "https"),
105 //! quiche::h3::Header::new(":authority", "quic.tech"),
106 //! quiche::h3::Header::new(":path", "/"),
107 //! quiche::h3::Header::new("user-agent", "quiche"),
108 //! ];
109 //!
110 //! let stream_id = h3_conn.send_request(&mut conn, &req, false)?;
111 //! h3_conn.send_body(&mut conn, stream_id, b"Hello World!", true)?;
112 //! # Ok::<(), quiche::h3::Error>(())
113 //! ```
114 //!
115 //! ## Handling requests and responses
116 //!
117 //! After [receiving] QUIC packets, HTTP/3 data is processed using the
118 //! connection's [`poll()`] method. On success, this returns an [`Event`] object
119 //! and an ID corresponding to the stream where the `Event` originated.
120 //!
121 //! An HTTP/3 server uses [`poll()`] to read requests and responds to them using
122 //! [`send_response()`] and [`send_body()`]:
123 //!
124 //! ```no_run
125 //! use quiche::h3::NameValue;
126 //!
127 //! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
128 //! # let scid = [0xba; 16];
129 //! # let mut conn = quiche::accept(&scid, None, &mut config).unwrap();
130 //! # let h3_config = quiche::h3::Config::new()?;
131 //! # let mut h3_conn = quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;
132 //! loop {
133 //! match h3_conn.poll(&mut conn) {
134 //! Ok((stream_id, quiche::h3::Event::Headers{list, has_body})) => {
135 //! let mut headers = list.into_iter();
136 //!
137 //! // Look for the request's method.
138 //! let method = headers.find(|h| h.name() == ":method").unwrap();
139 //!
140 //! // Look for the request's path.
141 //! let path = headers.find(|h| h.name() == ":path").unwrap();
142 //!
143 //! if method.value() == "GET" && path.value() == "/" {
144 //! let resp = vec![
145 //! quiche::h3::Header::new(":status", &200.to_string()),
146 //! quiche::h3::Header::new("server", "quiche"),
147 //! ];
148 //!
149 //! h3_conn.send_response(&mut conn, stream_id, &resp, false)?;
150 //! h3_conn.send_body(&mut conn, stream_id, b"Hello World!", true)?;
151 //! }
152 //! },
153 //!
154 //! Ok((stream_id, quiche::h3::Event::Data)) => {
155 //! // Request body data, handle it.
156 //! # return Ok(());
157 //! },
158 //!
159 //! Ok((stream_id, quiche::h3::Event::Finished)) => {
160 //! // Peer terminated stream, handle it.
161 //! },
162 //!
163 //! Ok((_flow_id, quiche::h3::Event::Datagram)) => (),
164 //!
165 //! Ok((goaway_id, quiche::h3::Event::GoAway)) => {
166 //! // Peer signalled it is going away, handle it.
167 //! },
168 //!
169 //! Err(quiche::h3::Error::Done) => {
170 //! // Done reading.
171 //! break;
172 //! },
173 //!
174 //! Err(e) => {
175 //! // An error occurred, handle it.
176 //! break;
177 //! },
178 //! }
179 //! }
180 //! # Ok::<(), quiche::h3::Error>(())
181 //! ```
182 //!
183 //! An HTTP/3 client uses [`poll()`] to read responses:
184 //!
185 //! ```no_run
186 //! use quiche::h3::NameValue;
187 //!
188 //! # let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap();
189 //! # let scid = [0xba; 16];
190 //! # let mut conn = quiche::connect(None, &scid, &mut config).unwrap();
191 //! # let h3_config = quiche::h3::Config::new()?;
192 //! # let mut h3_conn = quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;
193 //! loop {
194 //! match h3_conn.poll(&mut conn) {
195 //! Ok((stream_id, quiche::h3::Event::Headers{list, has_body})) => {
196 //! let status = list.iter().find(|h| h.name() == ":status").unwrap();
197 //! println!("Received {} response on stream {}",
198 //! status.value(), stream_id);
199 //! },
200 //!
201 //! Ok((stream_id, quiche::h3::Event::Data)) => {
202 //! let mut body = vec![0; 4096];
203 //!
204 //! if let Ok(read) =
205 //! h3_conn.recv_body(&mut conn, stream_id, &mut body)
206 //! {
207 //! println!("Received {} bytes of payload on stream {}",
208 //! read, stream_id);
209 //! }
210 //! },
211 //!
212 //! Ok((stream_id, quiche::h3::Event::Finished)) => {
213 //! // Peer terminated stream, handle it.
214 //! },
215 //!
216 //! Ok((_flow_id, quiche::h3::Event::Datagram)) => (),
217 //!
218 //! Ok((goaway_id, quiche::h3::Event::GoAway)) => {
219 //! // Peer signalled it is going away, handle it.
220 //! },
221 //!
222 //! Err(quiche::h3::Error::Done) => {
223 //! // Done reading.
224 //! break;
225 //! },
226 //!
227 //! Err(e) => {
228 //! // An error occurred, handle it.
229 //! break;
230 //! },
231 //! }
232 //! }
233 //! # Ok::<(), quiche::h3::Error>(())
234 //! ```
235 //!
236 //! ## Detecting end of request or response
237 //!
238 //! A single HTTP/3 request or response may consist of several HEADERS and DATA
239 //! frames; it is finished when the QUIC stream is closed. Calling [`poll()`]
240 //! repeatedly will generate an [`Event`] for each of these. The application may
241 //! use these event to do additional HTTP semantic validation.
242 //!
243 //! ## HTTP/3 protocol errors
244 //!
245 //! Quiche is responsible for managing the HTTP/3 connection, ensuring it is in
246 //! a correct state and validating all messages received by a peer. This mainly
247 //! takes place in the [`poll()`] method. If an HTTP/3 error occurs, quiche will
248 //! close the connection and send an appropriate CONNECTION_CLOSE frame to the
249 //! peer. An [`Error`] is returned to the application so that it can perform any
250 //! required tidy up such as closing sockets.
251 //!
252 //! [`application_proto()`]: ../struct.Connection.html#method.application_proto
253 //! [`stream_finished()`]: ../struct.Connection.html#method.stream_finished
254 //! [Connection setup]: ../index.html#connection-setup
255 //! [sending]: ../index.html#generating-outgoing-packets
256 //! [receiving]: ../index.html#handling-incoming-packets
257 //! [`with_transport()`]: struct.Connection.html#method.with_transport
258 //! [`poll()`]: struct.Connection.html#method.poll
259 //! [`Event`]: enum.Event.html
260 //! [`Error`]: enum.Error.html
261 //! [`send_request()`]: struct.Connection.html#method.send_response
262 //! [`send_response()`]: struct.Connection.html#method.send_response
263 //! [`send_body()`]: struct.Connection.html#method.send_body
264
265 use std::collections::HashMap;
266 use std::collections::VecDeque;
267
268 use crate::octets;
269
270 /// List of ALPN tokens of supported HTTP/3 versions.
271 ///
272 /// This can be passed directly to the [`Config::set_application_protos()`]
273 /// method when implementing HTTP/3 applications.
274 ///
275 /// [`Config::set_application_protos()`]:
276 /// ../struct.Config.html#method.set_application_protos
277 pub const APPLICATION_PROTOCOL: &[u8] = b"\x05h3-29\x05h3-28\x05h3-27";
278
279 // The offset used when converting HTTP/3 urgency to quiche urgency.
280 const PRIORITY_URGENCY_OFFSET: u8 = 124;
281
282 /// A specialized [`Result`] type for quiche HTTP/3 operations.
283 ///
284 /// This type is used throughout quiche's HTTP/3 public API for any operation
285 /// that can produce an error.
286 ///
287 /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
288 pub type Result<T> = std::result::Result<T, Error>;
289
290 /// An HTTP/3 error.
291 #[derive(Clone, Copy, Debug, PartialEq)]
292 pub enum Error {
293 /// There is no error or no work to do
294 Done,
295
296 /// The provided buffer is too short.
297 BufferTooShort,
298
299 /// Internal error in the HTTP/3 stack.
300 InternalError,
301
302 /// Endpoint detected that the peer is exhibiting behavior that causes.
303 /// excessive load.
304 ExcessiveLoad,
305
306 /// Stream ID or Push ID greater that current maximum was
307 /// used incorrectly, such as exceeding a limit, reducing a limit,
308 /// or being reused.
309 IdError,
310
311 /// The endpoint detected that its peer created a stream that it will not
312 /// accept.
313 StreamCreationError,
314
315 /// A required critical stream was closed.
316 ClosedCriticalStream,
317
318 /// No SETTINGS frame at beginning of control stream.
319 MissingSettings,
320
321 /// A frame was received which is not permitted in the current state.
322 FrameUnexpected,
323
324 /// Frame violated layout or size rules.
325 FrameError,
326
327 /// QPACK Header block decompression failure.
328 QpackDecompressionFailed,
329
330 /// Error originated from the transport layer.
331 TransportError(crate::Error),
332
333 /// The underlying QUIC stream (or connection) doesn't have enough capacity
334 /// for the operation to complete. The application should retry later on.
335 StreamBlocked,
336 }
337
338 impl Error {
to_wire(self) -> u64339 fn to_wire(self) -> u64 {
340 match self {
341 Error::Done => 0x100,
342 Error::InternalError => 0x102,
343 Error::StreamCreationError => 0x103,
344 Error::ClosedCriticalStream => 0x104,
345 Error::FrameUnexpected => 0x105,
346 Error::FrameError => 0x106,
347 Error::ExcessiveLoad => 0x107,
348 Error::IdError => 0x108,
349 Error::MissingSettings => 0x10A,
350 Error::QpackDecompressionFailed => 0x200,
351 Error::BufferTooShort => 0x999,
352 Error::TransportError { .. } => 0xFF,
353 Error::StreamBlocked => 0xFF,
354 }
355 }
356
to_c(self) -> libc::ssize_t357 fn to_c(self) -> libc::ssize_t {
358 match self {
359 Error::Done => -1,
360 Error::BufferTooShort => -2,
361 Error::InternalError => -3,
362 Error::ExcessiveLoad => -4,
363 Error::IdError => -5,
364 Error::StreamCreationError => -6,
365 Error::ClosedCriticalStream => -7,
366 Error::MissingSettings => -8,
367 Error::FrameUnexpected => -9,
368 Error::FrameError => -10,
369 Error::QpackDecompressionFailed => -11,
370 Error::TransportError { .. } => -12,
371 Error::StreamBlocked => -13,
372 }
373 }
374 }
375
376 impl std::fmt::Display for Error {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result377 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
378 write!(f, "{:?}", self)
379 }
380 }
381
382 impl std::error::Error for Error {
source(&self) -> Option<&(dyn std::error::Error + 'static)>383 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
384 None
385 }
386 }
387
388 impl std::convert::From<super::Error> for Error {
from(err: super::Error) -> Self389 fn from(err: super::Error) -> Self {
390 match err {
391 super::Error::Done => Error::Done,
392
393 _ => Error::TransportError(err),
394 }
395 }
396 }
397
398 impl std::convert::From<octets::BufferTooShortError> for Error {
from(_err: octets::BufferTooShortError) -> Self399 fn from(_err: octets::BufferTooShortError) -> Self {
400 Error::BufferTooShort
401 }
402 }
403
404 /// An HTTP/3 configuration.
405 pub struct Config {
406 max_header_list_size: Option<u64>,
407 qpack_max_table_capacity: Option<u64>,
408 qpack_blocked_streams: Option<u64>,
409 }
410
411 impl Config {
412 /// Creates a new configuration object with default settings.
new() -> Result<Config>413 pub fn new() -> Result<Config> {
414 Ok(Config {
415 max_header_list_size: None,
416 qpack_max_table_capacity: None,
417 qpack_blocked_streams: None,
418 })
419 }
420
421 /// Sets the `SETTINGS_MAX_HEADER_LIST_SIZE` setting.
422 ///
423 /// By default no limit is enforced.
set_max_header_list_size(&mut self, v: u64)424 pub fn set_max_header_list_size(&mut self, v: u64) {
425 self.max_header_list_size = Some(v);
426 }
427
428 /// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` setting.
429 ///
430 /// The default value is `0`.
set_qpack_max_table_capacity(&mut self, v: u64)431 pub fn set_qpack_max_table_capacity(&mut self, v: u64) {
432 self.qpack_max_table_capacity = Some(v);
433 }
434
435 /// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting.
436 ///
437 /// The default value is `0`.
set_qpack_blocked_streams(&mut self, v: u64)438 pub fn set_qpack_blocked_streams(&mut self, v: u64) {
439 self.qpack_blocked_streams = Some(v);
440 }
441 }
442
443 /// A trait for types with associated string name and value.
444 pub trait NameValue {
445 /// Returns the object's name.
name(&self) -> &str446 fn name(&self) -> &str;
447
448 /// Returns the object's value.
value(&self) -> &str449 fn value(&self) -> &str;
450 }
451
452 /// An owned name-value pair representing a raw HTTP header.
453 #[derive(Clone, Debug, PartialEq)]
454 pub struct Header(String, String);
455
456 impl Header {
457 /// Creates a new header.
458 ///
459 /// Both `name` and `value` will be cloned.
new(name: &str, value: &str) -> Self460 pub fn new(name: &str, value: &str) -> Self {
461 Self(String::from(name), String::from(value))
462 }
463 }
464
465 impl NameValue for Header {
name(&self) -> &str466 fn name(&self) -> &str {
467 &self.0
468 }
469
value(&self) -> &str470 fn value(&self) -> &str {
471 &self.1
472 }
473 }
474
475 /// A non-owned name-value pair representing a raw HTTP header.
476 #[derive(Clone, Debug, PartialEq)]
477 pub struct HeaderRef<'a>(&'a str, &'a str);
478
479 impl<'a> HeaderRef<'a> {
480 /// Creates a new header.
new(name: &'a str, value: &'a str) -> Self481 pub fn new(name: &'a str, value: &'a str) -> Self {
482 Self(name, value)
483 }
484 }
485
486 impl<'a> NameValue for HeaderRef<'a> {
name(&self) -> &str487 fn name(&self) -> &str {
488 self.0
489 }
490
value(&self) -> &str491 fn value(&self) -> &str {
492 self.1
493 }
494 }
495
496 /// An HTTP/3 connection event.
497 #[derive(Clone, Debug, PartialEq)]
498 pub enum Event {
499 /// Request/response headers were received.
500 Headers {
501 /// The list of received header fields. The application should validate
502 /// pseudo-headers and headers.
503 list: Vec<Header>,
504
505 /// Whether data will follow the headers on the stream.
506 has_body: bool,
507 },
508
509 /// Data was received.
510 ///
511 /// This indicates that the application can use the [`recv_body()`] method
512 /// to retrieve the data from the stream.
513 ///
514 /// This event will keep being reported until all the available data is
515 /// retrieved by the application.
516 ///
517 /// [`recv_body()`]: struct.Connection.html#method.recv_body
518 Data,
519
520 /// Stream was closed,
521 Finished,
522
523 /// DATAGRAM was received.
524 Datagram,
525
526 /// GOAWAY was received.
527 GoAway,
528 }
529
530 struct ConnectionSettings {
531 pub max_header_list_size: Option<u64>,
532 pub qpack_max_table_capacity: Option<u64>,
533 pub qpack_blocked_streams: Option<u64>,
534 }
535
536 struct QpackStreams {
537 pub encoder_stream_id: Option<u64>,
538 pub decoder_stream_id: Option<u64>,
539 }
540
541 /// An HTTP/3 connection.
542 pub struct Connection {
543 is_server: bool,
544
545 next_request_stream_id: u64,
546 next_uni_stream_id: u64,
547
548 streams: HashMap<u64, stream::Stream>,
549
550 local_settings: ConnectionSettings,
551 peer_settings: ConnectionSettings,
552
553 control_stream_id: Option<u64>,
554 peer_control_stream_id: Option<u64>,
555
556 qpack_encoder: qpack::Encoder,
557 qpack_decoder: qpack::Decoder,
558
559 local_qpack_streams: QpackStreams,
560 peer_qpack_streams: QpackStreams,
561
562 max_push_id: u64,
563
564 finished_streams: VecDeque<u64>,
565
566 frames_greased: bool,
567
568 local_goaway_id: Option<u64>,
569 peer_goaway_id: Option<u64>,
570 }
571
572 impl Connection {
new(config: &Config, is_server: bool) -> Result<Connection>573 fn new(config: &Config, is_server: bool) -> Result<Connection> {
574 let initial_uni_stream_id = if is_server { 0x3 } else { 0x2 };
575
576 Ok(Connection {
577 is_server,
578
579 next_request_stream_id: 0,
580
581 next_uni_stream_id: initial_uni_stream_id,
582
583 streams: HashMap::new(),
584
585 local_settings: ConnectionSettings {
586 max_header_list_size: config.max_header_list_size,
587 qpack_max_table_capacity: config.qpack_max_table_capacity,
588 qpack_blocked_streams: config.qpack_blocked_streams,
589 },
590
591 peer_settings: ConnectionSettings {
592 max_header_list_size: None,
593 qpack_max_table_capacity: None,
594 qpack_blocked_streams: None,
595 },
596
597 control_stream_id: None,
598 peer_control_stream_id: None,
599
600 qpack_encoder: qpack::Encoder::new(),
601 qpack_decoder: qpack::Decoder::new(),
602
603 local_qpack_streams: QpackStreams {
604 encoder_stream_id: None,
605 decoder_stream_id: None,
606 },
607
608 peer_qpack_streams: QpackStreams {
609 encoder_stream_id: None,
610 decoder_stream_id: None,
611 },
612
613 max_push_id: 0,
614
615 finished_streams: VecDeque::new(),
616
617 frames_greased: false,
618
619 local_goaway_id: None,
620 peer_goaway_id: None,
621 })
622 }
623
624 /// Creates a new HTTP/3 connection using the provided QUIC connection.
625 ///
626 /// This will also initiate the HTTP/3 handshake with the peer by opening
627 /// all control streams (including QPACK) and sending the local settings.
with_transport( conn: &mut super::Connection, config: &Config, ) -> Result<Connection>628 pub fn with_transport(
629 conn: &mut super::Connection, config: &Config,
630 ) -> Result<Connection> {
631 let mut http3_conn = Connection::new(config, conn.is_server)?;
632
633 http3_conn.send_settings(conn)?;
634
635 // Try opening QPACK streams, but ignore errors if it fails since we
636 // don't need them right now.
637 http3_conn.open_qpack_encoder_stream(conn).ok();
638 http3_conn.open_qpack_decoder_stream(conn).ok();
639
640 if conn.grease {
641 // Try opening a GREASE stream, but ignore errors since it's not
642 // critical.
643 http3_conn.open_grease_stream(conn).ok();
644 }
645
646 Ok(http3_conn)
647 }
648
649 /// Sends an HTTP/3 request.
650 ///
651 /// The request is encoded from the provided list of headers without a
652 /// body, and sent on a newly allocated stream. To include a body,
653 /// set `fin` as `false` and subsequently call [`send_body()`] with the
654 /// same `conn` and the `stream_id` returned from this method.
655 ///
656 /// On success the newly allocated stream ID is returned.
657 ///
658 /// The [`StreamBlocked`] error is returned when the underlying QUIC stream
659 /// doesn't have enough capacity for the operation to complete. When this
660 /// happens the application should retry the operation once the stream is
661 /// reported as writable again.
662 ///
663 /// [`send_body()`]: struct.Connection.html#method.send_body
664 /// [`StreamBlocked`]: enum.Error.html#variant.StreamBlocked
send_request<T: NameValue>( &mut self, conn: &mut super::Connection, headers: &[T], fin: bool, ) -> Result<u64>665 pub fn send_request<T: NameValue>(
666 &mut self, conn: &mut super::Connection, headers: &[T], fin: bool,
667 ) -> Result<u64> {
668 // If we received a GOAWAY from the peer, MUST NOT initiate new
669 // requests.
670 if self.peer_goaway_id.is_some() {
671 return Err(Error::FrameUnexpected);
672 }
673
674 let stream_id = self.next_request_stream_id;
675
676 self.streams
677 .insert(stream_id, stream::Stream::new(stream_id, true));
678
679 // The underlying QUIC stream does not exist yet, so calls to e.g.
680 // stream_capacity() will fail. By writing a 0-length buffer, we force
681 // the creation of the QUIC stream state, without actually writing
682 // anything.
683 conn.stream_send(stream_id, b"", false)?;
684
685 self.send_headers(conn, stream_id, headers, fin)?;
686
687 // To avoid skipping stream IDs, we only calculate the next available
688 // stream ID when a request has been successfully buffered.
689 self.next_request_stream_id = self
690 .next_request_stream_id
691 .checked_add(4)
692 .ok_or(Error::IdError)?;
693
694 Ok(stream_id)
695 }
696
697 /// Sends an HTTP/3 response on the specified stream with default priority.
698 ///
699 /// This method sends the provided `headers` without a body. To include a
700 /// body, set `fin` as `false` and subsequently call [`send_body()`] with
701 /// the same `conn` and `stream_id`.
702 ///
703 /// The [`StreamBlocked`] error is returned when the underlying QUIC stream
704 /// doesn't have enough capacity for the operation to complete. When this
705 /// happens the application should retry the operation once the stream is
706 /// reported as writable again.
707 ///
708 /// [`send_body()`]: struct.Connection.html#method.send_body
709 /// [`StreamBlocked`]: enum.Error.html#variant.StreamBlocked
send_response<T: NameValue>( &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T], fin: bool, ) -> Result<()>710 pub fn send_response<T: NameValue>(
711 &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T],
712 fin: bool,
713 ) -> Result<()> {
714 let priority = "u=3";
715
716 self.send_response_with_priority(
717 conn, stream_id, headers, priority, fin,
718 )?;
719
720 Ok(())
721 }
722
723 /// Sends an HTTP/3 response on the specified stream with specified
724 /// priority.
725 ///
726 /// The [`StreamBlocked`] error is returned when the underlying QUIC stream
727 /// doesn't have enough capacity for the operation to complete. When this
728 /// happens the application should retry the operation once the stream is
729 /// reported as writable again.
730 ///
731 /// [`StreamBlocked`]: enum.Error.html#variant.StreamBlocked
send_response_with_priority<T: NameValue>( &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T], priority: &str, fin: bool, ) -> Result<()>732 pub fn send_response_with_priority<T: NameValue>(
733 &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T],
734 priority: &str, fin: bool,
735 ) -> Result<()> {
736 if !self.streams.contains_key(&stream_id) {
737 return Err(Error::FrameUnexpected);
738 }
739
740 let mut urgency = 3;
741 let mut incremental = false;
742
743 for param in priority.split(',') {
744 if param.trim() == "i" {
745 incremental = true;
746 continue;
747 }
748
749 if param.trim().starts_with("u=") {
750 // u is an sh-integer (an i64) but it has a constrained range of
751 // 0-7. So detect anything outside that range and clamp it to
752 // the lowest urgency in order to avoid it interfering with
753 // valid items.
754 //
755 // TODO: this also detects when u is not an sh-integer and
756 // clamps it in the same way. A real structured header parser
757 // would actually fail to parse.
758 let mut u =
759 i64::from_str_radix(param.rsplit('=').next().unwrap(), 10)
760 .unwrap_or(7);
761
762 if u < 0 || u > 7 {
763 u = 7;
764 }
765
766 // The HTTP/3 urgency needs to be shifted into the quiche
767 // urgency range.
768 urgency = (u as u8).saturating_add(PRIORITY_URGENCY_OFFSET);
769 }
770 }
771
772 conn.stream_priority(stream_id, urgency, incremental)?;
773
774 self.send_headers(conn, stream_id, headers, fin)?;
775
776 Ok(())
777 }
778
encode_header_block<T: NameValue>( &mut self, headers: &[T], ) -> Result<Vec<u8>>779 fn encode_header_block<T: NameValue>(
780 &mut self, headers: &[T],
781 ) -> Result<Vec<u8>> {
782 let headers_len = headers
783 .iter()
784 .fold(0, |acc, h| acc + h.value().len() + h.name().len() + 32);
785
786 let mut header_block = vec![0; headers_len];
787 let len = self
788 .qpack_encoder
789 .encode(&headers, &mut header_block)
790 .map_err(|_| Error::InternalError)?;
791
792 header_block.truncate(len);
793
794 Ok(header_block)
795 }
796
send_headers<T: NameValue>( &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T], fin: bool, ) -> Result<()>797 fn send_headers<T: NameValue>(
798 &mut self, conn: &mut super::Connection, stream_id: u64, headers: &[T],
799 fin: bool,
800 ) -> Result<()> {
801 let mut d = [42; 10];
802 let mut b = octets::OctetsMut::with_slice(&mut d);
803
804 if !self.frames_greased && conn.grease {
805 self.send_grease_frames(conn, stream_id)?;
806 self.frames_greased = true;
807 }
808
809 let stream_cap = conn.stream_capacity(stream_id)?;
810
811 let header_block = self.encode_header_block(headers)?;
812
813 let overhead = octets::varint_len(frame::HEADERS_FRAME_TYPE_ID) +
814 octets::varint_len(header_block.len() as u64);
815
816 if stream_cap < overhead + header_block.len() {
817 return Err(Error::StreamBlocked);
818 }
819
820 trace!(
821 "{} tx frm HEADERS stream={} len={} fin={}",
822 conn.trace_id(),
823 stream_id,
824 header_block.len(),
825 fin
826 );
827
828 b.put_varint(frame::HEADERS_FRAME_TYPE_ID)?;
829 b.put_varint(header_block.len() as u64)?;
830 let off = b.off();
831 conn.stream_send(stream_id, &d[..off], false)?;
832
833 // Sending header block separately avoids unnecessary copy.
834 conn.stream_send(stream_id, &header_block, fin)?;
835
836 if let Some(s) = self.streams.get_mut(&stream_id) {
837 s.initialize_local();
838 }
839
840 if fin && conn.stream_finished(stream_id) {
841 self.streams.remove(&stream_id);
842 }
843
844 Ok(())
845 }
846
847 /// Sends an HTTP/3 body chunk on the given stream.
848 ///
849 /// On success the number of bytes written is returned, or [`Done`] if no
850 /// bytes could be written (e.g. because the stream is blocked).
851 ///
852 /// Note that the number of written bytes returned can be lower than the
853 /// length of the input buffer when the underlying QUIC stream doesn't have
854 /// enough capacity for the operation to complete.
855 ///
856 /// When a partial write happens (including when [`Done`] is returned) the
857 /// application should retry the operation once the stream is reported as
858 /// writable again.
859 ///
860 /// [`Done`]: enum.Error.html#variant.Done
send_body( &mut self, conn: &mut super::Connection, stream_id: u64, body: &[u8], fin: bool, ) -> Result<usize>861 pub fn send_body(
862 &mut self, conn: &mut super::Connection, stream_id: u64, body: &[u8],
863 fin: bool,
864 ) -> Result<usize> {
865 let mut d = [42; 10];
866 let mut b = octets::OctetsMut::with_slice(&mut d);
867
868 // Validate that it is sane to send data on the stream.
869 if stream_id % 4 != 0 {
870 return Err(Error::FrameUnexpected);
871 }
872
873 match self.streams.get(&stream_id) {
874 Some(s) =>
875 if !s.local_initialized() {
876 return Err(Error::FrameUnexpected);
877 },
878
879 None => {
880 return Err(Error::FrameUnexpected);
881 },
882 };
883
884 let overhead = octets::varint_len(frame::DATA_FRAME_TYPE_ID) +
885 octets::varint_len(body.len() as u64);
886
887 let stream_cap = conn.stream_capacity(stream_id)?;
888
889 // Make sure there is enough capacity to send the frame header and at
890 // least one byte of frame payload (this to avoid sending 0-length DATA
891 // frames).
892 if stream_cap <= overhead {
893 return Err(Error::Done);
894 }
895
896 // Cap the frame payload length to the stream's capacity.
897 let body_len = std::cmp::min(body.len(), stream_cap - overhead);
898
899 // If we can't send the entire body, set the fin flag to false so the
900 // application can try again later.
901 let fin = if body_len != body.len() { false } else { fin };
902
903 trace!(
904 "{} tx frm DATA stream={} len={} fin={}",
905 conn.trace_id(),
906 stream_id,
907 body_len,
908 fin
909 );
910
911 b.put_varint(frame::DATA_FRAME_TYPE_ID)?;
912 b.put_varint(body_len as u64)?;
913 let off = b.off();
914 conn.stream_send(stream_id, &d[..off], false)?;
915
916 // Return how many bytes were written, excluding the frame header.
917 // Sending body separately avoids unnecessary copy.
918 let written = conn.stream_send(stream_id, &body[..body_len], fin)?;
919
920 if fin && written == body.len() && conn.stream_finished(stream_id) {
921 self.streams.remove(&stream_id);
922 }
923
924 Ok(written)
925 }
926
927 /// Sends an HTTP/3 DATAGRAM with the specified flow ID.
send_dgram( &mut self, conn: &mut super::Connection, flow_id: u64, buf: &[u8], ) -> Result<()>928 pub fn send_dgram(
929 &mut self, conn: &mut super::Connection, flow_id: u64, buf: &[u8],
930 ) -> Result<()> {
931 let len = octets::varint_len(flow_id) + buf.len();
932 let mut d = vec![0; len as usize];
933 let mut b = octets::OctetsMut::with_slice(&mut d);
934
935 b.put_varint(flow_id)?;
936 b.put_bytes(buf)?;
937
938 conn.dgram_send(&d)?;
939
940 Ok(())
941 }
942
943 /// Reads a DATAGRAM into the provided buffer.
944 ///
945 /// Applications should call this method whenever the [`poll()`] method
946 /// returns a [`Datagram`] event.
947 ///
948 /// On success the DATAGRAM data is returned, with length and Flow ID and
949 /// length of the Flow ID.
950 ///
951 /// [`Done`] is returned if there is no data to read.
952 ///
953 /// [`BufferTooShort`] is returned if the provided buffer is too small for
954 /// the data.
955 ///
956 /// [`poll()`]: struct.Connection.html#method.poll
957 /// [`Datagram`]: enum.Event.html#variant.Datagram
958 /// [`Done`]: enum.Error.html#variant.Done
959 /// [`BufferTooShort`]: enum.Error.html#variant.BufferTooShort
recv_dgram( &mut self, conn: &mut super::Connection, buf: &mut [u8], ) -> Result<(usize, u64, usize)>960 pub fn recv_dgram(
961 &mut self, conn: &mut super::Connection, buf: &mut [u8],
962 ) -> Result<(usize, u64, usize)> {
963 let len = conn.dgram_recv(buf)?;
964 let mut b = octets::Octets::with_slice(buf);
965 let flow_id = b.get_varint()?;
966 Ok((len, flow_id, b.off()))
967 }
968
969 /// Returns the maximum HTTP/3 DATAGRAM payload that can be sent.
dgram_max_writable_len( &self, conn: &super::Connection, flow_id: u64, ) -> Option<usize>970 pub fn dgram_max_writable_len(
971 &self, conn: &super::Connection, flow_id: u64,
972 ) -> Option<usize> {
973 let flow_id_len = octets::varint_len(flow_id);
974 match conn.dgram_max_writable_len() {
975 None => None,
976 Some(len) => len.checked_sub(flow_id_len),
977 }
978 }
979
980 /// Reads request or response body data into the provided buffer.
981 ///
982 /// Applications should call this method whenever the [`poll()`] method
983 /// returns a [`Data`] event.
984 ///
985 /// On success the amount of bytes read is returned, or [`Done`] if there
986 /// is no data to read.
987 ///
988 /// [`poll()`]: struct.Connection.html#method.poll
989 /// [`Data`]: enum.Event.html#variant.Data
990 /// [`Done`]: enum.Error.html#variant.Done
recv_body( &mut self, conn: &mut super::Connection, stream_id: u64, out: &mut [u8], ) -> Result<usize>991 pub fn recv_body(
992 &mut self, conn: &mut super::Connection, stream_id: u64, out: &mut [u8],
993 ) -> Result<usize> {
994 let stream = self.streams.get_mut(&stream_id).ok_or(Error::Done)?;
995
996 if stream.state() != stream::State::Data {
997 return Err(Error::Done);
998 }
999
1000 let read = stream.try_consume_data(conn, out)?;
1001
1002 // While body is being received, the stream is marked as finished only
1003 // when all data is read by the application.
1004 if conn.stream_finished(stream_id) {
1005 self.finished_streams.push_back(stream_id);
1006 }
1007
1008 Ok(read)
1009 }
1010
1011 /// Processes HTTP/3 data received from the peer.
1012 ///
1013 /// On success it returns an [`Event`] and an ID.
1014 ///
1015 /// The events [`Headers`], [`Data`] and [`Finished`] return a stream ID,
1016 /// which is used in methods [`recv_body()`], [`send_response()`] or
1017 /// [`send_body()`].
1018 ///
1019 /// The event [`Datagram`] returns a flow ID.
1020 ///
1021 /// The event [`GoAway`] returns an ID that depends on the connection role.
1022 /// A client receives the largest processed stream ID. A server receives the
1023 /// the largest permitted push ID.
1024 ///
1025 /// If an error occurs while processing data, the connection is closed with
1026 /// the appropriate error code, using the transport's [`close()`] method.
1027 ///
1028 /// [`Event`]: enum.Event.html
1029 /// [`Headers`]: enum.Event.html#variant.Headers
1030 /// [`Data`]: enum.Event.html#variant.Data
1031 /// [`Finished`]: enum.Event.html#variant.Finished
1032 /// [`Datagram`]: enum.Event.html#variant.Datagram
1033 /// [`GoAway`]: enum.Event.html#variant.GoAWay
1034 /// [`recv_body()`]: struct.Connection.html#method.recv_body
1035 /// [`send_response()`]: struct.Connection.html#method.send_response
1036 /// [`send_body()`]: struct.Connection.html#method.send_body
1037 /// [`recv_dgram()`]: struct.Connection.html#method.recv_dgram
1038 /// [`close()`]: ../struct.Connection.html#method.close
poll(&mut self, conn: &mut super::Connection) -> Result<(u64, Event)>1039 pub fn poll(&mut self, conn: &mut super::Connection) -> Result<(u64, Event)> {
1040 // When connection close is initiated by the local application (e.g. due
1041 // to a protocol error), the connection itself might be in a broken
1042 // state, so return early.
1043 if conn.error.is_some() || conn.app_error.is_some() {
1044 return Err(Error::Done);
1045 }
1046
1047 // Process control streams first.
1048 if let Some(stream_id) = self.peer_control_stream_id {
1049 match self.process_control_stream(conn, stream_id) {
1050 Ok(ev) => return Ok(ev),
1051
1052 Err(Error::Done) => (),
1053
1054 Err(e) => return Err(e),
1055 };
1056 }
1057
1058 if let Some(stream_id) = self.peer_qpack_streams.encoder_stream_id {
1059 match self.process_control_stream(conn, stream_id) {
1060 Ok(ev) => return Ok(ev),
1061
1062 Err(Error::Done) => (),
1063
1064 Err(e) => return Err(e),
1065 };
1066 }
1067
1068 if let Some(stream_id) = self.peer_qpack_streams.decoder_stream_id {
1069 match self.process_control_stream(conn, stream_id) {
1070 Ok(ev) => return Ok(ev),
1071
1072 Err(Error::Done) => (),
1073
1074 Err(e) => return Err(e),
1075 };
1076 }
1077
1078 // Process finished streams list.
1079 if let Some(finished) = self.finished_streams.pop_front() {
1080 return Ok((finished, Event::Finished));
1081 }
1082
1083 // Process DATAGRAMs
1084 let mut d = [0; 8];
1085
1086 match conn.dgram_recv_peek(&mut d, 8) {
1087 Ok(_) => {
1088 let mut b = octets::Octets::with_slice(&d);
1089 let flow_id = b.get_varint()?;
1090 return Ok((flow_id, Event::Datagram));
1091 },
1092
1093 Err(crate::Error::Done) => (),
1094
1095 Err(e) => return Err(Error::TransportError(e)),
1096 };
1097
1098 // Process HTTP/3 data from readable streams.
1099 for s in conn.readable() {
1100 trace!("{} stream id {} is readable", conn.trace_id(), s);
1101
1102 let ev = match self.process_readable_stream(conn, s) {
1103 Ok(v) => Some(v),
1104
1105 Err(Error::Done) => None,
1106
1107 Err(e) => return Err(e),
1108 };
1109
1110 if conn.stream_finished(s) {
1111 self.finished_streams.push_back(s);
1112 }
1113
1114 // TODO: check if stream is completed so it can be freed
1115
1116 if let Some(ev) = ev {
1117 return Ok(ev);
1118 }
1119 }
1120
1121 Err(Error::Done)
1122 }
1123
1124 /// Sends a GOAWAY frame to initiate graceful connection closure.
1125 ///
1126 /// When quiche is used in the server role, the `id` parameter is the stream
1127 /// ID of the highest processed request. This can be any valid ID between 0
1128 /// and 2^62-4. However, the ID cannot be increased. Failure to satisfy
1129 /// these conditions will return an error.
1130 ///
1131 /// This method does not close the QUIC connection. Applications are
1132 /// required to call [`close()`] themselves.
1133 ///
1134 /// [`close()`]: ../struct.Connection.html#method.close
send_goaway( &mut self, conn: &mut super::Connection, id: u64, ) -> Result<()>1135 pub fn send_goaway(
1136 &mut self, conn: &mut super::Connection, id: u64,
1137 ) -> Result<()> {
1138 if !self.is_server {
1139 // TODO: server push
1140 return Ok(());
1141 }
1142
1143 if self.is_server && id % 4 != 0 {
1144 return Err(Error::IdError);
1145 }
1146
1147 if let Some(sent_id) = self.local_goaway_id {
1148 if id > sent_id {
1149 return Err(Error::IdError);
1150 }
1151 }
1152
1153 if let Some(stream_id) = self.control_stream_id {
1154 let mut d = [42; 10];
1155 let mut b = octets::OctetsMut::with_slice(&mut d);
1156
1157 let frame = frame::Frame::GoAway { id };
1158
1159 let wire_len = frame.to_bytes(&mut b)?;
1160 let stream_cap = conn.stream_capacity(stream_id)?;
1161
1162 if stream_cap < wire_len {
1163 return Err(Error::StreamBlocked);
1164 }
1165
1166 trace!("{} tx frm {:?}", conn.trace_id(), frame);
1167
1168 let off = b.off();
1169 conn.stream_send(stream_id, &d[..off], false)?;
1170
1171 self.local_goaway_id = Some(id);
1172 }
1173
1174 Ok(())
1175 }
1176
open_uni_stream( &mut self, conn: &mut super::Connection, ty: u64, ) -> Result<u64>1177 fn open_uni_stream(
1178 &mut self, conn: &mut super::Connection, ty: u64,
1179 ) -> Result<u64> {
1180 let stream_id = self.next_uni_stream_id;
1181
1182 let mut d = [0; 8];
1183 let mut b = octets::OctetsMut::with_slice(&mut d);
1184
1185 match ty {
1186 // Control and QPACK streams are the most important to schedule.
1187 stream::HTTP3_CONTROL_STREAM_TYPE_ID |
1188 stream::QPACK_ENCODER_STREAM_TYPE_ID |
1189 stream::QPACK_DECODER_STREAM_TYPE_ID => {
1190 conn.stream_priority(stream_id, 0, true)?;
1191 },
1192
1193 // TODO: Server push
1194 stream::HTTP3_PUSH_STREAM_TYPE_ID => (),
1195
1196 // Anything else is a GREASE stream, so make it the least important.
1197 _ => {
1198 conn.stream_priority(stream_id, 255, true)?;
1199 },
1200 }
1201
1202 conn.stream_send(stream_id, b.put_varint(ty)?, false)?;
1203
1204 // To avoid skipping stream IDs, we only calculate the next available
1205 // stream ID when data has been successfully buffered.
1206 self.next_uni_stream_id = self
1207 .next_uni_stream_id
1208 .checked_add(4)
1209 .ok_or(Error::IdError)?;
1210
1211 Ok(stream_id)
1212 }
1213
open_qpack_encoder_stream( &mut self, conn: &mut super::Connection, ) -> Result<()>1214 fn open_qpack_encoder_stream(
1215 &mut self, conn: &mut super::Connection,
1216 ) -> Result<()> {
1217 self.local_qpack_streams.encoder_stream_id = Some(
1218 self.open_uni_stream(conn, stream::QPACK_ENCODER_STREAM_TYPE_ID)?,
1219 );
1220
1221 Ok(())
1222 }
1223
open_qpack_decoder_stream( &mut self, conn: &mut super::Connection, ) -> Result<()>1224 fn open_qpack_decoder_stream(
1225 &mut self, conn: &mut super::Connection,
1226 ) -> Result<()> {
1227 self.local_qpack_streams.decoder_stream_id = Some(
1228 self.open_uni_stream(conn, stream::QPACK_DECODER_STREAM_TYPE_ID)?,
1229 );
1230
1231 Ok(())
1232 }
1233
1234 /// Send GREASE frames on the provided stream ID.
send_grease_frames( &mut self, conn: &mut super::Connection, stream_id: u64, ) -> Result<()>1235 fn send_grease_frames(
1236 &mut self, conn: &mut super::Connection, stream_id: u64,
1237 ) -> Result<()> {
1238 let mut d = [0; 8];
1239
1240 let stream_cap = conn.stream_capacity(stream_id)?;
1241
1242 let grease_frame1 = grease_value();
1243 let grease_frame2 = grease_value();
1244 let grease_payload = b"GREASE is the word";
1245
1246 let overhead = octets::varint_len(grease_frame1) + // frame type
1247 1 + // payload len
1248 octets::varint_len(grease_frame2) + // frame type
1249 1 + // payload len
1250 grease_payload.len(); // payload
1251
1252 // Don't send GREASE if there is not enough capacity for it. Greasing
1253 // will _not_ be attempted again later on.
1254 if stream_cap < overhead {
1255 return Ok(());
1256 }
1257
1258 trace!("{} tx frm GREASE stream={}", conn.trace_id(), stream_id);
1259
1260 // Empty GREASE frame.
1261 let mut b = octets::OctetsMut::with_slice(&mut d);
1262 conn.stream_send(stream_id, b.put_varint(grease_frame1)?, false)?;
1263
1264 let mut b = octets::OctetsMut::with_slice(&mut d);
1265 conn.stream_send(stream_id, b.put_varint(0)?, false)?;
1266
1267 // GREASE frame with payload.
1268 let mut b = octets::OctetsMut::with_slice(&mut d);
1269 conn.stream_send(stream_id, b.put_varint(grease_frame2)?, false)?;
1270
1271 let mut b = octets::OctetsMut::with_slice(&mut d);
1272 conn.stream_send(stream_id, b.put_varint(18)?, false)?;
1273
1274 conn.stream_send(stream_id, grease_payload, false)?;
1275
1276 Ok(())
1277 }
1278
1279 /// Opens a new unidirectional stream with a GREASE type and sends some
1280 /// unframed payload.
open_grease_stream(&mut self, conn: &mut super::Connection) -> Result<()>1281 fn open_grease_stream(&mut self, conn: &mut super::Connection) -> Result<()> {
1282 match self.open_uni_stream(conn, grease_value()) {
1283 Ok(stream_id) => {
1284 trace!("{} open GREASE stream {}", conn.trace_id(), stream_id);
1285
1286 conn.stream_send(stream_id, b"GREASE is the word", false)?;
1287 },
1288
1289 Err(Error::IdError) => {
1290 trace!("{} GREASE stream blocked", conn.trace_id(),);
1291
1292 return Ok(());
1293 },
1294
1295 Err(e) => return Err(e),
1296 };
1297
1298 Ok(())
1299 }
1300
1301 /// Sends SETTINGS frame based on HTTP/3 configuration.
send_settings(&mut self, conn: &mut super::Connection) -> Result<()>1302 fn send_settings(&mut self, conn: &mut super::Connection) -> Result<()> {
1303 self.control_stream_id = Some(
1304 self.open_uni_stream(conn, stream::HTTP3_CONTROL_STREAM_TYPE_ID)?,
1305 );
1306
1307 let grease = if conn.grease {
1308 Some((grease_value(), grease_value()))
1309 } else {
1310 None
1311 };
1312
1313 let frame = frame::Frame::Settings {
1314 max_header_list_size: self.local_settings.max_header_list_size,
1315 qpack_max_table_capacity: self
1316 .local_settings
1317 .qpack_max_table_capacity,
1318 qpack_blocked_streams: self.local_settings.qpack_blocked_streams,
1319 grease,
1320 };
1321
1322 let mut d = [42; 128];
1323 let mut b = octets::OctetsMut::with_slice(&mut d);
1324
1325 frame.to_bytes(&mut b)?;
1326
1327 let off = b.off();
1328
1329 if let Some(id) = self.control_stream_id {
1330 conn.stream_send(id, &d[..off], false)?;
1331 }
1332
1333 Ok(())
1334 }
1335
process_control_stream( &mut self, conn: &mut super::Connection, stream_id: u64, ) -> Result<(u64, Event)>1336 fn process_control_stream(
1337 &mut self, conn: &mut super::Connection, stream_id: u64,
1338 ) -> Result<(u64, Event)> {
1339 if conn.stream_finished(stream_id) {
1340 conn.close(
1341 true,
1342 Error::ClosedCriticalStream.to_wire(),
1343 b"Critical stream closed.",
1344 )?;
1345
1346 return Err(Error::ClosedCriticalStream);
1347 }
1348
1349 match self.process_readable_stream(conn, stream_id) {
1350 Ok(ev) => return Ok(ev),
1351
1352 Err(Error::Done) => (),
1353
1354 Err(e) => return Err(e),
1355 };
1356
1357 if conn.stream_finished(stream_id) {
1358 conn.close(
1359 true,
1360 Error::ClosedCriticalStream.to_wire(),
1361 b"Critical stream closed.",
1362 )?;
1363
1364 return Err(Error::ClosedCriticalStream);
1365 }
1366
1367 Err(Error::Done)
1368 }
1369
process_readable_stream( &mut self, conn: &mut super::Connection, stream_id: u64, ) -> Result<(u64, Event)>1370 fn process_readable_stream(
1371 &mut self, conn: &mut super::Connection, stream_id: u64,
1372 ) -> Result<(u64, Event)> {
1373 self.streams
1374 .entry(stream_id)
1375 .or_insert_with(|| stream::Stream::new(stream_id, false));
1376
1377 // We need to get a fresh reference to the stream for each
1378 // iteration, to avoid borrowing `self` for the entire duration
1379 // of the loop, because we'll need to borrow it again in the
1380 // `State::FramePayload` case below.
1381 while let Some(stream) = self.streams.get_mut(&stream_id) {
1382 match stream.state() {
1383 stream::State::StreamType => {
1384 stream.try_fill_buffer(conn)?;
1385
1386 let varint = match stream.try_consume_varint() {
1387 Ok(v) => v,
1388
1389 Err(_) => continue,
1390 };
1391
1392 let ty = stream::Type::deserialize(varint)?;
1393
1394 if let Err(e) = stream.set_ty(ty) {
1395 conn.close(true, e.to_wire(), b"")?;
1396 return Err(e);
1397 }
1398
1399 match &ty {
1400 stream::Type::Control => {
1401 // Only one control stream allowed.
1402 if self.peer_control_stream_id.is_some() {
1403 conn.close(
1404 true,
1405 Error::StreamCreationError.to_wire(),
1406 b"Received multiple control streams",
1407 )?;
1408
1409 return Err(Error::StreamCreationError);
1410 }
1411
1412 trace!(
1413 "{} open peer's control stream {}",
1414 conn.trace_id(),
1415 stream_id
1416 );
1417
1418 self.peer_control_stream_id = Some(stream_id);
1419 },
1420
1421 stream::Type::Push => {
1422 // Only clients can receive push stream.
1423 if self.is_server {
1424 conn.close(
1425 true,
1426 Error::StreamCreationError.to_wire(),
1427 b"Server received push stream.",
1428 )?;
1429
1430 return Err(Error::StreamCreationError);
1431 }
1432 },
1433
1434 stream::Type::QpackEncoder => {
1435 // Only one qpack encoder stream allowed.
1436 if self.peer_qpack_streams.encoder_stream_id.is_some()
1437 {
1438 conn.close(
1439 true,
1440 Error::StreamCreationError.to_wire(),
1441 b"Received multiple QPACK encoder streams",
1442 )?;
1443
1444 return Err(Error::StreamCreationError);
1445 }
1446
1447 self.peer_qpack_streams.encoder_stream_id =
1448 Some(stream_id);
1449 },
1450
1451 stream::Type::QpackDecoder => {
1452 // Only one qpack decoder allowed.
1453 if self.peer_qpack_streams.decoder_stream_id.is_some()
1454 {
1455 conn.close(
1456 true,
1457 Error::StreamCreationError.to_wire(),
1458 b"Received multiple QPACK decoder streams",
1459 )?;
1460
1461 return Err(Error::StreamCreationError);
1462 }
1463
1464 self.peer_qpack_streams.decoder_stream_id =
1465 Some(stream_id);
1466 },
1467
1468 stream::Type::Unknown => {
1469 // Unknown stream types are ignored.
1470 // TODO: we MAY send STOP_SENDING
1471 },
1472
1473 stream::Type::Request => unreachable!(),
1474 }
1475 },
1476
1477 stream::State::PushId => {
1478 stream.try_fill_buffer(conn)?;
1479
1480 let varint = match stream.try_consume_varint() {
1481 Ok(v) => v,
1482
1483 Err(_) => continue,
1484 };
1485
1486 if let Err(e) = stream.set_push_id(varint) {
1487 conn.close(true, e.to_wire(), b"")?;
1488 return Err(e);
1489 }
1490 },
1491
1492 stream::State::FrameType => {
1493 stream.try_fill_buffer(conn)?;
1494
1495 let varint = match stream.try_consume_varint() {
1496 Ok(v) => v,
1497
1498 Err(_) => continue,
1499 };
1500
1501 match stream.set_frame_type(varint) {
1502 Err(Error::FrameUnexpected) => {
1503 let msg = format!("Unexpected frame type {}", varint);
1504
1505 conn.close(
1506 true,
1507 Error::FrameUnexpected.to_wire(),
1508 msg.as_bytes(),
1509 )?;
1510
1511 return Err(Error::FrameUnexpected);
1512 },
1513
1514 Err(e) => {
1515 conn.close(
1516 true,
1517 e.to_wire(),
1518 b"Error handling frame.",
1519 )?;
1520
1521 return Err(e);
1522 },
1523
1524 _ => (),
1525 }
1526 },
1527
1528 stream::State::FramePayloadLen => {
1529 stream.try_fill_buffer(conn)?;
1530
1531 let varint = match stream.try_consume_varint() {
1532 Ok(v) => v,
1533
1534 Err(_) => continue,
1535 };
1536
1537 if let Err(e) = stream.set_frame_payload_len(varint) {
1538 conn.close(true, e.to_wire(), b"")?;
1539 return Err(e);
1540 }
1541 },
1542
1543 stream::State::FramePayload => {
1544 stream.try_fill_buffer(conn)?;
1545
1546 let frame = match stream.try_consume_frame() {
1547 Ok(frame) => frame,
1548
1549 Err(Error::Done) => return Err(Error::Done),
1550
1551 Err(e) => {
1552 conn.close(
1553 true,
1554 e.to_wire(),
1555 b"Error handling frame.",
1556 )?;
1557
1558 return Err(e);
1559 },
1560 };
1561
1562 match self.process_frame(conn, stream_id, frame) {
1563 Ok(ev) => return Ok(ev),
1564
1565 Err(Error::Done) => (),
1566
1567 Err(e) => return Err(e),
1568 };
1569 },
1570
1571 stream::State::Data => {
1572 return Ok((stream_id, Event::Data));
1573 },
1574
1575 stream::State::QpackInstruction => {
1576 let mut d = [0; 4096];
1577
1578 // Read data from the stream and discard immediately.
1579 loop {
1580 conn.stream_recv(stream_id, &mut d)?;
1581 }
1582 },
1583
1584 stream::State::Drain => {
1585 // Discard incoming data on the stream.
1586 conn.stream_shutdown(stream_id, crate::Shutdown::Read, 0)?;
1587
1588 break;
1589 },
1590 }
1591 }
1592
1593 Err(Error::Done)
1594 }
1595
process_frame( &mut self, conn: &mut super::Connection, stream_id: u64, frame: frame::Frame, ) -> Result<(u64, Event)>1596 fn process_frame(
1597 &mut self, conn: &mut super::Connection, stream_id: u64,
1598 frame: frame::Frame,
1599 ) -> Result<(u64, Event)> {
1600 trace!(
1601 "{} rx frm {:?} stream={}",
1602 conn.trace_id(),
1603 frame,
1604 stream_id
1605 );
1606
1607 match frame {
1608 frame::Frame::Settings {
1609 max_header_list_size,
1610 qpack_max_table_capacity,
1611 qpack_blocked_streams,
1612 ..
1613 } => {
1614 self.peer_settings = ConnectionSettings {
1615 max_header_list_size,
1616 qpack_max_table_capacity,
1617 qpack_blocked_streams,
1618 };
1619 },
1620
1621 frame::Frame::Headers { header_block } => {
1622 if Some(stream_id) == self.peer_control_stream_id {
1623 conn.close(
1624 true,
1625 Error::FrameUnexpected.to_wire(),
1626 b"HEADERS received on control stream",
1627 )?;
1628
1629 return Err(Error::FrameUnexpected);
1630 }
1631
1632 // Use "infinite" as default value for max_header_list_size if
1633 // it is not configured by the application.
1634 let max_size = self
1635 .local_settings
1636 .max_header_list_size
1637 .unwrap_or(std::u64::MAX);
1638
1639 let headers = self
1640 .qpack_decoder
1641 .decode(&header_block[..], max_size)
1642 .map_err(|e| match e {
1643 qpack::Error::HeaderListTooLarge => Error::ExcessiveLoad,
1644
1645 _ => Error::QpackDecompressionFailed,
1646 })?;
1647
1648 let has_body = !conn.stream_finished(stream_id);
1649
1650 return Ok((stream_id, Event::Headers {
1651 list: headers,
1652 has_body,
1653 }));
1654 },
1655
1656 frame::Frame::Data { .. } => {
1657 if Some(stream_id) == self.peer_control_stream_id {
1658 conn.close(
1659 true,
1660 Error::FrameUnexpected.to_wire(),
1661 b"DATA received on control stream",
1662 )?;
1663
1664 return Err(Error::FrameUnexpected);
1665 }
1666
1667 // Do nothing. The Data event is returned separately.
1668 },
1669
1670 frame::Frame::GoAway { id } => {
1671 if Some(stream_id) != self.peer_control_stream_id {
1672 conn.close(
1673 true,
1674 Error::FrameUnexpected.to_wire(),
1675 b"GOAWAY received on non-control stream",
1676 )?;
1677
1678 return Err(Error::FrameUnexpected);
1679 }
1680
1681 if !self.is_server && id % 4 != 0 {
1682 conn.close(
1683 true,
1684 Error::FrameUnexpected.to_wire(),
1685 b"GOAWAY received with ID of non-request stream",
1686 )?;
1687
1688 return Err(Error::IdError);
1689 }
1690
1691 if let Some(received_id) = self.peer_goaway_id {
1692 if id > received_id {
1693 conn.close(
1694 true,
1695 Error::IdError.to_wire(),
1696 b"GOAWAY received with ID larger than previously received",
1697 )?;
1698
1699 return Err(Error::IdError);
1700 }
1701 }
1702
1703 self.peer_goaway_id = Some(id);
1704
1705 return Ok((id, Event::GoAway));
1706 },
1707
1708 frame::Frame::MaxPushId { push_id } => {
1709 if Some(stream_id) != self.peer_control_stream_id {
1710 conn.close(
1711 true,
1712 Error::FrameUnexpected.to_wire(),
1713 b"MAX_PUSH_ID received on non-control stream",
1714 )?;
1715
1716 return Err(Error::FrameUnexpected);
1717 }
1718
1719 if !self.is_server {
1720 conn.close(
1721 true,
1722 Error::FrameUnexpected.to_wire(),
1723 b"MAX_PUSH_ID received by client",
1724 )?;
1725
1726 return Err(Error::FrameUnexpected);
1727 }
1728
1729 if push_id < self.max_push_id {
1730 conn.close(
1731 true,
1732 Error::IdError.to_wire(),
1733 b"MAX_PUSH_ID reduced limit",
1734 )?;
1735
1736 return Err(Error::IdError);
1737 }
1738
1739 self.max_push_id = push_id;
1740 },
1741
1742 frame::Frame::PushPromise { .. } => {
1743 if self.is_server {
1744 conn.close(
1745 true,
1746 Error::FrameUnexpected.to_wire(),
1747 b"PUSH_PROMISE received by server",
1748 )?;
1749
1750 return Err(Error::FrameUnexpected);
1751 }
1752
1753 if stream_id % 4 != 0 {
1754 conn.close(
1755 true,
1756 Error::FrameUnexpected.to_wire(),
1757 b"PUSH_PROMISE received on non-request stream",
1758 )?;
1759
1760 return Err(Error::FrameUnexpected);
1761 }
1762
1763 // TODO: implement more checks and PUSH_PROMISE event
1764 },
1765
1766 frame::Frame::CancelPush { .. } => {
1767 if Some(stream_id) != self.peer_control_stream_id {
1768 conn.close(
1769 true,
1770 Error::FrameUnexpected.to_wire(),
1771 b"CANCEL_PUSH received on non-control stream",
1772 )?;
1773
1774 return Err(Error::FrameUnexpected);
1775 }
1776
1777 // TODO: implement CANCEL_PUSH frame
1778 },
1779
1780 frame::Frame::Unknown => (),
1781 }
1782
1783 Err(Error::Done)
1784 }
1785 }
1786
1787 /// Generates an HTTP/3 GREASE variable length integer.
grease_value() -> u641788 fn grease_value() -> u64 {
1789 let n = super::rand::rand_u64_uniform(148_764_065_110_560_899);
1790 31 * n + 33
1791 }
1792
1793 #[doc(hidden)]
1794 pub mod testing {
1795 use super::*;
1796
1797 use crate::testing;
1798
1799 /// Session is an HTTP/3 test helper structure. It holds a client, server
1800 /// and pipe that allows them to communicate.
1801 ///
1802 /// `default()` creates a session with some sensible default
1803 /// configuration. `with_configs()` allows for providing a specific
1804 /// configuration.
1805 ///
1806 /// `handshake()` performs all the steps needed to establish an HTTP/3
1807 /// connection.
1808 ///
1809 /// Some utility functions are provided that make it less verbose to send
1810 /// request, responses and individual headers. The full quiche API remains
1811 /// available for any test that need to do unconventional things (such as
1812 /// bad behaviour that triggers errors).
1813 pub struct Session {
1814 pub pipe: testing::Pipe,
1815 pub client: Connection,
1816 pub server: Connection,
1817
1818 buf: [u8; 65535],
1819 }
1820
1821 impl Session {
default() -> Result<Session>1822 pub fn default() -> Result<Session> {
1823 let mut config = crate::Config::new(crate::PROTOCOL_VERSION)?;
1824 config.load_cert_chain_from_pem_file("examples/cert.crt")?;
1825 config.load_priv_key_from_pem_file("examples/cert.key")?;
1826 config.set_application_protos(b"\x02h3")?;
1827 config.set_initial_max_data(1500);
1828 config.set_initial_max_stream_data_bidi_local(150);
1829 config.set_initial_max_stream_data_bidi_remote(150);
1830 config.set_initial_max_stream_data_uni(150);
1831 config.set_initial_max_streams_bidi(5);
1832 config.set_initial_max_streams_uni(5);
1833 config.verify_peer(false);
1834
1835 let h3_config = Config::new()?;
1836 Session::with_configs(&mut config, &h3_config)
1837 }
1838
with_configs( config: &mut crate::Config, h3_config: &Config, ) -> Result<Session>1839 pub fn with_configs(
1840 config: &mut crate::Config, h3_config: &Config,
1841 ) -> Result<Session> {
1842 Ok(Session {
1843 pipe: testing::Pipe::with_config(config)?,
1844 client: Connection::new(&h3_config, false)?,
1845 server: Connection::new(&h3_config, true)?,
1846 buf: [0; 65535],
1847 })
1848 }
1849
1850 /// Do the HTTP/3 handshake so both ends are in sane initial state.
handshake(&mut self) -> Result<()>1851 pub fn handshake(&mut self) -> Result<()> {
1852 self.pipe.handshake(&mut self.buf)?;
1853
1854 // Client streams.
1855 self.client.send_settings(&mut self.pipe.client)?;
1856 self.pipe.advance(&mut self.buf).ok();
1857
1858 self.client
1859 .open_qpack_encoder_stream(&mut self.pipe.client)?;
1860 self.pipe.advance(&mut self.buf).ok();
1861
1862 self.client
1863 .open_qpack_decoder_stream(&mut self.pipe.client)?;
1864 self.pipe.advance(&mut self.buf).ok();
1865
1866 if self.pipe.client.grease {
1867 self.client.open_grease_stream(&mut self.pipe.client)?;
1868 }
1869
1870 self.pipe.advance(&mut self.buf).ok();
1871
1872 // Server streams.
1873 self.server.send_settings(&mut self.pipe.server)?;
1874 self.pipe.advance(&mut self.buf).ok();
1875
1876 self.server
1877 .open_qpack_encoder_stream(&mut self.pipe.server)?;
1878 self.pipe.advance(&mut self.buf).ok();
1879
1880 self.server
1881 .open_qpack_decoder_stream(&mut self.pipe.server)?;
1882 self.pipe.advance(&mut self.buf).ok();
1883
1884 if self.pipe.server.grease {
1885 self.server.open_grease_stream(&mut self.pipe.server)?;
1886 }
1887
1888 self.advance().ok();
1889
1890 while self.client.poll(&mut self.pipe.client).is_ok() {
1891 // Do nothing.
1892 }
1893
1894 while self.server.poll(&mut self.pipe.server).is_ok() {
1895 // Do nothing.
1896 }
1897
1898 Ok(())
1899 }
1900
1901 /// Advances the session pipe over the buffer.
advance(&mut self) -> crate::Result<()>1902 pub fn advance(&mut self) -> crate::Result<()> {
1903 self.pipe.advance(&mut self.buf)
1904 }
1905
1906 /// Polls the client for events.
poll_client(&mut self) -> Result<(u64, Event)>1907 pub fn poll_client(&mut self) -> Result<(u64, Event)> {
1908 self.client.poll(&mut self.pipe.client)
1909 }
1910
1911 /// Polls the server for events.
poll_server(&mut self) -> Result<(u64, Event)>1912 pub fn poll_server(&mut self) -> Result<(u64, Event)> {
1913 self.server.poll(&mut self.pipe.server)
1914 }
1915
1916 /// Sends a request from client with default headers.
1917 ///
1918 /// On success it returns the newly allocated stream and the headers.
send_request(&mut self, fin: bool) -> Result<(u64, Vec<Header>)>1919 pub fn send_request(&mut self, fin: bool) -> Result<(u64, Vec<Header>)> {
1920 let req = vec![
1921 Header::new(":method", "GET"),
1922 Header::new(":scheme", "https"),
1923 Header::new(":authority", "quic.tech"),
1924 Header::new(":path", "/test"),
1925 Header::new("user-agent", "quiche-test"),
1926 ];
1927
1928 let stream =
1929 self.client.send_request(&mut self.pipe.client, &req, fin)?;
1930
1931 self.advance().ok();
1932
1933 Ok((stream, req))
1934 }
1935
1936 /// Sends a response from server with default headers.
1937 ///
1938 /// On success it returns the headers.
send_response( &mut self, stream: u64, fin: bool, ) -> Result<Vec<Header>>1939 pub fn send_response(
1940 &mut self, stream: u64, fin: bool,
1941 ) -> Result<Vec<Header>> {
1942 let resp = vec![
1943 Header::new(":status", "200"),
1944 Header::new("server", "quiche-test"),
1945 ];
1946
1947 self.server.send_response(
1948 &mut self.pipe.server,
1949 stream,
1950 &resp,
1951 fin,
1952 )?;
1953
1954 self.advance().ok();
1955
1956 Ok(resp)
1957 }
1958
1959 /// Sends some default payload from client.
1960 ///
1961 /// On success it returns the payload.
send_body_client( &mut self, stream: u64, fin: bool, ) -> Result<Vec<u8>>1962 pub fn send_body_client(
1963 &mut self, stream: u64, fin: bool,
1964 ) -> Result<Vec<u8>> {
1965 let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1966
1967 self.client
1968 .send_body(&mut self.pipe.client, stream, &bytes, fin)?;
1969
1970 self.advance().ok();
1971
1972 Ok(bytes)
1973 }
1974
1975 /// Fetches DATA payload from the server.
1976 ///
1977 /// On success it returns the number of bytes received.
recv_body_client( &mut self, stream: u64, buf: &mut [u8], ) -> Result<usize>1978 pub fn recv_body_client(
1979 &mut self, stream: u64, buf: &mut [u8],
1980 ) -> Result<usize> {
1981 self.client.recv_body(&mut self.pipe.client, stream, buf)
1982 }
1983
1984 /// Sends some default payload from server.
1985 ///
1986 /// On success it returns the payload.
send_body_server( &mut self, stream: u64, fin: bool, ) -> Result<Vec<u8>>1987 pub fn send_body_server(
1988 &mut self, stream: u64, fin: bool,
1989 ) -> Result<Vec<u8>> {
1990 let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1991
1992 self.server
1993 .send_body(&mut self.pipe.server, stream, &bytes, fin)?;
1994
1995 self.advance().ok();
1996
1997 Ok(bytes)
1998 }
1999
2000 /// Fetches DATA payload from the client.
2001 ///
2002 /// On success it returns the number of bytes received.
recv_body_server( &mut self, stream: u64, buf: &mut [u8], ) -> Result<usize>2003 pub fn recv_body_server(
2004 &mut self, stream: u64, buf: &mut [u8],
2005 ) -> Result<usize> {
2006 self.server.recv_body(&mut self.pipe.server, stream, buf)
2007 }
2008
2009 /// Sends a single HTTP/3 frame from the client.
send_frame_client( &mut self, frame: frame::Frame, stream_id: u64, fin: bool, ) -> Result<()>2010 pub fn send_frame_client(
2011 &mut self, frame: frame::Frame, stream_id: u64, fin: bool,
2012 ) -> Result<()> {
2013 let mut d = [42; 65535];
2014
2015 let mut b = octets::OctetsMut::with_slice(&mut d);
2016
2017 frame.to_bytes(&mut b)?;
2018
2019 let off = b.off();
2020 self.pipe.client.stream_send(stream_id, &d[..off], fin)?;
2021
2022 self.advance().ok();
2023
2024 Ok(())
2025 }
2026
2027 /// Sends a single HTTP/3 frame from the server.
send_frame_server( &mut self, frame: frame::Frame, stream_id: u64, fin: bool, ) -> Result<()>2028 pub fn send_frame_server(
2029 &mut self, frame: frame::Frame, stream_id: u64, fin: bool,
2030 ) -> Result<()> {
2031 let mut d = [42; 65535];
2032
2033 let mut b = octets::OctetsMut::with_slice(&mut d);
2034
2035 frame.to_bytes(&mut b)?;
2036
2037 let off = b.off();
2038 self.pipe.server.stream_send(stream_id, &d[..off], fin)?;
2039
2040 self.advance().ok();
2041
2042 Ok(())
2043 }
2044 }
2045 }
2046
2047 #[cfg(test)]
2048 mod tests {
2049 use super::*;
2050
2051 use super::testing::*;
2052
2053 #[test]
2054 /// Make sure that random GREASE values is within the specified limit.
grease_value_in_varint_limit()2055 fn grease_value_in_varint_limit() {
2056 assert!(grease_value() < 2u64.pow(62) - 1);
2057 }
2058
2059 #[test]
2060 /// Send a request with no body, get a response with no body.
request_no_body_response_no_body()2061 fn request_no_body_response_no_body() {
2062 let mut s = Session::default().unwrap();
2063 s.handshake().unwrap();
2064
2065 let (stream, req) = s.send_request(true).unwrap();
2066
2067 assert_eq!(stream, 0);
2068
2069 let ev_headers = Event::Headers {
2070 list: req,
2071 has_body: false,
2072 };
2073
2074 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2075 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2076
2077 let resp = s.send_response(stream, true).unwrap();
2078
2079 let ev_headers = Event::Headers {
2080 list: resp,
2081 has_body: false,
2082 };
2083
2084 assert_eq!(s.poll_client(), Ok((stream, ev_headers)));
2085 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2086 assert_eq!(s.poll_client(), Err(Error::Done));
2087 }
2088
2089 #[test]
2090 /// Send a request with no body, get a response with one DATA frame.
request_no_body_response_one_chunk()2091 fn request_no_body_response_one_chunk() {
2092 let mut s = Session::default().unwrap();
2093 s.handshake().unwrap();
2094
2095 let (stream, req) = s.send_request(true).unwrap();
2096 assert_eq!(stream, 0);
2097
2098 let ev_headers = Event::Headers {
2099 list: req,
2100 has_body: false,
2101 };
2102
2103 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2104
2105 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2106
2107 let resp = s.send_response(stream, false).unwrap();
2108
2109 let body = s.send_body_server(stream, true).unwrap();
2110
2111 let mut recv_buf = vec![0; body.len()];
2112
2113 let ev_headers = Event::Headers {
2114 list: resp,
2115 has_body: true,
2116 };
2117
2118 assert_eq!(s.poll_client(), Ok((stream, ev_headers)));
2119
2120 assert_eq!(s.poll_client(), Ok((stream, Event::Data)));
2121 assert_eq!(s.recv_body_client(stream, &mut recv_buf), Ok(body.len()));
2122
2123 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2124 assert_eq!(s.poll_client(), Err(Error::Done));
2125 }
2126
2127 #[test]
2128 /// Send a request with no body, get a response with multiple DATA frames.
request_no_body_response_many_chunks()2129 fn request_no_body_response_many_chunks() {
2130 let mut s = Session::default().unwrap();
2131 s.handshake().unwrap();
2132
2133 let (stream, req) = s.send_request(true).unwrap();
2134
2135 let ev_headers = Event::Headers {
2136 list: req,
2137 has_body: false,
2138 };
2139
2140 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2141 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2142
2143 let total_data_frames = 4;
2144
2145 let resp = s.send_response(stream, false).unwrap();
2146
2147 for _ in 0..total_data_frames - 1 {
2148 s.send_body_server(stream, false).unwrap();
2149 }
2150
2151 let body = s.send_body_server(stream, true).unwrap();
2152
2153 let mut recv_buf = vec![0; body.len()];
2154
2155 let ev_headers = Event::Headers {
2156 list: resp,
2157 has_body: true,
2158 };
2159
2160 assert_eq!(s.poll_client(), Ok((stream, ev_headers)));
2161
2162 for _ in 0..total_data_frames {
2163 assert_eq!(s.poll_client(), Ok((stream, Event::Data)));
2164 assert_eq!(s.recv_body_client(stream, &mut recv_buf), Ok(body.len()));
2165 }
2166
2167 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2168 assert_eq!(s.poll_client(), Err(Error::Done));
2169 }
2170
2171 #[test]
2172 /// Send a request with one DATA frame, get a response with no body.
request_one_chunk_response_no_body()2173 fn request_one_chunk_response_no_body() {
2174 let mut s = Session::default().unwrap();
2175 s.handshake().unwrap();
2176
2177 let (stream, req) = s.send_request(false).unwrap();
2178
2179 let body = s.send_body_client(stream, true).unwrap();
2180
2181 let mut recv_buf = vec![0; body.len()];
2182
2183 let ev_headers = Event::Headers {
2184 list: req,
2185 has_body: true,
2186 };
2187
2188 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2189
2190 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2191 assert_eq!(s.recv_body_server(stream, &mut recv_buf), Ok(body.len()));
2192
2193 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2194
2195 let resp = s.send_response(stream, true).unwrap();
2196
2197 let ev_headers = Event::Headers {
2198 list: resp,
2199 has_body: false,
2200 };
2201
2202 assert_eq!(s.poll_client(), Ok((stream, ev_headers)));
2203 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2204 }
2205
2206 #[test]
2207 /// Send a request with multiple DATA frames, get a response with no body.
request_many_chunks_response_no_body()2208 fn request_many_chunks_response_no_body() {
2209 let mut s = Session::default().unwrap();
2210 s.handshake().unwrap();
2211
2212 let (stream, req) = s.send_request(false).unwrap();
2213
2214 let total_data_frames = 4;
2215
2216 for _ in 0..total_data_frames - 1 {
2217 s.send_body_client(stream, false).unwrap();
2218 }
2219
2220 let body = s.send_body_client(stream, true).unwrap();
2221
2222 let mut recv_buf = vec![0; body.len()];
2223
2224 let ev_headers = Event::Headers {
2225 list: req,
2226 has_body: true,
2227 };
2228
2229 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2230
2231 for _ in 0..total_data_frames {
2232 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2233 assert_eq!(s.recv_body_server(stream, &mut recv_buf), Ok(body.len()));
2234 }
2235
2236 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2237
2238 let resp = s.send_response(stream, true).unwrap();
2239
2240 let ev_headers = Event::Headers {
2241 list: resp,
2242 has_body: false,
2243 };
2244
2245 assert_eq!(s.poll_client(), Ok((stream, ev_headers)));
2246 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2247 }
2248
2249 #[test]
2250 /// Send a request with multiple DATA frames, get a response with one DATA
2251 /// frame.
many_requests_many_chunks_response_one_chunk()2252 fn many_requests_many_chunks_response_one_chunk() {
2253 let mut s = Session::default().unwrap();
2254 s.handshake().unwrap();
2255
2256 let mut reqs = Vec::new();
2257
2258 let (stream1, req1) = s.send_request(false).unwrap();
2259 assert_eq!(stream1, 0);
2260 reqs.push(req1);
2261
2262 let (stream2, req2) = s.send_request(false).unwrap();
2263 assert_eq!(stream2, 4);
2264 reqs.push(req2);
2265
2266 let (stream3, req3) = s.send_request(false).unwrap();
2267 assert_eq!(stream3, 8);
2268 reqs.push(req3);
2269
2270 let body = s.send_body_client(stream1, false).unwrap();
2271 s.send_body_client(stream2, false).unwrap();
2272 s.send_body_client(stream3, false).unwrap();
2273
2274 let mut recv_buf = vec![0; body.len()];
2275
2276 // Reverse order of writes.
2277
2278 s.send_body_client(stream3, true).unwrap();
2279 s.send_body_client(stream2, true).unwrap();
2280 s.send_body_client(stream1, true).unwrap();
2281
2282 for _ in 0..reqs.len() {
2283 let (stream, ev) = s.poll_server().unwrap();
2284 let ev_headers = Event::Headers {
2285 list: reqs[(stream / 4) as usize].clone(),
2286 has_body: true,
2287 };
2288 assert_eq!(ev, ev_headers);
2289 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2290 assert_eq!(s.recv_body_server(stream, &mut recv_buf), Ok(body.len()));
2291 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2292 assert_eq!(s.recv_body_server(stream, &mut recv_buf), Ok(body.len()));
2293 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2294 }
2295
2296 assert_eq!(s.poll_server(), Err(Error::Done));
2297
2298 let mut resps = Vec::new();
2299
2300 let resp1 = s.send_response(stream1, true).unwrap();
2301 resps.push(resp1);
2302
2303 let resp2 = s.send_response(stream2, true).unwrap();
2304 resps.push(resp2);
2305
2306 let resp3 = s.send_response(stream3, true).unwrap();
2307 resps.push(resp3);
2308
2309 for _ in 0..resps.len() {
2310 let (stream, ev) = s.poll_client().unwrap();
2311 let ev_headers = Event::Headers {
2312 list: resps[(stream / 4) as usize].clone(),
2313 has_body: false,
2314 };
2315 assert_eq!(ev, ev_headers);
2316 assert_eq!(s.poll_client(), Ok((stream, Event::Finished)));
2317 }
2318
2319 assert_eq!(s.poll_client(), Err(Error::Done));
2320 }
2321
2322 #[test]
2323 /// Try to send DATA frames before HEADERS.
body_response_before_headers()2324 fn body_response_before_headers() {
2325 let mut s = Session::default().unwrap();
2326 s.handshake().unwrap();
2327
2328 let (stream, req) = s.send_request(true).unwrap();
2329 assert_eq!(stream, 0);
2330
2331 let ev_headers = Event::Headers {
2332 list: req,
2333 has_body: false,
2334 };
2335
2336 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2337
2338 assert_eq!(s.poll_server(), Ok((stream, Event::Finished)));
2339
2340 assert_eq!(
2341 s.send_body_server(stream, true),
2342 Err(Error::FrameUnexpected)
2343 );
2344
2345 assert_eq!(s.poll_client(), Err(Error::Done));
2346 }
2347
2348 #[test]
2349 /// Try to send DATA frames on wrong streams, ensure the API returns an
2350 /// error before anything hits the transport layer.
send_body_invalid_client_stream()2351 fn send_body_invalid_client_stream() {
2352 let mut s = Session::default().unwrap();
2353 s.handshake().unwrap();
2354
2355 assert_eq!(s.send_body_client(0, true), Err(Error::FrameUnexpected));
2356
2357 assert_eq!(
2358 s.send_body_client(s.client.control_stream_id.unwrap(), true),
2359 Err(Error::FrameUnexpected)
2360 );
2361
2362 assert_eq!(
2363 s.send_body_client(
2364 s.client.local_qpack_streams.encoder_stream_id.unwrap(),
2365 true
2366 ),
2367 Err(Error::FrameUnexpected)
2368 );
2369
2370 assert_eq!(
2371 s.send_body_client(
2372 s.client.local_qpack_streams.decoder_stream_id.unwrap(),
2373 true
2374 ),
2375 Err(Error::FrameUnexpected)
2376 );
2377
2378 assert_eq!(
2379 s.send_body_client(s.client.peer_control_stream_id.unwrap(), true),
2380 Err(Error::FrameUnexpected)
2381 );
2382
2383 assert_eq!(
2384 s.send_body_client(
2385 s.client.peer_qpack_streams.encoder_stream_id.unwrap(),
2386 true
2387 ),
2388 Err(Error::FrameUnexpected)
2389 );
2390
2391 assert_eq!(
2392 s.send_body_client(
2393 s.client.peer_qpack_streams.decoder_stream_id.unwrap(),
2394 true
2395 ),
2396 Err(Error::FrameUnexpected)
2397 );
2398 }
2399
2400 #[test]
2401 /// Try to send DATA frames on wrong streams, ensure the API returns an
2402 /// error before anything hits the transport layer.
send_body_invalid_server_stream()2403 fn send_body_invalid_server_stream() {
2404 let mut s = Session::default().unwrap();
2405 s.handshake().unwrap();
2406
2407 assert_eq!(s.send_body_server(0, true), Err(Error::FrameUnexpected));
2408
2409 assert_eq!(
2410 s.send_body_server(s.server.control_stream_id.unwrap(), true),
2411 Err(Error::FrameUnexpected)
2412 );
2413
2414 assert_eq!(
2415 s.send_body_server(
2416 s.server.local_qpack_streams.encoder_stream_id.unwrap(),
2417 true
2418 ),
2419 Err(Error::FrameUnexpected)
2420 );
2421
2422 assert_eq!(
2423 s.send_body_server(
2424 s.server.local_qpack_streams.decoder_stream_id.unwrap(),
2425 true
2426 ),
2427 Err(Error::FrameUnexpected)
2428 );
2429
2430 assert_eq!(
2431 s.send_body_server(s.server.peer_control_stream_id.unwrap(), true),
2432 Err(Error::FrameUnexpected)
2433 );
2434
2435 assert_eq!(
2436 s.send_body_server(
2437 s.server.peer_qpack_streams.encoder_stream_id.unwrap(),
2438 true
2439 ),
2440 Err(Error::FrameUnexpected)
2441 );
2442
2443 assert_eq!(
2444 s.send_body_server(
2445 s.server.peer_qpack_streams.decoder_stream_id.unwrap(),
2446 true
2447 ),
2448 Err(Error::FrameUnexpected)
2449 );
2450 }
2451
2452 #[test]
2453 /// Send a MAX_PUSH_ID frame from the client on a valid stream.
max_push_id_from_client_good()2454 fn max_push_id_from_client_good() {
2455 let mut s = Session::default().unwrap();
2456 s.handshake().unwrap();
2457
2458 s.send_frame_client(
2459 frame::Frame::MaxPushId { push_id: 1 },
2460 s.client.control_stream_id.unwrap(),
2461 false,
2462 )
2463 .unwrap();
2464
2465 assert_eq!(s.poll_server(), Err(Error::Done));
2466 }
2467
2468 #[test]
2469 /// Send a MAX_PUSH_ID frame from the client on an invalid stream.
max_push_id_from_client_bad_stream()2470 fn max_push_id_from_client_bad_stream() {
2471 let mut s = Session::default().unwrap();
2472 s.handshake().unwrap();
2473
2474 let (stream, req) = s.send_request(false).unwrap();
2475
2476 s.send_frame_client(
2477 frame::Frame::MaxPushId { push_id: 2 },
2478 stream,
2479 false,
2480 )
2481 .unwrap();
2482
2483 let ev_headers = Event::Headers {
2484 list: req,
2485 has_body: true,
2486 };
2487
2488 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2489 assert_eq!(s.poll_server(), Err(Error::FrameUnexpected));
2490 }
2491
2492 #[test]
2493 /// Send a sequence of MAX_PUSH_ID frames from the client that attempt to
2494 /// reduce the limit.
max_push_id_from_client_limit_reduction()2495 fn max_push_id_from_client_limit_reduction() {
2496 let mut s = Session::default().unwrap();
2497 s.handshake().unwrap();
2498
2499 s.send_frame_client(
2500 frame::Frame::MaxPushId { push_id: 2 },
2501 s.client.control_stream_id.unwrap(),
2502 false,
2503 )
2504 .unwrap();
2505
2506 s.send_frame_client(
2507 frame::Frame::MaxPushId { push_id: 1 },
2508 s.client.control_stream_id.unwrap(),
2509 false,
2510 )
2511 .unwrap();
2512
2513 assert_eq!(s.poll_server(), Err(Error::IdError));
2514 }
2515
2516 #[test]
2517 /// Send a MAX_PUSH_ID frame from the server, which is forbidden.
max_push_id_from_server()2518 fn max_push_id_from_server() {
2519 let mut s = Session::default().unwrap();
2520 s.handshake().unwrap();
2521
2522 s.send_frame_server(
2523 frame::Frame::MaxPushId { push_id: 1 },
2524 s.server.control_stream_id.unwrap(),
2525 false,
2526 )
2527 .unwrap();
2528
2529 assert_eq!(s.poll_client(), Err(Error::FrameUnexpected));
2530 }
2531
2532 #[test]
2533 /// Send a PUSH_PROMISE frame from the client, which is forbidden.
push_promise_from_client()2534 fn push_promise_from_client() {
2535 let mut s = Session::default().unwrap();
2536 s.handshake().unwrap();
2537
2538 let (stream, req) = s.send_request(false).unwrap();
2539
2540 let header_block = s.client.encode_header_block(&req).unwrap();
2541
2542 s.send_frame_client(
2543 frame::Frame::PushPromise {
2544 push_id: 1,
2545 header_block,
2546 },
2547 stream,
2548 false,
2549 )
2550 .unwrap();
2551
2552 let ev_headers = Event::Headers {
2553 list: req,
2554 has_body: true,
2555 };
2556
2557 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2558 assert_eq!(s.poll_server(), Err(Error::FrameUnexpected));
2559 }
2560
2561 #[test]
2562 /// Send a CANCEL_PUSH frame from the client.
cancel_push_from_client()2563 fn cancel_push_from_client() {
2564 let mut s = Session::default().unwrap();
2565 s.handshake().unwrap();
2566
2567 s.send_frame_client(
2568 frame::Frame::CancelPush { push_id: 1 },
2569 s.client.control_stream_id.unwrap(),
2570 false,
2571 )
2572 .unwrap();
2573
2574 assert_eq!(s.poll_server(), Err(Error::Done));
2575 }
2576
2577 #[test]
2578 /// Send a CANCEL_PUSH frame from the client on an invalid stream.
cancel_push_from_client_bad_stream()2579 fn cancel_push_from_client_bad_stream() {
2580 let mut s = Session::default().unwrap();
2581 s.handshake().unwrap();
2582
2583 let (stream, req) = s.send_request(false).unwrap();
2584
2585 s.send_frame_client(
2586 frame::Frame::CancelPush { push_id: 2 },
2587 stream,
2588 false,
2589 )
2590 .unwrap();
2591
2592 let ev_headers = Event::Headers {
2593 list: req,
2594 has_body: true,
2595 };
2596
2597 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2598 assert_eq!(s.poll_server(), Err(Error::FrameUnexpected));
2599 }
2600
2601 #[test]
2602 /// Send a CANCEL_PUSH frame from the client.
cancel_push_from_server()2603 fn cancel_push_from_server() {
2604 let mut s = Session::default().unwrap();
2605 s.handshake().unwrap();
2606
2607 s.send_frame_server(
2608 frame::Frame::CancelPush { push_id: 1 },
2609 s.server.control_stream_id.unwrap(),
2610 false,
2611 )
2612 .unwrap();
2613
2614 assert_eq!(s.poll_client(), Err(Error::Done));
2615 }
2616
2617 #[test]
2618 /// Send a GOAWAY frame from the client.
goaway_from_client_good()2619 fn goaway_from_client_good() {
2620 let mut s = Session::default().unwrap();
2621 s.handshake().unwrap();
2622
2623 s.client.send_goaway(&mut s.pipe.client, 1).unwrap();
2624
2625 s.advance().ok();
2626
2627 // TODO: server push
2628 assert_eq!(s.poll_server(), Err(Error::Done));
2629 }
2630
2631 #[test]
2632 /// Send a GOAWAY frame from the server.
goaway_from_server_good()2633 fn goaway_from_server_good() {
2634 let mut s = Session::default().unwrap();
2635 s.handshake().unwrap();
2636
2637 s.server.send_goaway(&mut s.pipe.server, 4000).unwrap();
2638
2639 s.advance().ok();
2640
2641 assert_eq!(s.poll_client(), Ok((4000, Event::GoAway)));
2642 }
2643
2644 #[test]
2645 /// A client MUST NOT send a request after it receives GOAWAY.
client_request_after_goaway()2646 fn client_request_after_goaway() {
2647 let mut s = Session::default().unwrap();
2648 s.handshake().unwrap();
2649
2650 s.server.send_goaway(&mut s.pipe.server, 4000).unwrap();
2651
2652 s.advance().ok();
2653
2654 assert_eq!(s.poll_client(), Ok((4000, Event::GoAway)));
2655
2656 assert_eq!(s.send_request(true), Err(Error::FrameUnexpected));
2657 }
2658
2659 #[test]
2660 /// Send a GOAWAY frame from the server, using an invalid goaway ID.
goaway_from_server_invalid_id()2661 fn goaway_from_server_invalid_id() {
2662 let mut s = Session::default().unwrap();
2663 s.handshake().unwrap();
2664
2665 s.send_frame_server(
2666 frame::Frame::GoAway { id: 1 },
2667 s.server.control_stream_id.unwrap(),
2668 false,
2669 )
2670 .unwrap();
2671
2672 assert_eq!(s.poll_client(), Err(Error::IdError));
2673 }
2674
2675 #[test]
2676 /// Send multiple GOAWAY frames from the server, that increase the goaway
2677 /// ID.
goaway_from_server_increase_id()2678 fn goaway_from_server_increase_id() {
2679 let mut s = Session::default().unwrap();
2680 s.handshake().unwrap();
2681
2682 s.send_frame_server(
2683 frame::Frame::GoAway { id: 0 },
2684 s.server.control_stream_id.unwrap(),
2685 false,
2686 )
2687 .unwrap();
2688
2689 s.send_frame_server(
2690 frame::Frame::GoAway { id: 4 },
2691 s.server.control_stream_id.unwrap(),
2692 false,
2693 )
2694 .unwrap();
2695
2696 assert_eq!(s.poll_client(), Ok((0, Event::GoAway)));
2697
2698 assert_eq!(s.poll_client(), Err(Error::IdError));
2699 }
2700
2701 #[test]
2702 /// Ensure quiche allocates streams for client and server roles as expected.
uni_stream_local_counting()2703 fn uni_stream_local_counting() {
2704 let config = Config::new().unwrap();
2705
2706 let h3_cln = Connection::new(&config, false).unwrap();
2707 assert_eq!(h3_cln.next_uni_stream_id, 2);
2708
2709 let h3_srv = Connection::new(&config, true).unwrap();
2710 assert_eq!(h3_srv.next_uni_stream_id, 3);
2711 }
2712
2713 #[test]
2714 /// Client opens multiple control streams, which is forbidden.
open_multiple_control_streams()2715 fn open_multiple_control_streams() {
2716 let mut s = Session::default().unwrap();
2717 s.handshake().unwrap();
2718
2719 let stream_id = s.client.next_uni_stream_id;
2720
2721 let mut d = [42; 8];
2722 let mut b = octets::OctetsMut::with_slice(&mut d);
2723
2724 s.pipe
2725 .client
2726 .stream_send(
2727 stream_id,
2728 b.put_varint(stream::HTTP3_CONTROL_STREAM_TYPE_ID).unwrap(),
2729 false,
2730 )
2731 .unwrap();
2732
2733 s.advance().ok();
2734
2735 assert_eq!(s.poll_server(), Err(Error::StreamCreationError));
2736 }
2737
2738 #[test]
2739 /// Client closes the control stream, which is forbidden.
close_control_stream()2740 fn close_control_stream() {
2741 let mut s = Session::default().unwrap();
2742 s.handshake().unwrap();
2743
2744 let mut control_stream_closed = false;
2745
2746 s.send_frame_client(
2747 frame::Frame::MaxPushId { push_id: 1 },
2748 s.client.control_stream_id.unwrap(),
2749 true,
2750 )
2751 .unwrap();
2752
2753 loop {
2754 match s.server.poll(&mut s.pipe.server) {
2755 Ok(_) => (),
2756
2757 Err(Error::Done) => {
2758 break;
2759 },
2760
2761 Err(Error::ClosedCriticalStream) => {
2762 control_stream_closed = true;
2763 break;
2764 },
2765
2766 Err(_) => (),
2767 }
2768 }
2769
2770 assert!(control_stream_closed);
2771 }
2772
2773 #[test]
2774 /// Client closes QPACK stream, which is forbidden.
close_qpack_stream()2775 fn close_qpack_stream() {
2776 let mut s = Session::default().unwrap();
2777 s.handshake().unwrap();
2778
2779 let mut qpack_stream_closed = false;
2780
2781 let stream_id = s.client.local_qpack_streams.encoder_stream_id.unwrap();
2782 let d = [0; 1];
2783
2784 s.pipe.client.stream_send(stream_id, &d, false).unwrap();
2785 s.pipe.client.stream_send(stream_id, &d, true).unwrap();
2786
2787 s.advance().ok();
2788
2789 loop {
2790 match s.server.poll(&mut s.pipe.server) {
2791 Ok(_) => (),
2792
2793 Err(Error::Done) => {
2794 break;
2795 },
2796
2797 Err(Error::ClosedCriticalStream) => {
2798 qpack_stream_closed = true;
2799 break;
2800 },
2801
2802 Err(_) => (),
2803 }
2804 }
2805
2806 assert!(qpack_stream_closed);
2807 }
2808
2809 #[test]
2810 /// Client sends QPACK data.
qpack_data()2811 fn qpack_data() {
2812 // TODO: QPACK instructions are ignored until dynamic table support is
2813 // added so we just test that the data is safely ignored.
2814 let mut s = Session::default().unwrap();
2815 s.handshake().unwrap();
2816
2817 let e_stream_id = s.client.local_qpack_streams.encoder_stream_id.unwrap();
2818 let d_stream_id = s.client.local_qpack_streams.decoder_stream_id.unwrap();
2819 let d = [0; 20];
2820
2821 s.pipe.client.stream_send(e_stream_id, &d, false).unwrap();
2822 s.advance().ok();
2823
2824 s.pipe.client.stream_send(d_stream_id, &d, false).unwrap();
2825 s.advance().ok();
2826
2827 loop {
2828 match s.server.poll(&mut s.pipe.server) {
2829 Ok(_) => (),
2830
2831 Err(Error::Done) => {
2832 break;
2833 },
2834
2835 Err(_) => {
2836 panic!();
2837 },
2838 }
2839 }
2840 }
2841
2842 #[test]
2843 /// Tests limits for the stream state buffer maximum size.
max_state_buf_size()2844 fn max_state_buf_size() {
2845 // DATA frames don't consume the state buffer, so can be of any size.
2846 let mut s = Session::default().unwrap();
2847 s.handshake().unwrap();
2848
2849 let mut d = [42; 128];
2850 let mut b = octets::OctetsMut::with_slice(&mut d);
2851
2852 let frame_type = b.put_varint(frame::DATA_FRAME_TYPE_ID).unwrap();
2853 s.pipe.client.stream_send(0, frame_type, false).unwrap();
2854
2855 let frame_len = b.put_varint(1 << 24).unwrap();
2856 s.pipe.client.stream_send(0, frame_len, false).unwrap();
2857
2858 s.pipe.client.stream_send(0, &d, false).unwrap();
2859
2860 s.advance().ok();
2861
2862 assert_eq!(s.server.poll(&mut s.pipe.server), Ok((0, Event::Data)));
2863
2864 // GREASE frames consume the state buffer, so need to be limited.
2865 let mut s = Session::default().unwrap();
2866 s.handshake().unwrap();
2867
2868 let mut d = [42; 128];
2869 let mut b = octets::OctetsMut::with_slice(&mut d);
2870
2871 let frame_type = b.put_varint(148_764_065_110_560_899).unwrap();
2872 s.pipe.client.stream_send(0, frame_type, false).unwrap();
2873
2874 let frame_len = b.put_varint(1 << 24).unwrap();
2875 s.pipe.client.stream_send(0, frame_len, false).unwrap();
2876
2877 s.pipe.client.stream_send(0, &d, false).unwrap();
2878
2879 s.advance().ok();
2880
2881 assert_eq!(s.server.poll(&mut s.pipe.server), Err(Error::InternalError));
2882 }
2883
2884 #[test]
2885 /// Tests that DATA frames are properly truncated depending on the request
2886 /// stream's outgoing flow control capacity.
stream_backpressure()2887 fn stream_backpressure() {
2888 let bytes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2889
2890 let mut s = Session::default().unwrap();
2891 s.handshake().unwrap();
2892
2893 let (stream, req) = s.send_request(false).unwrap();
2894
2895 let total_data_frames = 6;
2896
2897 for _ in 0..total_data_frames {
2898 assert_eq!(
2899 s.client
2900 .send_body(&mut s.pipe.client, stream, &bytes, false),
2901 Ok(bytes.len())
2902 );
2903
2904 s.advance().ok();
2905 }
2906
2907 assert_eq!(
2908 s.client.send_body(&mut s.pipe.client, stream, &bytes, true),
2909 Ok(bytes.len() - 2)
2910 );
2911
2912 s.advance().ok();
2913
2914 let mut recv_buf = vec![0; bytes.len()];
2915
2916 let ev_headers = Event::Headers {
2917 list: req,
2918 has_body: true,
2919 };
2920
2921 assert_eq!(s.poll_server(), Ok((stream, ev_headers)));
2922
2923 for _ in 0..total_data_frames {
2924 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2925 assert_eq!(
2926 s.recv_body_server(stream, &mut recv_buf),
2927 Ok(bytes.len())
2928 );
2929 }
2930
2931 assert_eq!(s.poll_server(), Ok((stream, Event::Data)));
2932 assert_eq!(
2933 s.recv_body_server(stream, &mut recv_buf),
2934 Ok(bytes.len() - 2)
2935 );
2936
2937 // Fin flag from last send_body() call was not sent as the buffer was
2938 // only partially written.
2939 assert_eq!(s.poll_server(), Err(Error::Done));
2940 }
2941
2942 #[test]
2943 /// Tests that the max header list size setting is enforced.
request_max_header_size_limit()2944 fn request_max_header_size_limit() {
2945 let mut config = crate::Config::new(crate::PROTOCOL_VERSION).unwrap();
2946 config
2947 .load_cert_chain_from_pem_file("examples/cert.crt")
2948 .unwrap();
2949 config
2950 .load_priv_key_from_pem_file("examples/cert.key")
2951 .unwrap();
2952 config.set_application_protos(b"\x02h3").unwrap();
2953 config.set_initial_max_data(1500);
2954 config.set_initial_max_stream_data_bidi_local(150);
2955 config.set_initial_max_stream_data_bidi_remote(150);
2956 config.set_initial_max_stream_data_uni(150);
2957 config.set_initial_max_streams_bidi(5);
2958 config.set_initial_max_streams_uni(5);
2959 config.verify_peer(false);
2960
2961 let mut h3_config = Config::new().unwrap();
2962 h3_config.set_max_header_list_size(65);
2963
2964 let mut s = Session::with_configs(&mut config, &mut h3_config).unwrap();
2965
2966 s.handshake().unwrap();
2967
2968 let req = vec![
2969 Header::new(":method", "GET"),
2970 Header::new(":scheme", "https"),
2971 Header::new(":authority", "quic.tech"),
2972 Header::new(":path", "/test"),
2973 Header::new("aaaaaaa", "aaaaaaaa"),
2974 ];
2975
2976 let stream = s
2977 .client
2978 .send_request(&mut s.pipe.client, &req, true)
2979 .unwrap();
2980
2981 s.advance().ok();
2982
2983 assert_eq!(stream, 0);
2984
2985 assert_eq!(s.poll_server(), Err(Error::ExcessiveLoad));
2986 }
2987
2988 #[test]
2989 /// Tests that Error::TransportError contains a transport error.
transport_error()2990 fn transport_error() {
2991 let mut s = Session::default().unwrap();
2992 s.handshake().unwrap();
2993
2994 let req = vec![
2995 Header::new(":method", "GET"),
2996 Header::new(":scheme", "https"),
2997 Header::new(":authority", "quic.tech"),
2998 Header::new(":path", "/test"),
2999 Header::new("user-agent", "quiche-test"),
3000 ];
3001
3002 // We need to open all streams in the same flight, so we can't use the
3003 // Session::send_request() method because it also calls advance(),
3004 // otherwise the server would send a MAX_STREAMS frame and the client
3005 // wouldn't hit the streams limit.
3006 assert_eq!(s.client.send_request(&mut s.pipe.client, &req, true), Ok(0));
3007 assert_eq!(s.client.send_request(&mut s.pipe.client, &req, true), Ok(4));
3008 assert_eq!(s.client.send_request(&mut s.pipe.client, &req, true), Ok(8));
3009 assert_eq!(
3010 s.client.send_request(&mut s.pipe.client, &req, true),
3011 Ok(12)
3012 );
3013 assert_eq!(
3014 s.client.send_request(&mut s.pipe.client, &req, true),
3015 Ok(16)
3016 );
3017
3018 assert_eq!(
3019 s.client.send_request(&mut s.pipe.client, &req, true),
3020 Err(Error::TransportError(crate::Error::StreamLimit))
3021 );
3022 }
3023
3024 #[test]
3025 /// Tests that calling poll() after an error occured does nothing.
poll_after_error()3026 fn poll_after_error() {
3027 // DATA frames don't consume the state buffer, so can be of any size.
3028 let mut s = Session::default().unwrap();
3029 s.handshake().unwrap();
3030
3031 let mut d = [42; 128];
3032 let mut b = octets::OctetsMut::with_slice(&mut d);
3033
3034 let frame_type = b.put_varint(frame::DATA_FRAME_TYPE_ID).unwrap();
3035 s.pipe.client.stream_send(0, frame_type, false).unwrap();
3036
3037 let frame_len = b.put_varint(1 << 24).unwrap();
3038 s.pipe.client.stream_send(0, frame_len, false).unwrap();
3039
3040 s.pipe.client.stream_send(0, &d, false).unwrap();
3041
3042 s.advance().ok();
3043
3044 assert_eq!(s.server.poll(&mut s.pipe.server), Ok((0, Event::Data)));
3045
3046 // GREASE frames consume the state buffer, so need to be limited.
3047 let mut s = Session::default().unwrap();
3048 s.handshake().unwrap();
3049
3050 let mut d = [42; 128];
3051 let mut b = octets::OctetsMut::with_slice(&mut d);
3052
3053 let frame_type = b.put_varint(148_764_065_110_560_899).unwrap();
3054 s.pipe.client.stream_send(0, frame_type, false).unwrap();
3055
3056 let frame_len = b.put_varint(1 << 24).unwrap();
3057 s.pipe.client.stream_send(0, frame_len, false).unwrap();
3058
3059 s.pipe.client.stream_send(0, &d, false).unwrap();
3060
3061 s.advance().ok();
3062
3063 assert_eq!(s.server.poll(&mut s.pipe.server), Err(Error::InternalError));
3064
3065 // Try to call poll() again after an error occurred.
3066 assert_eq!(s.server.poll(&mut s.pipe.server), Err(Error::Done));
3067 }
3068
3069 #[test]
3070 /// Tests that we limit sending HEADERS based on the stream capacity.
headers_blocked()3071 fn headers_blocked() {
3072 let mut config = crate::Config::new(crate::PROTOCOL_VERSION).unwrap();
3073 config
3074 .load_cert_chain_from_pem_file("examples/cert.crt")
3075 .unwrap();
3076 config
3077 .load_priv_key_from_pem_file("examples/cert.key")
3078 .unwrap();
3079 config.set_application_protos(b"\x02h3").unwrap();
3080 config.set_initial_max_data(70);
3081 config.set_initial_max_stream_data_bidi_local(150);
3082 config.set_initial_max_stream_data_bidi_remote(150);
3083 config.set_initial_max_stream_data_uni(150);
3084 config.set_initial_max_streams_bidi(100);
3085 config.set_initial_max_streams_uni(5);
3086 config.verify_peer(false);
3087
3088 let mut h3_config = Config::new().unwrap();
3089
3090 let mut s = Session::with_configs(&mut config, &mut h3_config).unwrap();
3091
3092 s.handshake().unwrap();
3093
3094 let req = vec![
3095 Header::new(":method", "GET"),
3096 Header::new(":scheme", "https"),
3097 Header::new(":authority", "quic.tech"),
3098 Header::new(":path", "/test"),
3099 ];
3100
3101 assert_eq!(s.client.send_request(&mut s.pipe.client, &req, true), Ok(0));
3102
3103 assert_eq!(
3104 s.client.send_request(&mut s.pipe.client, &req, true),
3105 Err(Error::StreamBlocked)
3106 );
3107
3108 s.advance().ok();
3109
3110 // Once the server gives flow control credits back, we can send the
3111 // request.
3112 assert_eq!(s.client.send_request(&mut s.pipe.client, &req, true), Ok(4));
3113 }
3114
3115 #[test]
3116 /// Tests that blocked 0-length DATA writes are reported correctly.
zero_length_data_blocked()3117 fn zero_length_data_blocked() {
3118 let mut config = crate::Config::new(crate::PROTOCOL_VERSION).unwrap();
3119 config
3120 .load_cert_chain_from_pem_file("examples/cert.crt")
3121 .unwrap();
3122 config
3123 .load_priv_key_from_pem_file("examples/cert.key")
3124 .unwrap();
3125 config.set_application_protos(b"\x02h3").unwrap();
3126 config.set_initial_max_data(70);
3127 config.set_initial_max_stream_data_bidi_local(150);
3128 config.set_initial_max_stream_data_bidi_remote(150);
3129 config.set_initial_max_stream_data_uni(150);
3130 config.set_initial_max_streams_bidi(100);
3131 config.set_initial_max_streams_uni(5);
3132 config.verify_peer(false);
3133
3134 let mut h3_config = Config::new().unwrap();
3135
3136 let mut s = Session::with_configs(&mut config, &mut h3_config).unwrap();
3137
3138 s.handshake().unwrap();
3139
3140 let req = vec![
3141 Header::new(":method", "GET"),
3142 Header::new(":scheme", "https"),
3143 Header::new(":authority", "quic.tech"),
3144 Header::new(":path", "/test"),
3145 ];
3146
3147 assert_eq!(
3148 s.client.send_request(&mut s.pipe.client, &req, false),
3149 Ok(0)
3150 );
3151
3152 assert_eq!(
3153 s.client.send_body(&mut s.pipe.client, 0, b"", true),
3154 Err(Error::Done)
3155 );
3156
3157 s.advance().ok();
3158
3159 // Once the server gives flow control credits back, we can send the body.
3160 assert_eq!(s.client.send_body(&mut s.pipe.client, 0, b"", true), Ok(0));
3161 }
3162 }
3163
3164 mod ffi;
3165 mod frame;
3166 #[doc(hidden)]
3167 pub mod qpack;
3168 mod stream;
3169