1#![forbid(unsafe_code)]
12
13mod frame;
14mod validate;
15
16pub use frame::Settings;
17pub use simoom_qpack::Field;
18pub use validate::{pseudo, validate_request, validate_response, validate_trailers, Validated};
19
20use simoom_qpack::{Decoded, Decoder, Encoder};
21use simoom_quic::coding::{put_varint, varint_len, Reader};
22use simoom_quic::stream::{is_bidi, is_server_initiated, IdMap};
23use simoom_quic::{Connection, Event, StreamError};
24use std::collections::VecDeque;
25use std::time::Instant;
26
27const SMALL_FRAME: usize = 16 * 1024;
30
31fn mark_blocked(conn: &mut Connection, stream: u64) {
35 if conn.stream_writable(stream) == Some(0) {
36 let r = conn.stream_send(stream, &[0], false);
37 debug_assert!(!matches!(r, Ok(n) if n > 0), "a stream with no room accepted data");
38 }
39}
40
41pub mod code {
43 pub const NO_ERROR: u64 = 0x100;
44 pub const GENERAL_PROTOCOL_ERROR: u64 = 0x101;
45 pub const INTERNAL_ERROR: u64 = 0x102;
46 pub const STREAM_CREATION_ERROR: u64 = 0x103;
47 pub const CLOSED_CRITICAL_STREAM: u64 = 0x104;
48 pub const FRAME_UNEXPECTED: u64 = 0x105;
49 pub const FRAME_ERROR: u64 = 0x106;
50 pub const EXCESSIVE_LOAD: u64 = 0x107;
51 pub const ID_ERROR: u64 = 0x108;
52 pub const SETTINGS_ERROR: u64 = 0x109;
53 pub const MISSING_SETTINGS: u64 = 0x10a;
54 pub const REQUEST_REJECTED: u64 = 0x10b;
55 pub const REQUEST_CANCELLED: u64 = 0x10c;
56 pub const REQUEST_INCOMPLETE: u64 = 0x10d;
57 pub const MESSAGE_ERROR: u64 = 0x10e;
58 pub const CONNECT_ERROR: u64 = 0x10f;
59 pub const VERSION_FALLBACK: u64 = 0x110;
60}
61
62#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub struct H3Error {
65 pub code: u64,
66 pub reason: &'static str,
67}
68
69impl H3Error {
70 pub const fn new(code: u64, reason: &'static str) -> Self {
71 H3Error { code, reason }
72 }
73}
74
75impl std::fmt::Display for H3Error {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "HTTP/3 error 0x{:x}: {}", self.code, self.reason)
78 }
79}
80
81impl std::error::Error for H3Error {}
82
83#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub enum SendError {
86 UnknownStream,
88 InvalidState,
90 HeadersTooLarge,
92 GoingAway,
94 Stream(StreamError),
95}
96
97impl From<StreamError> for SendError {
98 fn from(e: StreamError) -> Self {
99 SendError::Stream(e)
100 }
101}
102
103#[derive(Clone, Debug)]
104pub struct Config {
105 pub max_field_section_size: u64,
107 pub qpack_max_table_capacity: u64,
109 pub qpack_blocked_streams: u64,
111 pub qpack_encoder_capacity: u64,
113 pub body_buffer: usize,
115 pub enable_connect_protocol: bool,
118}
119
120impl Default for Config {
121 fn default() -> Self {
122 Config {
123 max_field_section_size: 16 << 10,
124 qpack_max_table_capacity: 4096,
125 qpack_blocked_streams: 16,
126 qpack_encoder_capacity: 0,
127 body_buffer: 64 << 10,
128 enable_connect_protocol: false,
129 }
130 }
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
134pub enum H3Event {
135 Headers { stream: u64, fields: Vec<Field> },
137 Data { stream: u64 },
139 Trailers { stream: u64, fields: Vec<Field> },
140 Finished { stream: u64 },
142 Reset { stream: u64, code: u64 },
144 Writable { stream: u64 },
146 GoAway { id: u64 },
148 Error(H3Error),
150}
151
152#[derive(Clone, Copy, PartialEq, Eq, Debug)]
153enum UniKind {
154 Unknown,
155 Control,
156 Encoder,
157 Decoder,
158}
159
160struct UniIn {
161 kind: UniKind,
162 buf: Vec<u8>,
163}
164
165#[derive(Default)]
166struct Req {
167 inbuf: Vec<u8>,
168 body: VecDeque<u8>,
169 data_left: u64,
171 skip_left: u64,
172 headers_done: bool,
173 trailers_done: bool,
174 blocked: bool,
176 fin_seen: bool,
177 finished: bool,
178 content_length: Option<u64>,
179 body_len: u64,
180 data_event: bool,
181 out: Vec<u8>,
183 headers_sent: bool,
184 finish_after_out: bool,
185 send_done: bool,
186 want_writable: bool,
187}
188
189pub struct Http3 {
190 is_server: bool,
191 cfg: Config,
192 encoder: Encoder,
193 decoder: Decoder,
194 control_out: Option<u64>,
195 encoder_out: Option<u64>,
196 decoder_out: Option<u64>,
197 pending_uni: VecDeque<(u64, Vec<u8>)>,
198 uni: IdMap<UniIn>,
199 have: [bool; 3],
200 peer_settings: Option<Settings>,
201 reqs: IdMap<Req>,
202 events: VecDeque<H3Event>,
203 pending_fields: VecDeque<(u64, Option<Vec<Field>>)>,
204 goaway_sent: Option<u64>,
205 goaway_recv: Option<u64>,
206 max_request: Option<u64>,
207 failed: bool,
208 scratch: Vec<u8>,
209}
210
211impl Http3 {
212 pub fn new(is_server: bool, cfg: Config) -> Self {
213 let encoder = if cfg.qpack_encoder_capacity > 0 {
214 Encoder::with_dynamic_table(cfg.qpack_encoder_capacity)
215 } else {
216 Encoder::new()
217 };
218 let decoder = Decoder::new(cfg.qpack_max_table_capacity, cfg.qpack_blocked_streams, cfg.max_field_section_size);
219 Http3 {
220 is_server,
221 encoder,
222 decoder,
223 control_out: None,
224 encoder_out: None,
225 decoder_out: None,
226 pending_uni: VecDeque::new(),
227 uni: IdMap::default(),
228 have: [false; 3],
229 peer_settings: None,
230 reqs: IdMap::default(),
231 events: VecDeque::new(),
232 pending_fields: VecDeque::new(),
233 goaway_sent: None,
234 goaway_recv: None,
235 max_request: None,
236 failed: false,
237 scratch: vec![0; 16 << 10],
238 cfg,
239 }
240 }
241
242 pub fn poll_event(&mut self) -> Option<H3Event> {
243 self.events.pop_front()
244 }
245
246 pub fn peer_connect_protocol(&self) -> Option<bool> {
249 self.peer_settings.as_ref().map(|s| s.enable_connect_protocol == Some(1))
250 }
251
252 pub fn peer_settings(&self) -> Option<&Settings> {
254 self.peer_settings.as_ref()
255 }
256
257 pub fn active_streams(&self) -> usize {
259 self.reqs.len()
260 }
261
262 pub fn open(&mut self, conn: &mut Connection) {
265 if self.control_out.is_some() {
266 return;
267 }
268 let mut b = Vec::with_capacity(32);
269 put_varint(&mut b, 0x00);
270 Settings {
271 max_field_section_size: Some(self.cfg.max_field_section_size),
272 qpack_max_table_capacity: Some(self.cfg.qpack_max_table_capacity),
273 qpack_blocked_streams: Some(self.cfg.qpack_blocked_streams),
274 enable_connect_protocol: (self.is_server && self.cfg.enable_connect_protocol).then_some(1),
275 }
276 .encode(&mut b);
277 self.control_out = self.open_uni(conn, b);
278 self.encoder_out = self.open_uni(conn, vec![0x02]);
279 self.decoder_out = self.open_uni(conn, vec![0x03]);
280 }
281
282 fn open_uni(&mut self, conn: &mut Connection, prefix: Vec<u8>) -> Option<u64> {
283 let id = conn.open_uni().ok()?;
284 self.pending_uni.push_back((id, prefix));
285 self.flush_uni(conn);
286 Some(id)
287 }
288
289 fn flush_uni(&mut self, conn: &mut Connection) {
290 for e in self.pending_uni.iter_mut() {
291 if let Ok(k) = conn.stream_send(e.0, &e.1, false) {
292 e.1.drain(..k);
293 }
294 }
295 self.pending_uni.retain(|e| !e.1.is_empty());
296 }
297
298 fn send_uni(&mut self, conn: &mut Connection, id: Option<u64>, data: &[u8]) {
299 let Some(id) = id else { return };
300 if data.is_empty() {
301 return;
302 }
303 if let Some(e) = self.pending_uni.iter_mut().find(|e| e.0 == id) {
304 e.1.extend_from_slice(data);
305 return;
306 }
307 self.pending_uni.push_back((id, data.to_vec()));
308 self.flush_uni(conn);
309 }
310
311 fn flush_qpack(&mut self, conn: &mut Connection) {
313 let mut b = Vec::new();
314 self.decoder.take_decoder_stream(&mut b);
315 let d = self.decoder_out;
316 self.send_uni(conn, d, &b);
317 b.clear();
318 self.encoder.take_encoder_stream(&mut b);
319 let e = self.encoder_out;
320 self.send_uni(conn, e, &b);
321 }
322
323 fn fail(&mut self, now: Instant, conn: &mut Connection, e: H3Error) {
324 if self.failed {
325 return;
326 }
327 self.failed = true;
328 conn.close(now, e.code, e.reason.as_bytes());
329 self.events.push_back(H3Event::Error(e));
330 }
331
332 fn reject(&mut self, conn: &mut Connection, id: u64, code: u64) {
334 self.reset_stream(conn, id, code);
335 self.events.push_back(H3Event::Reset { stream: id, code });
336 }
337
338 pub fn handle(&mut self, now: Instant, conn: &mut Connection, ev: &Event) {
340 if self.failed {
341 return;
342 }
343 let r = match *ev {
344 Event::Connected => {
345 self.open(conn);
346 Ok(())
347 }
348 Event::StreamOpened(id) => self.on_opened(conn, id),
349 Event::StreamReadable(id) => self.on_readable(conn, id),
350 Event::StreamWritable(id) => {
351 self.on_writable(conn, id);
352 Ok(())
353 }
354 Event::StreamReset { id, code } => self.on_reset(conn, id, code),
355 Event::StreamStopped { id, code } => self.on_stopped(id, code),
356 Event::Closed(_) | Event::StreamsAvailable(_) | Event::PathMigrated(_) => Ok(()),
357 };
358 let r = r.and_then(|_| self.resume_unblocked(conn));
359 if let Err(e) = r {
360 self.fail(now, conn, e);
361 return;
362 }
363 self.flush_qpack(conn);
364 }
365
366 fn is_local_critical(&self, id: u64) -> bool {
367 Some(id) == self.control_out || Some(id) == self.encoder_out || Some(id) == self.decoder_out
368 }
369
370 fn on_stopped(&mut self, id: u64, code_: u64) -> Result<(), H3Error> {
371 if self.is_local_critical(id) {
372 return Err(H3Error::new(code::CLOSED_CRITICAL_STREAM, "critical stream stopped"));
373 }
374 if let Some(r) = self.reqs.get_mut(&id) {
375 r.send_done = true;
376 r.out.clear();
377 self.events.push_back(H3Event::Reset { stream: id, code: code_ });
378 self.maybe_drop(id);
379 }
380 Ok(())
381 }
382
383 fn on_opened(&mut self, conn: &mut Connection, id: u64) -> Result<(), H3Error> {
384 if is_bidi(id) {
385 if !self.is_server || is_server_initiated(id) {
386 return Err(H3Error::new(code::STREAM_CREATION_ERROR, "unexpected bidirectional stream"));
387 }
388 if self.goaway_sent.is_some_and(|g| id >= g) {
389 let _ = conn.stream_stop(id, code::REQUEST_REJECTED);
390 let _ = conn.stream_reset(id, code::REQUEST_REJECTED);
391 return Ok(());
392 }
393 self.max_request = Some(self.max_request.map_or(id, |m| m.max(id)));
394 self.reqs.insert(id, Req::default());
395 } else {
396 self.uni.insert(id, UniIn { kind: UniKind::Unknown, buf: Vec::new() });
397 }
398 Ok(())
399 }
400
401 fn on_reset(&mut self, conn: &mut Connection, id: u64, code_: u64) -> Result<(), H3Error> {
402 if let Some(u) = self.uni.get(&id) {
403 if u.kind != UniKind::Unknown {
404 return Err(H3Error::new(code::CLOSED_CRITICAL_STREAM, "critical stream reset"));
405 }
406 self.uni.remove(&id);
407 return Ok(());
408 }
409 if let Some(r) = self.reqs.remove(&id) {
410 if !r.headers_done || r.blocked {
411 self.decoder.cancel_stream(id);
412 }
413 self.events.push_back(H3Event::Reset { stream: id, code: code_ });
414 if !r.send_done {
416 let _ = conn.stream_reset(id, code::REQUEST_CANCELLED);
417 }
418 }
419 Ok(())
420 }
421
422 fn on_writable(&mut self, conn: &mut Connection, id: u64) {
423 if self.pending_uni.iter().any(|e| e.0 == id) {
424 self.flush_uni(conn);
425 return;
426 }
427 let Some(r) = self.reqs.get_mut(&id) else { return };
428 if !r.out.is_empty() {
429 if let Ok(k) = conn.stream_send(id, &r.out, false) {
430 r.out.drain(..k);
431 }
432 if r.out.is_empty() && r.finish_after_out {
433 let _ = conn.stream_finish(id);
434 r.send_done = true;
435 }
436 }
437 if r.out.is_empty() && r.want_writable && !r.send_done {
438 r.want_writable = false;
439 self.events.push_back(H3Event::Writable { stream: id });
440 }
441 self.maybe_drop(id);
442 }
443
444 fn on_readable(&mut self, conn: &mut Connection, id: u64) -> Result<(), H3Error> {
445 if self.uni.contains_key(&id) {
446 return self.read_uni(conn, id);
447 }
448 if self.reqs.contains_key(&id) {
449 return self.pump(conn, id);
450 }
451 let mut b = std::mem::take(&mut self.scratch);
453 while let Ok((n, fin)) = conn.stream_recv(id, &mut b) {
454 if n == 0 || fin {
455 break;
456 }
457 }
458 self.scratch = b;
459 Ok(())
460 }
461
462 fn read_uni(&mut self, conn: &mut Connection, id: u64) -> Result<(), H3Error> {
465 let mut b = std::mem::take(&mut self.scratch);
466 let res = self.read_uni_inner(conn, id, &mut b);
467 self.scratch = b;
468 res
469 }
470
471 fn read_uni_inner(&mut self, conn: &mut Connection, id: u64, b: &mut [u8]) -> Result<(), H3Error> {
472 loop {
473 let (n, fin) = match conn.stream_recv(id, b) {
474 Ok(x) => x,
475 Err(_) => return Ok(()),
476 };
477 let Some(u) = self.uni.get_mut(&id) else { return Ok(()) };
478 if u.kind == UniKind::Unknown {
479 u.buf.extend_from_slice(&b[..n]);
480 let Some((ty, len)) = Reader::new(&u.buf).varint_with_len() else {
481 if fin {
482 self.uni.remove(&id);
483 return Ok(());
484 }
485 if n == 0 {
486 return Ok(());
487 }
488 continue;
489 };
490 let kind = match ty {
491 0x00 => UniKind::Control,
492 0x02 => UniKind::Encoder,
493 0x03 => UniKind::Decoder,
494 0x01 => {
495 return Err(if self.is_server {
496 H3Error::new(code::STREAM_CREATION_ERROR, "push stream from a client")
497 } else {
498 H3Error::new(code::ID_ERROR, "push stream without MAX_PUSH_ID")
499 })
500 }
501 _ => {
502 let _ = conn.stream_stop(id, code::STREAM_CREATION_ERROR);
504 self.uni.remove(&id);
505 return Ok(());
506 }
507 };
508 let slot = kind as usize - 1;
509 if self.have[slot] {
510 return Err(H3Error::new(code::STREAM_CREATION_ERROR, "duplicate critical stream"));
511 }
512 self.have[slot] = true;
513 let u = self.uni.get_mut(&id).unwrap();
514 u.kind = kind;
515 let pending = u.buf.split_off(len);
516 u.buf.clear();
517 self.uni_data(id, kind, &pending)?;
518 } else if n > 0 {
519 let kind = u.kind;
520 self.uni_data(id, kind, &b[..n])?;
521 }
522 if fin {
523 return Err(H3Error::new(code::CLOSED_CRITICAL_STREAM, "critical stream closed"));
524 }
525 if n == 0 {
526 return Ok(());
527 }
528 }
529 }
530
531 fn uni_data(&mut self, id: u64, kind: UniKind, data: &[u8]) -> Result<(), H3Error> {
532 match kind {
533 UniKind::Encoder => {
534 let unblocked = self
535 .decoder
536 .on_encoder_stream(data)
537 .map_err(|e| H3Error::new(e.code(), "QPACK encoder stream error"))?;
538 for (sid, res) in unblocked {
539 if let Some(r) = self.reqs.get_mut(&sid) {
540 r.blocked = false;
541 }
542 match res {
543 Ok(f) => self.pending_fields.push_back((sid, Some(f))),
544 Err(simoom_qpack::Error::FieldSectionTooLarge) => self.pending_fields.push_back((sid, None)),
545 Err(e) => return Err(H3Error::new(e.code(), "QPACK decompression failed")),
546 }
547 }
548 Ok(())
549 }
550 UniKind::Decoder => self
551 .encoder
552 .on_decoder_stream(data)
553 .map_err(|e| H3Error::new(e.code(), "QPACK decoder stream error")),
554 UniKind::Control => {
555 let u = self.uni.get_mut(&id).unwrap();
556 u.buf.extend_from_slice(data);
557 let buf = std::mem::take(&mut u.buf);
558 let used = self.control_frames(&buf)?;
559 let u = self.uni.get_mut(&id).unwrap();
560 u.buf = buf[used..].to_vec();
561 Ok(())
562 }
563 UniKind::Unknown => Ok(()),
564 }
565 }
566
567 fn control_frames(&mut self, buf: &[u8]) -> Result<usize, H3Error> {
569 let mut pos = 0;
570 loop {
571 let mut r = Reader::new(&buf[pos..]);
572 let (Some(ty), Some(len)) = (r.varint(), r.varint()) else {
573 if buf.len() - pos > 16 {
574 return Err(H3Error::new(code::FRAME_ERROR, "bad frame header"));
575 }
576 return Ok(pos);
577 };
578 if self.peer_settings.is_none() && ty != frame::SETTINGS {
579 return Err(H3Error::new(code::MISSING_SETTINGS, "first control frame is not SETTINGS"));
580 }
581 if len > 16 << 10 {
583 return Err(H3Error::new(code::EXCESSIVE_LOAD, "control frame too large"));
584 }
585 if (r.remaining() as u64) < len {
586 return Ok(pos);
587 }
588 let payload = r.bytes(len as usize).unwrap();
589 pos += r.position();
590 match ty {
591 frame::SETTINGS => {
592 if self.peer_settings.is_some() {
593 return Err(H3Error::new(code::FRAME_UNEXPECTED, "second SETTINGS"));
594 }
595 let s = Settings::decode(payload)?;
596 self.encoder
597 .set_peer_settings(s.qpack_max_table_capacity.unwrap_or(0), s.qpack_blocked_streams.unwrap_or(0));
598 self.peer_settings = Some(s);
599 }
600 frame::GOAWAY => {
601 let id = frame::single_varint(payload)?;
602 if !self.is_server && (is_server_initiated(id) || !is_bidi(id)) {
603 return Err(H3Error::new(code::ID_ERROR, "GOAWAY with a non-request stream ID"));
604 }
605 if self.goaway_recv.is_some_and(|g| id > g) {
606 return Err(H3Error::new(code::ID_ERROR, "GOAWAY ID increased"));
607 }
608 self.goaway_recv = Some(id);
609 self.events.push_back(H3Event::GoAway { id });
610 }
611 frame::MAX_PUSH_ID => {
612 if !self.is_server {
613 return Err(H3Error::new(code::FRAME_UNEXPECTED, "MAX_PUSH_ID from a server"));
614 }
615 frame::single_varint(payload)?;
616 }
617 frame::CANCEL_PUSH => {
618 frame::single_varint(payload)?;
619 }
620 frame::DATA | frame::HEADERS | frame::PUSH_PROMISE => {
621 return Err(H3Error::new(code::FRAME_UNEXPECTED, "frame not allowed on the control stream"))
622 }
623 t if frame::is_reserved_h2(t) => return Err(H3Error::new(code::FRAME_UNEXPECTED, "HTTP/2 frame type")),
624 _ => {} }
626 }
627 }
628
629 fn pump(&mut self, conn: &mut Connection, id: u64) -> Result<(), H3Error> {
632 let mut b = std::mem::take(&mut self.scratch);
633 let res = self.pump_inner(conn, id, &mut b);
634 self.scratch = b;
635 res
636 }
637
638 fn pump_inner(&mut self, conn: &mut Connection, id: u64, b: &mut [u8]) -> Result<(), H3Error> {
641 loop {
642 let Some(r) = self.reqs.get_mut(&id) else { return Ok(()) };
643 if r.fin_seen || r.blocked || r.body.len() >= self.cfg.body_buffer || r.inbuf.len() > b.len() * 2 {
644 break;
645 }
646 match conn.stream_recv(id, b) {
647 Ok((n, fin)) => {
648 r.inbuf.extend_from_slice(&b[..n]);
649 r.fin_seen = fin;
650 self.parse(conn, id)?;
651 if n == 0 && !fin {
652 break;
653 }
654 }
655 Err(StreamError::Reset(c)) => return self.on_reset(conn, id, c),
656 Err(_) => break,
657 }
658 }
659 self.parse(conn, id)?;
660 self.after_parse(conn, id);
661 Ok(())
662 }
663
664 fn after_parse(&mut self, conn: &mut Connection, id: u64) {
665 let Some(r) = self.reqs.get_mut(&id) else { return };
666 if !r.body.is_empty() && !r.data_event {
667 r.data_event = true;
668 self.events.push_back(H3Event::Data { stream: id });
669 }
670 if r.fin_seen && !r.finished && r.inbuf.is_empty() && !r.blocked {
671 if r.data_left > 0 || r.skip_left > 0 {
672 self.reject(conn, id, code::FRAME_ERROR);
673 } else if !r.headers_done {
674 self.reject(conn, id, code::REQUEST_INCOMPLETE);
675 } else if r.content_length.is_some_and(|cl| cl != r.body_len) {
676 self.reject(conn, id, code::MESSAGE_ERROR);
677 } else if r.body.is_empty() {
678 r.finished = true;
679 self.events.push_back(H3Event::Finished { stream: id });
680 self.maybe_drop(id);
681 }
682 }
683 }
684
685 fn parse(&mut self, conn: &mut Connection, id: u64) -> Result<(), H3Error> {
686 loop {
687 let max_fs = self.cfg.max_field_section_size;
688 let body_cap = self.cfg.body_buffer;
689 let Some(r) = self.reqs.get_mut(&id) else { return Ok(()) };
690 if r.blocked || r.inbuf.is_empty() {
691 return Ok(());
692 }
693 if r.data_left > 0 {
694 if r.body.len() >= body_cap {
695 return Ok(());
696 }
697 let n = (r.data_left as usize).min(r.inbuf.len()).min(body_cap - r.body.len());
698 r.body.extend(&r.inbuf[..n]);
699 r.inbuf.drain(..n);
700 r.data_left -= n as u64;
701 r.body_len += n as u64;
702 if r.content_length.is_some_and(|cl| r.body_len > cl) {
703 self.reject(conn, id, code::MESSAGE_ERROR);
704 return Ok(());
705 }
706 continue;
707 }
708 if r.skip_left > 0 {
709 let n = (r.skip_left as usize).min(r.inbuf.len());
710 r.inbuf.drain(..n);
711 r.skip_left -= n as u64;
712 continue;
713 }
714 let mut rd = Reader::new(&r.inbuf);
715 let (Some(ty), Some(len)) = (rd.varint(), rd.varint()) else {
716 if r.inbuf.len() > 16 {
717 return Err(H3Error::new(code::FRAME_ERROR, "bad frame header"));
718 }
719 return Ok(());
720 };
721 let hdr = rd.position();
722 match ty {
723 frame::DATA => {
724 if !r.headers_done || r.trailers_done {
725 return Err(H3Error::new(code::FRAME_UNEXPECTED, "DATA before HEADERS or after trailers"));
726 }
727 r.inbuf.drain(..hdr);
728 r.data_left = len;
729 }
730 frame::HEADERS => {
731 if r.trailers_done {
732 return Err(H3Error::new(code::FRAME_UNEXPECTED, "HEADERS after trailers"));
733 }
734 if len > max_fs + 1024 {
735 self.reject(conn, id, code::EXCESSIVE_LOAD);
736 return Ok(());
737 }
738 if ((r.inbuf.len() - hdr) as u64) < len {
739 return Ok(());
740 }
741 let end = hdr + len as usize;
742 let block: Vec<u8> = r.inbuf[hdr..end].to_vec();
743 r.inbuf.drain(..end);
744 match self.decoder.decode(id, &block) {
745 Ok(Decoded::Fields(f)) => self.on_fields(conn, id, f),
746 Ok(Decoded::Blocked) => {
747 self.reqs.get_mut(&id).unwrap().blocked = true;
748 return Ok(());
749 }
750 Err(simoom_qpack::Error::FieldSectionTooLarge) => {
751 self.reject(conn, id, code::EXCESSIVE_LOAD);
752 return Ok(());
753 }
754 Err(e) => return Err(H3Error::new(e.code(), "QPACK decompression failed")),
755 }
756 }
757 frame::PUSH_PROMISE => {
758 return Err(if self.is_server {
759 H3Error::new(code::FRAME_UNEXPECTED, "PUSH_PROMISE from a client")
760 } else {
761 H3Error::new(code::ID_ERROR, "PUSH_PROMISE without MAX_PUSH_ID")
762 })
763 }
764 frame::SETTINGS | frame::GOAWAY | frame::MAX_PUSH_ID | frame::CANCEL_PUSH => {
765 return Err(H3Error::new(code::FRAME_UNEXPECTED, "control frame on a request stream"))
766 }
767 t if frame::is_reserved_h2(t) => return Err(H3Error::new(code::FRAME_UNEXPECTED, "HTTP/2 frame type")),
768 _ => {
769 r.inbuf.drain(..hdr);
770 r.skip_left = len;
771 }
772 }
773 }
774 }
775
776 fn on_fields(&mut self, conn: &mut Connection, id: u64, fields: Vec<Field>) {
777 let is_server = self.is_server;
778 let Some(r) = self.reqs.get_mut(&id) else { return };
779 if !r.headers_done {
780 let mut res = if is_server { validate_request(&fields) } else { validate_response(&fields) };
781 if is_server && !self.cfg.enable_connect_protocol && fields.iter().any(|f| f.name == b":protocol") {
782 res = Err(());
783 }
784 match res {
785 Ok(v) => {
786 if !v.informational {
787 r.headers_done = true;
788 r.content_length = v.content_length;
789 }
790 self.events.push_back(H3Event::Headers { stream: id, fields });
791 }
792 Err(()) => self.reject(conn, id, code::MESSAGE_ERROR),
793 }
794 } else if validate_trailers(&fields).is_err() {
795 self.reject(conn, id, code::MESSAGE_ERROR);
796 } else {
797 r.trailers_done = true;
798 self.events.push_back(H3Event::Trailers { stream: id, fields });
799 }
800 }
801
802 fn resume_unblocked(&mut self, conn: &mut Connection) -> Result<(), H3Error> {
804 while let Some((id, f)) = self.pending_fields.pop_front() {
805 match f {
806 None => self.reject(conn, id, code::EXCESSIVE_LOAD),
807 Some(f) => {
808 self.on_fields(conn, id, f);
809 self.pump(conn, id)?;
810 }
811 }
812 }
813 Ok(())
814 }
815
816 pub fn recv_body(&mut self, now: Instant, conn: &mut Connection, stream: u64, out: &mut [u8]) -> Result<(usize, bool), SendError> {
819 let r = self.reqs.get_mut(&stream).ok_or(SendError::UnknownStream)?;
820 let n = out.len().min(r.body.len());
821 let (a, b) = r.body.as_slices();
822 if n <= a.len() {
823 out[..n].copy_from_slice(&a[..n]);
824 } else {
825 out[..a.len()].copy_from_slice(a);
826 out[a.len()..n].copy_from_slice(&b[..n - a.len()]);
827 }
828 r.body.drain(..n);
829 if r.body.is_empty() {
830 r.data_event = false;
831 }
832 if let Err(e) = self.pump(conn, stream) {
834 self.fail(now, conn, e);
835 }
836 let Some(r) = self.reqs.get_mut(&stream) else { return Ok((n, true)) };
837 let fin = r.finished || (r.fin_seen && r.inbuf.is_empty() && r.body.is_empty() && r.data_left == 0 && r.headers_done);
838 if fin && !r.finished {
839 r.finished = true;
840 self.events.push_back(H3Event::Finished { stream });
841 self.maybe_drop(stream);
842 }
843 Ok((n, fin))
844 }
845
846 fn maybe_drop(&mut self, id: u64) {
847 if self.reqs.get(&id).is_some_and(|r| r.finished && r.send_done && r.out.is_empty()) {
848 self.reqs.remove(&id);
849 }
850 }
851
852 fn encode_headers(&mut self, id: u64, fields: &[(&[u8], &[u8])], out: &mut Vec<u8>) -> Result<(), SendError> {
855 if let Some(max) = self.peer_settings.as_ref().and_then(|s| s.max_field_section_size) {
856 let size: u64 = fields.iter().map(|(n, v)| n.len() as u64 + v.len() as u64 + 32).sum();
857 if size > max {
858 return Err(SendError::HeadersTooLarge);
859 }
860 }
861 let mut block = Vec::with_capacity(64);
862 self.encoder.encode(id, fields, &mut block);
863 put_varint(out, frame::HEADERS);
864 put_varint(out, block.len() as u64);
865 out.extend_from_slice(&block);
866 Ok(())
867 }
868
869 fn write_frame(&mut self, conn: &mut Connection, id: u64, bytes: Vec<u8>, fin: bool) -> Result<(), SendError> {
870 let r = self.reqs.get_mut(&id).ok_or(SendError::UnknownStream)?;
871 if r.out.is_empty() {
872 let k = match conn.stream_send(id, &bytes, fin) {
873 Ok(k) => k,
874 Err(StreamError::Blocked) => 0,
875 Err(e) => return Err(e.into()),
876 };
877 if k < bytes.len() {
878 r.out.extend_from_slice(&bytes[k..]);
879 r.finish_after_out = fin;
880 } else if fin {
881 r.send_done = true;
882 }
883 } else {
884 r.out.extend_from_slice(&bytes);
885 r.finish_after_out = fin;
886 }
887 Ok(())
888 }
889
890 pub fn send_headers(&mut self, conn: &mut Connection, stream: u64, fields: &[(&[u8], &[u8])], fin: bool) -> Result<(), SendError> {
893 let r = self.reqs.get(&stream).ok_or(SendError::UnknownStream)?;
894 if r.send_done || r.headers_sent {
895 return Err(SendError::InvalidState);
896 }
897 let interim = self.is_server && fields.iter().any(|(n, v)| *n == b":status" && v.first() == Some(&b'1'));
898 let mut b = Vec::with_capacity(128);
899 self.encode_headers(stream, fields, &mut b)?;
900 self.write_frame(conn, stream, b, fin && !interim)?;
901 if !interim {
902 self.reqs.get_mut(&stream).unwrap().headers_sent = true;
903 }
904 self.flush_qpack(conn);
905 self.maybe_drop(stream);
906 Ok(())
907 }
908
909 pub fn send_body(&mut self, conn: &mut Connection, stream: u64, data: &[u8], fin: bool) -> Result<usize, SendError> {
912 let r = self.reqs.get_mut(&stream).ok_or(SendError::UnknownStream)?;
913 if !r.headers_sent || r.send_done {
914 return Err(SendError::InvalidState);
915 }
916 if !r.out.is_empty() {
917 r.want_writable = true;
918 return Ok(0);
919 }
920 if data.is_empty() {
921 if fin {
922 conn.stream_finish(stream)?;
923 r.send_done = true;
924 self.maybe_drop(stream);
925 }
926 return Ok(0);
927 }
928 let room = conn.stream_writable(stream).unwrap_or(0) as usize;
929 let hdr_len = 1 + varint_len(data.len() as u64);
930 if room == 0 {
931 r.want_writable = true;
932 mark_blocked(conn, stream);
933 return Ok(0);
934 }
935 if room <= hdr_len {
936 let n = data.len().min(SMALL_FRAME);
940 let all = n == data.len() && fin;
941 let mut b = Vec::with_capacity(9 + n);
942 put_varint(&mut b, frame::DATA);
943 put_varint(&mut b, n as u64);
944 b.extend_from_slice(&data[..n]);
945 if n < data.len() {
946 r.want_writable = true;
947 }
948 self.write_frame(conn, stream, b, all)?;
949 if all {
950 self.maybe_drop(stream);
951 }
952 return Ok(n);
953 }
954 let n = data.len().min(room - hdr_len);
955 let mut h = Vec::with_capacity(9);
956 put_varint(&mut h, frame::DATA);
957 put_varint(&mut h, n as u64);
958 let all = n == data.len() && fin;
959 conn.stream_send(stream, &h, false)?;
960 conn.stream_send(stream, &data[..n], all)?;
961 if all {
962 r.send_done = true;
963 self.maybe_drop(stream);
964 } else if n < data.len() {
965 r.want_writable = true;
970 mark_blocked(conn, stream);
971 }
972 Ok(n)
973 }
974
975 pub fn send_trailers(&mut self, conn: &mut Connection, stream: u64, fields: &[(&[u8], &[u8])]) -> Result<(), SendError> {
977 let r = self.reqs.get(&stream).ok_or(SendError::UnknownStream)?;
978 if !r.headers_sent || r.send_done {
979 return Err(SendError::InvalidState);
980 }
981 let mut b = Vec::new();
982 self.encode_headers(stream, fields, &mut b)?;
983 self.write_frame(conn, stream, b, true)?;
984 self.flush_qpack(conn);
985 self.maybe_drop(stream);
986 Ok(())
987 }
988
989 pub fn reset_stream(&mut self, conn: &mut Connection, stream: u64, code_: u64) {
991 let _ = conn.stream_stop(stream, code_);
992 let _ = conn.stream_reset(stream, code_);
993 if let Some(r) = self.reqs.remove(&stream) {
994 if !r.headers_done || r.blocked {
995 self.decoder.cancel_stream(stream);
996 }
997 }
998 self.flush_qpack(conn);
999 }
1000
1001 pub fn send_request(&mut self, conn: &mut Connection, fields: &[(&[u8], &[u8])], fin: bool) -> Result<u64, SendError> {
1003 if self.goaway_recv.is_some() {
1004 return Err(SendError::GoingAway);
1005 }
1006 let id = conn.open_bi()?;
1007 self.reqs.insert(id, Req::default());
1008 self.send_headers(conn, id, fields, fin)?;
1009 Ok(id)
1010 }
1011
1012 pub fn goaway(&mut self, conn: &mut Connection) -> u64 {
1015 let id = self.max_request.map_or(0, |m| m + 4);
1016 let id = self.goaway_sent.map_or(id, |g| g.min(id));
1017 self.goaway_sent = Some(id);
1018 let mut b = Vec::with_capacity(10);
1019 put_varint(&mut b, frame::GOAWAY);
1020 put_varint(&mut b, varint_len(id) as u64);
1021 put_varint(&mut b, id);
1022 let c = self.control_out;
1023 self.send_uni(conn, c, &b);
1024 id
1025 }
1026
1027 pub fn is_idle_after_goaway(&self) -> bool {
1029 self.goaway_sent.is_some() && self.reqs.is_empty()
1030 }
1031}