1use std::collections::HashMap;
5use std::hash::{BuildHasherDefault, Hasher};
6
7use simoom_hpack::{Decoder, Encoder, Error as HpackError};
8
9use crate::budget::{Kind as Budget, Meter};
10use crate::frame::{self, be32, flag, kind, setting, ErrorCode, FrameHeader, DEFAULT_WINDOW, HEADER_LEN, MAX_WINDOW, PREFACE};
11use crate::headers::{connection_specific, valid_name, valid_value, Headers, Kind as HeadKind};
12use crate::upgrade::{base64url_decode, base64url_encode};
13use crate::{Config, Error, Event};
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum Role {
18 Client,
19 Server,
20}
21
22#[derive(Default)]
24struct IdHasher(u64);
25
26impl Hasher for IdHasher {
27 fn finish(&self) -> u64 {
28 self.0
29 }
30 fn write(&mut self, b: &[u8]) {
31 for &x in b {
32 self.0 = (self.0.rotate_left(8) ^ x as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15);
33 }
34 }
35 fn write_u32(&mut self, n: u32) {
36 self.0 = (n as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15).rotate_left(32);
37 }
38}
39
40type StreamMap = HashMap<u32, Stream, BuildHasherDefault<IdHasher>>;
41
42#[derive(Debug, Default)]
43struct Stream {
44 send_window: i64,
45 recv_window: i64,
46 unreleased: u32,
48 unacked: u32,
50 received: u64,
52 content_length: Option<u64>,
53 remote_end: bool,
54 local_end: bool,
55 reset: bool,
56 peer_reset: bool,
58 open: bool,
60 handler: bool,
62 final_sent: bool,
63 final_recv: bool,
64 blocked: bool,
65 head: bool,
67}
68
69impl Stream {
70 fn closed(&self) -> bool {
71 self.reset || (self.local_end && self.remote_end)
72 }
73}
74
75#[derive(Clone, Copy, Debug, PartialEq, Eq)]
76enum Phase {
77 Preface,
79 Settings,
81 Open,
82 Closed,
83}
84
85#[derive(Clone, Copy, Debug)]
87struct Block {
88 stream: u32,
89 end_stream: bool,
90 self_dep: bool,
91 frames: u32,
92}
93
94type R = Result<(), (ErrorCode, &'static str)>;
95
96fn perr(msg: &'static str) -> R {
97 Err((ErrorCode::PROTOCOL_ERROR, msg))
98}
99
100fn calm(msg: &'static str) -> R {
101 Err((ErrorCode::ENHANCE_YOUR_CALM, msg))
102}
103
104const BDP_PING: [u8; 8] = *b"simoomBD";
105const CLOSED_WINDOW: usize = 32;
107const SEEN_WINDOW: usize = 2048;
109const SHUTDOWN_PING: [u8; 8] = *b"simoomGA";
110const KEEPALIVE_PING: [u8; 8] = *b"simoomKA";
111const BDP_INTERVAL_MS: u64 = 500;
113
114fn local_settings(role: Role, c: &Config) -> Vec<(u16, u32)> {
116 let mut s = Vec::with_capacity(6);
117 if c.header_table_size != 4096 {
118 s.push((setting::HEADER_TABLE_SIZE, c.header_table_size));
119 }
120 if role == Role::Client {
121 s.push((setting::ENABLE_PUSH, 0));
122 } else {
123 s.push((setting::MAX_CONCURRENT_STREAMS, c.max_concurrent_streams));
124 if cfg!(feature = "connect-protocol") && c.enable_connect_protocol {
125 s.push((setting::ENABLE_CONNECT_PROTOCOL, 1));
126 }
127 }
128 if c.initial_window_size != DEFAULT_WINDOW {
129 s.push((setting::INITIAL_WINDOW_SIZE, c.initial_window_size));
130 }
131 if c.max_frame_size != frame::MIN_FRAME_SIZE {
132 s.push((setting::MAX_FRAME_SIZE, c.max_frame_size));
133 }
134 s.push((setting::MAX_HEADER_LIST_SIZE, c.max_header_list_size));
135 s
136}
137
138pub fn http2_settings_header(config: &Config) -> String {
140 let mut p = Vec::new();
141 for (id, v) in local_settings(Role::Client, &sanitize(config.clone())) {
142 p.extend_from_slice(&id.to_be_bytes());
143 p.extend_from_slice(&v.to_be_bytes());
144 }
145 base64url_encode(&p)
146}
147
148fn sanitize(mut c: Config) -> Config {
149 c.max_frame_size = c.max_frame_size.clamp(frame::MIN_FRAME_SIZE, frame::MAX_FRAME_SIZE);
150 c.initial_window_size = c.initial_window_size.min(MAX_WINDOW);
151 c.connection_window_size = c.connection_window_size.clamp(DEFAULT_WINDOW, MAX_WINDOW);
152 c.max_stream_window = c.max_stream_window.clamp(c.initial_window_size, MAX_WINDOW);
153 c.max_connection_window = c.max_connection_window.clamp(c.connection_window_size, MAX_WINDOW);
154 c.max_send_buffer = c.max_send_buffer.max(1024);
155 c
156}
157
158pub struct Connection {
160 role: Role,
161 cfg: Config,
162 phase: Phase,
163 now: u64,
164 out: Vec<u8>,
165 out_pos: usize,
166 enc: Encoder,
167 dec: Decoder,
168 streams: StreamMap,
169 rx: Headers,
170 hb: Option<Block>,
171 hb_buf: Vec<u8>,
172 scratch: Vec<u8>,
173 peer_initial_window: u32,
175 peer_max_frame: usize,
176 peer_max_concurrent: u32,
177 peer_max_header_list: u32,
179 peer_connect_protocol: bool,
181 last_recv: Option<u64>,
184 keepalive_deadline: Option<u64>,
185 send_window: i64,
187 recv_window: i64,
188 conn_target: u32,
189 conn_unacked: u32,
190 stream_target: u32,
191 stream_effective: u32,
194 first_settings_acked: bool,
195 settings_unacked: u32,
196 settings_deadline: Option<u64>,
197 next_stream_id: u32,
199 last_peer_stream: u32,
200 open_count: u32,
201 handlers: u32,
202 goaway_sent: Option<u32>,
204 graceful_deadline: Option<u64>,
205 goaway_recv: Option<u32>,
206 close_code: Option<ErrorCode>,
207 bdp_sent: bool,
209 bdp_bytes: u64,
210 bdp_last: Option<u64>,
211 meter: Meter,
212 recent_closed: [u32; CLOSED_WINDOW],
217 closed_pos: usize,
218 seen: [u64; SEEN_WINDOW / 64],
221 blocked: Vec<u32>,
222}
223
224impl std::fmt::Debug for Connection {
225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
226 f.debug_struct("Connection")
227 .field("role", &self.role)
228 .field("phase", &self.phase)
229 .field("streams", &self.streams.len())
230 .field("handlers", &self.handlers)
231 .finish()
232 }
233}
234
235impl Connection {
236 fn new(role: Role, cfg: Config) -> Connection {
237 let cfg = sanitize(cfg);
238 let mut c = Connection {
239 role,
240 phase: Phase::Settings,
241 now: 0,
242 out: Vec::with_capacity(1024),
243 out_pos: 0,
244 enc: Encoder::new(cfg.encoder_table_size as usize),
245 dec: Decoder::new((cfg.header_table_size as usize).max(4096), cfg.max_header_list_size as usize),
246 streams: StreamMap::default(),
247 rx: Headers::default(),
248 hb: None,
249 hb_buf: Vec::new(),
250 scratch: Vec::new(),
251 peer_initial_window: DEFAULT_WINDOW,
252 peer_max_frame: frame::MIN_FRAME_SIZE as usize,
253 peer_max_concurrent: u32::MAX,
254 peer_max_header_list: u32::MAX,
255 peer_connect_protocol: false,
256 last_recv: None,
257 keepalive_deadline: None,
258 send_window: DEFAULT_WINDOW as i64,
259 recv_window: cfg.connection_window_size as i64,
260 conn_target: cfg.connection_window_size,
261 conn_unacked: 0,
262 stream_target: cfg.initial_window_size,
263 stream_effective: cfg.initial_window_size.max(DEFAULT_WINDOW),
264 first_settings_acked: false,
265 settings_unacked: 0,
266 settings_deadline: None,
267 next_stream_id: if role == Role::Client { 1 } else { 2 },
268 last_peer_stream: 0,
269 open_count: 0,
270 handlers: 0,
271 goaway_sent: None,
272 graceful_deadline: None,
273 goaway_recv: None,
274 close_code: None,
275 bdp_sent: false,
276 bdp_bytes: 0,
277 bdp_last: None,
278 meter: Meter::new(&cfg.budgets),
279 recent_closed: [0; CLOSED_WINDOW],
280 closed_pos: 0,
281 seen: [0; SEEN_WINDOW / 64],
282 blocked: Vec::new(),
283 cfg,
284 };
285 c.rx.allow_protocol = cfg!(feature = "connect-protocol") && role == Role::Server && c.cfg.enable_connect_protocol;
286 if role == Role::Client {
287 c.out.extend_from_slice(PREFACE);
288 }
289 frame::write_settings(&mut c.out, &local_settings(role, &c.cfg));
290 c.settings_unacked = 1;
291 if c.conn_target > DEFAULT_WINDOW {
292 frame::write_window_update(&mut c.out, 0, c.conn_target - DEFAULT_WINDOW);
293 }
294 c
295 }
296
297 pub fn server(cfg: Config) -> Connection {
300 let mut c = Connection::new(Role::Server, cfg);
301 c.phase = Phase::Preface;
302 c
303 }
304
305 pub fn client(cfg: Config) -> Connection {
308 Connection::new(Role::Client, cfg)
309 }
310
311 pub fn server_upgrade(cfg: Config, http2_settings: &[u8]) -> Result<Connection, Error> {
316 let payload = base64url_decode(http2_settings).ok_or(Error::InvalidUpgradeSettings)?;
317 if payload.len() % 6 != 0 {
318 return Err(Error::InvalidUpgradeSettings);
319 }
320 let mut c = Connection::server(cfg);
321 if c.apply_settings(&payload).is_err() {
322 return Err(Error::InvalidUpgradeSettings);
323 }
324 let s = Stream {
325 send_window: c.peer_initial_window as i64,
326 recv_window: 0,
327 remote_end: true,
328 open: true,
329 handler: true,
330 ..Stream::default()
331 };
332 c.streams.insert(1, s);
333 c.open_count = 1;
334 c.handlers = 1;
335 c.mark_seen(1);
336 Ok(c)
337 }
338
339 pub fn client_upgrade(cfg: Config, head: bool) -> Connection {
343 let mut c = Connection::client(cfg);
344 let s = Stream {
345 send_window: c.peer_initial_window as i64,
346 recv_window: c.stream_effective as i64,
347 local_end: true,
348 open: true,
349 final_sent: true,
350 head,
351 ..Stream::default()
352 };
353 c.streams.insert(1, s);
354 c.open_count = 1;
355 c.next_stream_id = 3;
356 c
357 }
358
359 pub fn output(&self) -> &[u8] {
363 &self.out[self.out_pos..]
364 }
365
366 pub fn take_output(&mut self, mut empty: Vec<u8>) -> Vec<u8> {
370 empty.clear();
371 let mut v = std::mem::replace(&mut self.out, empty);
372 if self.out_pos > 0 {
373 v.drain(..self.out_pos);
374 self.out_pos = 0;
375 }
376 v
377 }
378
379 pub fn advance_output(&mut self, n: usize) {
381 self.out_pos = (self.out_pos + n).min(self.out.len());
382 if self.out_pos == self.out.len() {
383 self.out.clear();
384 self.out_pos = 0;
385 if self.out.capacity() > 4 * self.cfg.max_send_buffer {
386 self.out = Vec::with_capacity(16 * 1024);
387 }
388 } else if self.out_pos > 64 * 1024 && self.out_pos * 2 > self.out.len() {
389 self.out.drain(..self.out_pos);
390 self.out_pos = 0;
391 }
392 }
393
394 fn pending(&self) -> usize {
395 self.out.len() - self.out_pos
396 }
397
398 pub fn role(&self) -> Role {
402 self.role
403 }
404
405 pub fn wants_close(&self) -> bool {
408 let goaway_done = self.goaway_sent.is_some() || (self.goaway_recv.is_some() && self.role == Role::Client);
413 self.phase == Phase::Closed || (goaway_done && self.streams.is_empty())
414 }
415
416 pub fn close_code(&self) -> Option<ErrorCode> {
418 self.close_code
419 }
420
421 pub fn active_handlers(&self) -> u32 {
423 self.handlers
424 }
425
426 pub fn open_streams(&self) -> u32 {
428 self.open_count
429 }
430
431 pub fn tracked_streams(&self) -> usize {
433 self.streams.len()
434 }
435
436 pub fn peer_max_concurrent_streams(&self) -> u32 {
438 self.peer_max_concurrent
439 }
440
441 pub fn can_open_stream(&self) -> bool {
443 self.role == Role::Client
444 && self.phase != Phase::Closed
445 && self.goaway_recv.is_none()
446 && self.goaway_sent.is_none()
447 && self.open_count < self.peer_max_concurrent
448 && self.next_stream_id <= MAX_WINDOW
449 }
450
451 pub fn send_capacity(&self, stream: u32) -> usize {
454 match self.streams.get(&stream) {
455 Some(s) if !s.reset && !s.local_end => {
456 let room = self.cfg.max_send_buffer.saturating_sub(self.pending()) as i64;
457 s.send_window.min(self.send_window).min(room).max(0) as usize
458 }
459 _ => 0,
460 }
461 }
462
463 pub fn receive_windows(&self) -> (u32, u32) {
465 (self.conn_target, self.stream_target)
466 }
467
468 pub fn poll_timeout(&self) -> Option<u64> {
471 let t = match (self.settings_deadline, self.graceful_deadline) {
472 (Some(a), Some(b)) => Some(a.min(b)),
473 (a, b) => a.or(b),
474 };
475 match (t, self.keepalive_due()) {
476 (Some(a), Some(b)) => Some(a.min(b)),
477 (a, b) => a.or(b),
478 }
479 }
480
481 fn keepalive_due(&self) -> Option<u64> {
483 if !cfg!(feature = "keepalive") {
484 return None;
485 }
486 let interval = self.cfg.keepalive_interval_ms?;
487 if self.phase == Phase::Closed {
488 return None;
489 }
490 self.keepalive_deadline.or_else(|| self.last_recv.map(|t| t.saturating_add(interval)))
491 }
492
493 fn keepalive(&mut self, now: u64, sink: &mut dyn FnMut(Event<'_>)) {
496 if !cfg!(feature = "keepalive") {
497 return;
498 }
499 let Some(interval) = self.cfg.keepalive_interval_ms else { return };
500 if self.phase == Phase::Closed {
501 return;
502 }
503 if let Some(d) = self.keepalive_deadline {
504 if now >= d {
505 self.conn_error(ErrorCode::NO_ERROR, "PING keepalive timeout", sink);
506 }
507 return;
508 }
509 let last = *self.last_recv.get_or_insert(now);
510 if now >= last.saturating_add(interval) {
511 frame::write_ping(&mut self.out, KEEPALIVE_PING, false);
512 self.keepalive_deadline = Some(now.saturating_add(self.cfg.keepalive_timeout_ms));
513 }
514 }
515
516 pub fn handle_timeout(&mut self, now: u64, sink: &mut dyn FnMut(Event<'_>)) {
518 self.now = now;
519 if self.phase == Phase::Closed {
520 return;
521 }
522 if self.settings_deadline.is_some_and(|d| now >= d) {
523 self.conn_error(ErrorCode::SETTINGS_TIMEOUT, "SETTINGS not acknowledged", sink);
524 return;
525 }
526 if self.graceful_deadline.is_some_and(|d| now >= d) {
527 self.final_goaway();
528 }
529 self.keepalive(now, sink);
530 }
531
532 pub fn recv(&mut self, input: &[u8], now: u64, sink: &mut dyn FnMut(Event<'_>)) -> usize {
541 self.now = now;
542 if cfg!(feature = "keepalive") && !input.is_empty() {
543 self.last_recv = Some(now);
545 self.keepalive_deadline = None;
546 }
547 if self.settings_unacked > 0 && self.settings_deadline.is_none() {
548 self.settings_deadline = Some(now + self.cfg.settings_timeout_ms);
549 }
550 let mut pos = 0;
551 while self.phase != Phase::Closed {
552 if self.pending() > 2 * self.cfg.max_send_buffer {
553 break;
554 }
555 let rest = &input[pos..];
556 if self.phase == Phase::Preface {
557 let n = rest.len().min(PREFACE.len());
558 if rest[..n] != PREFACE[..n] {
559 self.conn_error(ErrorCode::PROTOCOL_ERROR, "invalid connection preface", sink);
560 break;
561 }
562 if n < PREFACE.len() {
563 break;
564 }
565 pos += n;
566 self.phase = Phase::Settings;
567 continue;
568 }
569 if rest.len() < HEADER_LEN {
570 break;
571 }
572 let h = FrameHeader::parse(rest);
573 if h.len > self.cfg.max_frame_size as usize {
574 self.conn_error(ErrorCode::FRAME_SIZE_ERROR, "frame larger than SETTINGS_MAX_FRAME_SIZE", sink);
575 break;
576 }
577 if rest.len() - HEADER_LEN < h.len {
578 break;
579 }
580 pos += HEADER_LEN + h.len;
581 if let Err((code, msg)) = self.on_frame(h, &rest[HEADER_LEN..HEADER_LEN + h.len], sink) {
582 self.conn_error(code, msg, sink);
583 }
584 }
585 if self.phase == Phase::Closed {
586 input.len()
587 } else {
588 pos
589 }
590 }
591
592 fn conn_error(&mut self, code: ErrorCode, msg: &'static str, sink: &mut dyn FnMut(Event<'_>)) {
593 if self.phase == Phase::Closed {
594 return;
595 }
596 frame::write_goaway(&mut self.out, self.last_peer_stream, code, msg.as_bytes());
597 self.phase = Phase::Closed;
598 self.close_code = Some(code);
599 self.hb = None;
600 self.settings_deadline = None;
601 self.graceful_deadline = None;
602 sink(Event::Closed { code });
603 }
604
605 fn hit(&mut self, b: Budget) -> bool {
606 self.meter.hit(b, self.now)
607 }
608
609 fn is_idle(&self, id: u32) -> bool {
610 let ours = (id & 1 == 1) == (self.role == Role::Client);
611 if ours {
612 id >= self.next_stream_id
613 } else {
614 id > self.last_peer_stream
615 }
616 }
617
618 fn recently_closed(&self, id: u32) -> bool {
619 self.recent_closed.contains(&id)
620 }
621
622 fn refused_or_reset(&self, id: u32) -> bool {
624 !self.is_idle(id) && !self.streams.contains_key(&id) && !self.recently_closed(id) && self.existed(id)
625 }
626
627 fn existed(&self, id: u32) -> bool {
631 let ours = (id & 1 == 1) == (self.role == Role::Client);
632 if ours || id > self.last_peer_stream {
633 return ours;
634 }
635 let back = (self.last_peer_stream - id) / 2;
636 if back as usize >= SEEN_WINDOW {
637 return true;
638 }
639 let slot = (id / 2) as usize % SEEN_WINDOW;
640 self.seen[slot / 64] & (1 << (slot % 64)) != 0
641 }
642
643 fn mark_seen(&mut self, id: u32) {
646 let prev = self.last_peer_stream;
647 let gap = if prev == 0 { SEEN_WINDOW as u32 } else { (id - prev) / 2 };
648 if gap as usize >= SEEN_WINDOW {
649 self.seen = [0; SEEN_WINDOW / 64];
650 } else {
651 let mut k = prev + 2;
652 while k < id {
653 let slot = (k / 2) as usize % SEEN_WINDOW;
654 self.seen[slot / 64] &= !(1 << (slot % 64));
655 k += 2;
656 }
657 }
658 let slot = (id / 2) as usize % SEEN_WINDOW;
659 self.seen[slot / 64] |= 1 << (slot % 64);
660 self.last_peer_stream = id;
661 }
662
663 fn on_frame(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
664 if self.phase == Phase::Settings {
665 if h.kind != kind::SETTINGS || h.has(flag::ACK) {
666 return perr("the first frame must be SETTINGS");
667 }
668 self.phase = Phase::Open;
669 }
670 if let Some(b) = &self.hb {
671 if h.kind != kind::CONTINUATION || h.stream != b.stream {
672 return perr("expected CONTINUATION");
673 }
674 }
675 match h.kind {
676 kind::DATA => self.on_data(h, p, sink),
677 kind::HEADERS => self.on_headers(h, p, sink),
678 kind::PRIORITY => self.on_priority(h, p, sink),
679 kind::RST_STREAM => self.on_rst(h, p, sink),
680 kind::SETTINGS => self.on_settings(h, p, sink),
681 kind::PUSH_PROMISE => perr("PUSH_PROMISE is disabled"),
682 kind::PING => self.on_ping(h, p, sink),
683 kind::GOAWAY => self.on_goaway(h, p, sink),
684 kind::WINDOW_UPDATE => self.on_window_update(h, p, sink),
685 kind::CONTINUATION => self.on_continuation(h, p, sink),
686 _ => Ok(()), }
688 }
689
690 fn unpad<'a>(h: &FrameHeader, p: &'a [u8]) -> Result<&'a [u8], (ErrorCode, &'static str)> {
691 if !h.has(flag::PADDED) {
692 return Ok(p);
693 }
694 let Some(&pad) = p.first() else {
695 return Err((ErrorCode::FRAME_SIZE_ERROR, "padded frame without pad length"));
696 };
697 if pad as usize >= p.len() {
698 return Err((ErrorCode::PROTOCOL_ERROR, "padding longer than the payload"));
699 }
700 Ok(&p[1..p.len() - pad as usize])
701 }
702
703 fn on_data(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
706 let id = h.stream;
707 if id == 0 {
708 return perr("DATA on stream 0");
709 }
710 let data = Self::unpad(&h, p)?;
711 let flen = p.len() as u32;
712 if flen as i64 > self.recv_window {
713 return Err((ErrorCode::FLOW_CONTROL_ERROR, "connection receive window exceeded"));
714 }
715 self.recv_window -= flen as i64;
716 let end = h.has(flag::END_STREAM);
717 if data.is_empty() && !end && self.hit(Budget::Empty) {
718 return calm("too many empty frames");
719 }
720 let idle = self.is_idle(id);
721 let client = self.role == Role::Client;
722 enum Next {
723 Closed,
724 Ignore,
725 StreamError(ErrorCode),
726 Deliver,
727 }
728 let next = match self.streams.get_mut(&id) {
729 None if idle => return perr("DATA on an idle stream"),
730 None => Next::Closed,
731 Some(s) if s.peer_reset || (s.remote_end && !s.reset) => Next::StreamError(ErrorCode::STREAM_CLOSED),
732 Some(s) if s.reset => Next::Ignore,
733 Some(s) if client && !s.final_recv => Next::StreamError(ErrorCode::PROTOCOL_ERROR),
734 Some(s) if flen as i64 > s.recv_window => Next::StreamError(ErrorCode::FLOW_CONTROL_ERROR),
735 Some(s) => {
736 s.recv_window -= flen as i64;
737 s.received += data.len() as u64;
738 let bad_length = match s.content_length {
739 Some(cl) if !s.head => s.received > cl || (end && s.received != cl),
740 _ => false,
741 };
742 if bad_length {
743 Next::StreamError(ErrorCode::PROTOCOL_ERROR)
744 } else {
745 s.unreleased += data.len() as u32;
746 if end {
747 s.remote_end = true;
748 }
749 Next::Deliver
750 }
751 }
752 };
753 match next {
754 Next::Closed => {
755 self.release_conn(flen);
756 if self.recently_closed(id) || !self.existed(id) {
757 frame::write_rst(&mut self.out, id, ErrorCode::STREAM_CLOSED);
761 if self.hit(Budget::RstSent) {
762 return calm("too many stream errors");
763 }
764 }
765 }
766 Next::Ignore => self.release_conn(flen),
767 Next::StreamError(code) => {
768 self.release_conn(flen);
769 self.stream_error(id, code, sink)?;
770 }
771 Next::Deliver => {
772 let pad = flen - data.len() as u32;
773 if pad > 0 {
774 self.credit(id, pad);
775 }
776 sink(Event::Data { stream: id, data, end_stream: end });
777 if !data.is_empty() {
778 self.bdp_on_data(data.len());
779 }
780 if end {
781 self.update(id);
782 }
783 }
784 }
785 Ok(())
786 }
787
788 fn release_conn(&mut self, n: u32) {
790 if n == 0 || self.phase == Phase::Closed {
791 return;
792 }
793 self.conn_unacked += n;
794 if self.conn_unacked >= self.conn_target / 2 {
795 frame::write_window_update(&mut self.out, 0, self.conn_unacked);
796 self.recv_window += self.conn_unacked as i64;
797 self.conn_unacked = 0;
798 }
799 }
800
801 fn credit(&mut self, id: u32, n: u32) {
803 if let Some(s) = self.streams.get_mut(&id) {
804 if !s.reset && !s.remote_end && self.phase != Phase::Closed {
805 s.unacked += n;
806 if s.unacked >= self.stream_target / 2 {
807 frame::write_window_update(&mut self.out, id, s.unacked);
808 s.recv_window += s.unacked as i64;
809 s.unacked = 0;
810 }
811 }
812 }
813 self.release_conn(n);
814 }
815
816 pub fn release(&mut self, stream: u32, n: usize) {
819 let Some(s) = self.streams.get_mut(&stream) else { return };
820 let n = n.min(s.unreleased as usize) as u32;
821 if n == 0 {
822 return;
823 }
824 s.unreleased -= n;
825 self.credit(stream, n);
826 }
827
828 fn bdp_on_data(&mut self, n: usize) {
829 if !self.cfg.window_autotune || self.phase == Phase::Closed {
830 return;
831 }
832 if self.bdp_sent {
833 self.bdp_bytes += n as u64;
834 return;
835 }
836 if self.conn_target >= self.cfg.max_connection_window && self.stream_target >= self.cfg.max_stream_window {
837 return;
838 }
839 if self.bdp_last.is_some_and(|t| self.now < t + BDP_INTERVAL_MS) {
840 return;
841 }
842 frame::write_ping(&mut self.out, BDP_PING, false);
843 self.bdp_sent = true;
844 self.bdp_bytes = n as u64;
845 self.bdp_last = Some(self.now);
846 }
847
848 fn bdp_ack(&mut self) {
853 self.bdp_sent = false;
854 let sample = self.bdp_bytes.min(MAX_WINDOW as u64) as u32;
855 let grow = |target: u32, max: u32| -> u32 {
856 if sample as u64 * 2 >= target as u64 {
857 (sample.saturating_mul(2)).max(target.saturating_mul(2)).min(max).max(target)
858 } else {
859 target
860 }
861 };
862 let conn = grow(self.conn_target, self.cfg.max_connection_window);
863 if conn > self.conn_target {
864 let delta = conn - self.conn_target;
865 self.conn_target = conn;
866 self.recv_window += delta as i64;
867 frame::write_window_update(&mut self.out, 0, delta);
868 }
869 let stream = grow(self.stream_target, self.cfg.max_stream_window);
870 if stream > self.stream_target {
871 let delta = (stream - self.stream_target) as i64;
872 self.stream_target = stream;
873 self.stream_effective = self.stream_effective.max(stream);
874 for s in self.streams.values_mut() {
875 if !s.remote_end && !s.reset {
876 s.recv_window += delta;
877 }
878 }
879 frame::write_settings(&mut self.out, &[(setting::INITIAL_WINDOW_SIZE, stream)]);
880 self.settings_unacked += 1;
881 if self.settings_deadline.is_none() {
882 self.settings_deadline = Some(self.now + self.cfg.settings_timeout_ms);
883 }
884 }
885 }
886
887 fn send_rst(&mut self, id: u32, code: ErrorCode, caused: bool) -> R {
892 frame::write_rst(&mut self.out, id, code);
893 if caused && self.hit(Budget::RstSent) {
894 return calm("too many stream errors");
895 }
896 Ok(())
897 }
898
899 fn mark_reset(&mut self, id: u32) -> bool {
902 let client = self.role == Role::Client;
903 let (credit, known) = match self.streams.get_mut(&id) {
904 Some(s) if !s.reset => {
905 s.reset = true;
906 let c = s.unreleased;
907 s.unreleased = 0;
908 (c, s.handler || client)
909 }
910 _ => return false,
911 };
912 self.release_conn(credit);
913 known
914 }
915
916 fn stream_error(&mut self, id: u32, code: ErrorCode, sink: &mut dyn FnMut(Event<'_>)) -> R {
918 if self.mark_reset(id) {
919 sink(Event::Reset { stream: id, code, remote: false });
920 }
921 let r = self.send_rst(id, code, true);
922 self.update(id);
923 r
924 }
925
926 fn update(&mut self, id: u32) {
928 let Some(s) = self.streams.get_mut(&id) else { return };
929 if !s.closed() {
930 return;
931 }
932 if s.open {
933 s.open = false;
934 self.open_count -= 1;
935 }
936 if !s.handler {
937 let credit = s.unreleased;
938 let reset_by_us = s.reset && !s.peer_reset;
940 self.streams.remove(&id);
941 if !reset_by_us {
942 self.recent_closed[self.closed_pos] = id;
943 self.closed_pos = (self.closed_pos + 1) % self.recent_closed.len();
944 }
945 self.release_conn(credit);
946 }
947 }
948
949 fn header_cap(&self) -> usize {
952 self.cfg.max_header_list_size as usize
953 }
954
955 fn block_cap(&self) -> usize {
960 self.header_cap().saturating_mul(2)
961 }
962
963 fn on_headers(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
964 let id = h.stream;
965 if id == 0 {
966 return perr("HEADERS on stream 0");
967 }
968 let mut frag = Self::unpad(&h, p)?;
969 let mut self_dep = false;
970 if h.has(flag::PRIORITY) {
971 if frag.len() < 5 {
972 return Err((ErrorCode::FRAME_SIZE_ERROR, "HEADERS too short for its priority fields"));
973 }
974 self_dep = be32(frag) & 0x7fff_ffff == id;
975 frag = &frag[5..];
976 }
977 let end = h.has(flag::END_STREAM);
978 if h.has(flag::END_HEADERS) {
979 return self.on_block(id, end, self_dep, frag, sink);
980 }
981 if frag.is_empty() && self.hit(Budget::Empty) {
982 return calm("too many empty frames");
983 }
984 if frag.len() > self.block_cap() {
985 return calm("header block too large");
986 }
987 self.hb = Some(Block { stream: id, end_stream: end, self_dep, frames: 1 });
988 self.hb_buf.clear();
989 self.hb_buf.extend_from_slice(frag);
990 Ok(())
991 }
992
993 fn on_continuation(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
994 let Some(mut b) = self.hb.take() else {
995 return perr("CONTINUATION without HEADERS");
996 };
997 b.frames += 1;
998 if b.frames > self.cfg.max_continuation_frames + 1 {
999 return calm("too many CONTINUATION frames");
1000 }
1001 if p.is_empty() && !h.has(flag::END_HEADERS) && self.hit(Budget::Empty) {
1002 return calm("too many empty frames");
1003 }
1004 if self.hb_buf.len() + p.len() > self.block_cap() {
1005 return calm("header block too large");
1006 }
1007 self.hb_buf.extend_from_slice(p);
1008 if !h.has(flag::END_HEADERS) {
1009 self.hb = Some(b);
1010 return Ok(());
1011 }
1012 let buf = std::mem::take(&mut self.hb_buf);
1013 let r = self.on_block(b.stream, b.end_stream, b.self_dep, &buf, sink);
1014 self.hb_buf = buf;
1015 r
1016 }
1017
1018 fn on_block(&mut self, id: u32, end: bool, self_dep: bool, block: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1020 if block.len() > self.block_cap() {
1021 return calm("header block too large");
1022 }
1023 let server = self.role == Role::Server;
1024 let existing = self.streams.get(&id).map(|s| (s.reset && !s.peer_reset, s.remote_end || s.peer_reset, s.final_recv));
1025 let kind = match existing {
1026 Some((_, _, final_recv)) if server || final_recv => HeadKind::Trailers,
1027 Some(_) => HeadKind::Response,
1028 None => HeadKind::Request,
1029 };
1030 self.rx.reset(kind);
1032 let rx = &mut self.rx;
1033 let too_large = match self.dec.decode(block, &mut |n: &[u8], v: &[u8]| rx.push(n, v)) {
1034 Ok(()) => false,
1035 Err(HpackError::HeaderListTooLarge) => true,
1036 Err(_) => return Err((ErrorCode::COMPRESSION_ERROR, "HPACK decoding failed")),
1037 };
1038 self.rx.finish();
1039 let peer_initiated = (id & 1 == 1) == server;
1040 if !peer_initiated && server {
1041 return perr("client stream ids must be odd");
1042 }
1043 if peer_initiated && !server {
1044 return perr("server-initiated streams are not allowed (push is disabled)");
1045 }
1046 match existing {
1047 Some((true, _, _)) => Ok(()),
1048 Some((_, true, _)) => self.stream_error(id, ErrorCode::STREAM_CLOSED, sink),
1049 Some(_) if self_dep || too_large || self.rx.malformed().is_some() => {
1050 self.stream_error(id, ErrorCode::PROTOCOL_ERROR, sink)
1051 }
1052 Some(_) if kind == HeadKind::Trailers => {
1053 let s = self.streams.get_mut(&id).expect("stream exists");
1054 let bad_length = s.content_length.is_some_and(|cl| !s.head && cl != s.received);
1055 if !end || bad_length {
1056 return self.stream_error(id, ErrorCode::PROTOCOL_ERROR, sink);
1057 }
1058 s.remote_end = true;
1059 sink(Event::Trailers { stream: id, trailers: &self.rx });
1060 self.update(id);
1061 Ok(())
1062 }
1063 Some(_) => {
1064 let status = self.rx.status().unwrap_or(0);
1066 let s = self.streams.get_mut(&id).expect("stream exists");
1067 if status < 200 {
1068 if end {
1069 return self.stream_error(id, ErrorCode::PROTOCOL_ERROR, sink);
1070 }
1071 sink(Event::Headers { stream: id, headers: &self.rx, end_stream: false });
1072 return Ok(());
1073 }
1074 s.final_recv = true;
1075 s.content_length = self.rx.content_length();
1076 if end && !s.head && s.content_length.is_some_and(|cl| cl != 0) {
1077 return self.stream_error(id, ErrorCode::PROTOCOL_ERROR, sink);
1078 }
1079 s.remote_end = end;
1080 sink(Event::Headers { stream: id, headers: &self.rx, end_stream: end });
1081 if end {
1082 self.update(id);
1083 }
1084 Ok(())
1085 }
1086 None if server => {
1087 if id <= self.last_peer_stream {
1088 if self.recently_closed(id) {
1089 return Err((ErrorCode::STREAM_CLOSED, "HEADERS on a closed stream"));
1090 }
1091 if self.refused_or_reset(id) {
1092 return Ok(());
1095 }
1096 return perr("stream id lower than a previous one");
1097 }
1098 self.mark_seen(id);
1099 self.new_request(id, end, self_dep, too_large, sink)
1100 }
1101 None => {
1102 if self.is_idle(id) {
1103 return perr("HEADERS on an idle stream");
1104 }
1105 Ok(())
1106 }
1107 }
1108 }
1109
1110 fn new_request(&mut self, id: u32, end: bool, self_dep: bool, too_large: bool, sink: &mut dyn FnMut(Event<'_>)) -> R {
1111 if self.goaway_sent.is_some_and(|last| id > last) {
1112 return Ok(()); }
1114 if self_dep {
1115 return self.send_rst(id, ErrorCode::PROTOCOL_ERROR, true);
1116 }
1117 if too_large {
1118 self.write_block(id, true, |enc, out| enc.field(b":status", b"431", out));
1120 if !end {
1121 return self.send_rst(id, ErrorCode::NO_ERROR, true);
1122 }
1123 if self.hit(Budget::RstSent) {
1124 return calm("too many refused requests");
1125 }
1126 return Ok(());
1127 }
1128 let max = self.cfg.max_concurrent_streams;
1129 if self.open_count >= max || self.handlers >= max {
1130 return self.send_rst(id, ErrorCode::REFUSED_STREAM, true);
1131 }
1132 if self.rx.malformed().is_some() || (end && self.rx.content_length().is_some_and(|cl| cl != 0)) {
1133 return self.send_rst(id, ErrorCode::PROTOCOL_ERROR, true);
1134 }
1135 let s = Stream {
1136 send_window: self.peer_initial_window as i64,
1137 recv_window: self.stream_effective as i64,
1138 remote_end: end,
1139 open: true,
1140 handler: true,
1141 content_length: self.rx.content_length(),
1142 head: self.rx.method() == Some(b"HEAD"),
1143 ..Stream::default()
1144 };
1145 self.streams.insert(id, s);
1146 self.open_count += 1;
1147 self.handlers += 1;
1148 sink(Event::Headers { stream: id, headers: &self.rx, end_stream: end });
1149 Ok(())
1150 }
1151
1152 fn on_priority(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1155 if h.stream == 0 {
1156 return perr("PRIORITY on stream 0");
1157 }
1158 if self.hit(Budget::Priority) {
1159 return calm("too many PRIORITY frames");
1160 }
1161 if p.len() != 5 {
1162 return self.stream_error(h.stream, ErrorCode::FRAME_SIZE_ERROR, sink);
1163 }
1164 if be32(p) & 0x7fff_ffff == h.stream {
1165 return self.stream_error(h.stream, ErrorCode::PROTOCOL_ERROR, sink);
1166 }
1167 Ok(()) }
1169
1170 fn on_rst(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1171 if h.stream == 0 {
1172 return perr("RST_STREAM on stream 0");
1173 }
1174 if p.len() != 4 {
1175 return Err((ErrorCode::FRAME_SIZE_ERROR, "RST_STREAM length"));
1176 }
1177 if self.is_idle(h.stream) {
1178 return perr("RST_STREAM on an idle stream");
1179 }
1180 if self.hit(Budget::RstReceived) {
1181 return calm("too many RST_STREAM frames");
1182 }
1183 if self.mark_reset(h.stream) {
1184 sink(Event::Reset { stream: h.stream, code: ErrorCode(be32(p)), remote: true });
1185 }
1186 if let Some(s) = self.streams.get_mut(&h.stream) {
1187 s.peer_reset = true;
1188 }
1189 self.update(h.stream);
1190 Ok(())
1191 }
1192
1193 fn apply_settings(&mut self, p: &[u8]) -> R {
1195 for c in p.chunks_exact(6) {
1196 let id = u16::from_be_bytes([c[0], c[1]]);
1197 let v = be32(&c[2..]);
1198 match id {
1199 setting::HEADER_TABLE_SIZE => self.enc.set_peer_max_table_size(v as usize),
1200 setting::ENABLE_PUSH => {
1201 if v > 1 || (v == 1 && self.role == Role::Client) {
1202 return perr("invalid SETTINGS_ENABLE_PUSH");
1203 }
1204 }
1205 setting::MAX_CONCURRENT_STREAMS => self.peer_max_concurrent = v,
1206 setting::INITIAL_WINDOW_SIZE => {
1207 if v > MAX_WINDOW {
1208 return Err((ErrorCode::FLOW_CONTROL_ERROR, "SETTINGS_INITIAL_WINDOW_SIZE too large"));
1209 }
1210 let delta = v as i64 - self.peer_initial_window as i64;
1211 self.peer_initial_window = v;
1212 let mut overflow = false;
1213 for s in self.streams.values_mut() {
1214 s.send_window += delta;
1215 overflow |= s.send_window > MAX_WINDOW as i64;
1216 }
1217 if overflow {
1218 return Err((ErrorCode::FLOW_CONTROL_ERROR, "stream window overflow"));
1219 }
1220 }
1221 setting::MAX_FRAME_SIZE => {
1222 if !(frame::MIN_FRAME_SIZE..=frame::MAX_FRAME_SIZE).contains(&v) {
1223 return perr("invalid SETTINGS_MAX_FRAME_SIZE");
1224 }
1225 self.peer_max_frame = v as usize;
1226 }
1227 setting::MAX_HEADER_LIST_SIZE => self.peer_max_header_list = v,
1228 setting::ENABLE_CONNECT_PROTOCOL if cfg!(feature = "connect-protocol") => {
1229 if v > 1 || (v == 0 && self.peer_connect_protocol) {
1231 return perr("invalid SETTINGS_ENABLE_CONNECT_PROTOCOL");
1232 }
1233 self.peer_connect_protocol = v == 1;
1234 }
1235 _ => {} }
1237 }
1238 Ok(())
1239 }
1240
1241 fn on_settings(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1242 if h.stream != 0 {
1243 return perr("SETTINGS on a stream");
1244 }
1245 if h.has(flag::ACK) {
1246 if !p.is_empty() {
1247 return Err((ErrorCode::FRAME_SIZE_ERROR, "SETTINGS ACK with a payload"));
1248 }
1249 if self.settings_unacked > 0 {
1250 self.settings_unacked -= 1;
1251 self.settings_deadline = if self.settings_unacked > 0 { Some(self.now + self.cfg.settings_timeout_ms) } else { None };
1252 if !self.first_settings_acked {
1253 self.first_settings_acked = true;
1254 self.dec.set_max_allowed(self.cfg.header_table_size as usize);
1255 if self.stream_effective > self.stream_target {
1256 let delta = self.stream_effective as i64 - self.stream_target as i64;
1257 self.stream_effective = self.stream_target;
1258 for s in self.streams.values_mut() {
1259 s.recv_window -= delta;
1260 }
1261 }
1262 }
1263 }
1264 return Ok(());
1265 }
1266 if p.len() % 6 != 0 {
1267 return Err((ErrorCode::FRAME_SIZE_ERROR, "SETTINGS length"));
1268 }
1269 if self.hit(Budget::Settings) {
1270 return calm("too many SETTINGS frames");
1271 }
1272 self.apply_settings(p)?;
1273 frame::write_settings_ack(&mut self.out);
1274 sink(Event::Settings);
1275 Ok(())
1276 }
1277
1278 fn on_ping(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1279 if h.stream != 0 {
1280 return perr("PING on a stream");
1281 }
1282 if p.len() != 8 {
1283 return Err((ErrorCode::FRAME_SIZE_ERROR, "PING length"));
1284 }
1285 let mut data = [0u8; 8];
1286 data.copy_from_slice(p);
1287 if h.has(flag::ACK) {
1288 if data == BDP_PING && self.bdp_sent {
1289 self.bdp_ack();
1290 } else if data == SHUTDOWN_PING && self.graceful_deadline.is_some() {
1291 self.final_goaway();
1292 } else if cfg!(feature = "keepalive") && data == KEEPALIVE_PING && self.cfg.keepalive_interval_ms.is_some() {
1293 self.keepalive_deadline = None;
1294 } else {
1295 if self.hit(Budget::Ping) {
1296 return calm("too many PING frames");
1297 }
1298 sink(Event::Pong { data });
1299 }
1300 return Ok(());
1301 }
1302 if self.hit(Budget::Ping) {
1303 return calm("too many PING frames");
1304 }
1305 frame::write_ping(&mut self.out, data, true);
1306 Ok(())
1307 }
1308
1309 fn on_goaway(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1310 if h.stream != 0 {
1311 return perr("GOAWAY on a stream");
1312 }
1313 if p.len() < 8 {
1314 return Err((ErrorCode::FRAME_SIZE_ERROR, "GOAWAY length"));
1315 }
1316 let last = be32(p) & 0x7fff_ffff;
1317 let code = ErrorCode(be32(&p[4..]));
1318 self.goaway_recv = Some(self.goaway_recv.map_or(last, |l| l.min(last)));
1319 sink(Event::GoAway { last_stream: last, code, debug: &p[8..] });
1320 let client = self.role == Role::Client;
1322 let refused: Vec<u32> = self
1323 .streams
1324 .iter()
1325 .filter(|(&id, s)| (id & 1 == 1) == client && id > last && !s.reset)
1326 .map(|(&id, _)| id)
1327 .collect();
1328 for id in refused {
1329 if self.mark_reset(id) {
1330 sink(Event::Reset { stream: id, code: ErrorCode::REFUSED_STREAM, remote: true });
1331 }
1332 self.update(id);
1333 }
1334 if self.role == Role::Server {
1335 self.shutdown(self.now);
1337 }
1338 Ok(())
1339 }
1340
1341 fn on_window_update(&mut self, h: FrameHeader, p: &[u8], sink: &mut dyn FnMut(Event<'_>)) -> R {
1342 if p.len() != 4 {
1343 return Err((ErrorCode::FRAME_SIZE_ERROR, "WINDOW_UPDATE length"));
1344 }
1345 let inc = be32(p) & 0x7fff_ffff;
1346 if inc < 1024 && self.hit(Budget::SmallWindowUpdate) {
1347 return calm("too many small WINDOW_UPDATE frames");
1348 }
1349 let id = h.stream;
1350 if id == 0 {
1351 if inc == 0 {
1352 return perr("WINDOW_UPDATE with a zero increment");
1353 }
1354 self.send_window += inc as i64;
1355 if self.send_window > MAX_WINDOW as i64 {
1356 return Err((ErrorCode::FLOW_CONTROL_ERROR, "connection window overflow"));
1357 }
1358 return Ok(());
1359 }
1360 if self.is_idle(id) {
1361 return perr("WINDOW_UPDATE on an idle stream");
1362 }
1363 let code = match self.streams.get_mut(&id) {
1364 None => return Ok(()),
1365 Some(s) if s.reset => return Ok(()),
1366 Some(_) if inc == 0 => ErrorCode::PROTOCOL_ERROR,
1367 Some(s) => {
1368 s.send_window += inc as i64;
1369 if s.send_window <= MAX_WINDOW as i64 {
1370 return Ok(());
1371 }
1372 ErrorCode::FLOW_CONTROL_ERROR
1373 }
1374 };
1375 self.stream_error(id, code, sink)
1376 }
1377
1378 fn write_block(&mut self, id: u32, end: bool, fields: impl FnOnce(&mut Encoder, &mut Vec<u8>)) {
1383 let at = self.out.len();
1384 frame::write_header(&mut self.out, 0, kind::HEADERS, 0, id);
1385 self.enc.begin_block(&mut self.out);
1386 fields(&mut self.enc, &mut self.out);
1387 let len = self.out.len() - at - HEADER_LEN;
1388 let fl = if end { flag::END_STREAM } else { 0 };
1389 if len <= self.peer_max_frame {
1390 frame::patch_header(&mut self.out, at, len, fl | flag::END_HEADERS);
1391 } else {
1392 self.scratch.clear();
1393 self.scratch.extend_from_slice(&self.out[at + HEADER_LEN..]);
1394 self.out.truncate(at);
1395 frame::write_headers(&mut self.out, id, &self.scratch, end, self.peer_max_frame);
1396 }
1397 }
1398
1399 fn check_list_size(&self, pseudo: &[(&[u8], &[u8])], fields: &[(&[u8], &[u8])]) -> Result<(), Error> {
1403 let size: u64 = pseudo.iter().chain(fields).map(|(n, v)| n.len() as u64 + v.len() as u64 + 32).sum();
1404 if size > u64::from(self.peer_max_header_list) {
1405 return Err(Error::HeaderListTooLarge);
1406 }
1407 Ok(())
1408 }
1409
1410 pub fn peer_max_header_list_size(&self) -> u32 {
1412 self.peer_max_header_list
1413 }
1414
1415 pub fn peer_connect_protocol(&self) -> bool {
1418 self.peer_connect_protocol
1419 }
1420
1421 pub fn send_extended_connect(&mut self, protocol: &[u8], scheme: &[u8], authority: &[u8], path: &[u8], fields: &[(&[u8], &[u8])]) -> Result<u32, Error> {
1426 if self.role != Role::Client {
1427 return Err(Error::WrongRole);
1428 }
1429 if self.phase == Phase::Closed {
1430 return Err(Error::ConnectionClosed);
1431 }
1432 if self.goaway_recv.is_some() || self.goaway_sent.is_some() {
1433 return Err(Error::GoingAway);
1434 }
1435 if !self.peer_connect_protocol {
1436 return Err(Error::ConnectProtocolDisabled);
1437 }
1438 if self.next_stream_id > MAX_WINDOW {
1439 return Err(Error::StreamIdsExhausted);
1440 }
1441 if self.open_count >= self.peer_max_concurrent {
1442 return Err(Error::StreamLimit);
1443 }
1444 let ok = |v: &[u8]| !v.is_empty() && valid_value(v);
1445 if !ok(protocol) || !ok(scheme) || !ok(authority) || !ok(path) {
1446 return Err(Error::InvalidHeader);
1447 }
1448 Self::check_fields(fields)?;
1449 let pseudo: [(&[u8], &[u8]); 5] = [(b":method", b"CONNECT"), (b":protocol", protocol), (b":scheme", scheme), (b":authority", authority), (b":path", path)];
1450 self.check_list_size(&pseudo, fields)?;
1451 let id = self.next_stream_id;
1452 self.next_stream_id += 2;
1453 let s = Stream { send_window: self.peer_initial_window as i64, recv_window: self.stream_effective as i64, open: true, final_sent: true, ..Stream::default() };
1454 self.streams.insert(id, s);
1455 self.open_count += 1;
1456 self.write_block(id, false, |enc, out| {
1457 for (n, v) in pseudo {
1458 enc.field(n, v, out);
1459 }
1460 for (n, v) in fields {
1461 enc.field(n, v, out);
1462 }
1463 });
1464 Ok(id)
1465 }
1466
1467 fn check_fields(fields: &[(&[u8], &[u8])]) -> Result<(), Error> {
1468 for (n, v) in fields {
1469 if !valid_name(n) || connection_specific(n) || (*n == b"te" && *v != b"trailers") || !valid_value(v) {
1470 return Err(Error::InvalidHeader);
1471 }
1472 }
1473 Ok(())
1474 }
1475
1476 fn sendable(&self, stream: u32) -> Result<(), Error> {
1477 if self.phase == Phase::Closed {
1478 return Err(Error::ConnectionClosed);
1479 }
1480 match self.streams.get(&stream) {
1481 None => Err(Error::UnknownStream),
1482 Some(s) if s.reset => Err(Error::StreamReset),
1483 Some(s) if s.local_end => Err(Error::StreamClosed),
1484 Some(_) => Ok(()),
1485 }
1486 }
1487
1488 pub fn send_response(&mut self, stream: u32, status: u16, fields: &[(&[u8], &[u8])], end_stream: bool) -> Result<(), Error> {
1491 if self.role != Role::Server {
1492 return Err(Error::WrongRole);
1493 }
1494 if !(100..1000).contains(&status) || status == 101 || (status < 200 && end_stream) {
1495 return Err(Error::InvalidHeader);
1496 }
1497 Self::check_fields(fields)?;
1498 self.sendable(stream)?;
1499 let digits = [b'0' + (status / 100) as u8, b'0' + (status / 10 % 10) as u8, b'0' + (status % 10) as u8];
1500 self.check_list_size(&[(b":status", &digits)], fields)?;
1501 let s = self.streams.get_mut(&stream).expect("checked");
1502 if s.final_sent {
1503 return Err(Error::HeadersAlreadySent);
1504 }
1505 if status >= 200 {
1506 s.final_sent = true;
1507 }
1508 if end_stream {
1509 s.local_end = true;
1510 }
1511 self.write_block(stream, end_stream, |enc, out| {
1512 enc.field(b":status", &digits, out);
1513 for (n, v) in fields {
1514 enc.field(n, v, out);
1515 }
1516 });
1517 if end_stream {
1518 self.update(stream);
1519 }
1520 Ok(())
1521 }
1522
1523 #[allow(clippy::too_many_arguments)]
1526 pub fn send_request(
1527 &mut self,
1528 method: &[u8],
1529 scheme: &[u8],
1530 authority: &[u8],
1531 path: &[u8],
1532 fields: &[(&[u8], &[u8])],
1533 end_stream: bool,
1534 ) -> Result<u32, Error> {
1535 if self.role != Role::Client {
1536 return Err(Error::WrongRole);
1537 }
1538 if self.phase == Phase::Closed {
1539 return Err(Error::ConnectionClosed);
1540 }
1541 if self.goaway_recv.is_some() || self.goaway_sent.is_some() {
1542 return Err(Error::GoingAway);
1543 }
1544 if self.next_stream_id > MAX_WINDOW {
1545 return Err(Error::StreamIdsExhausted);
1546 }
1547 if self.open_count >= self.peer_max_concurrent {
1548 return Err(Error::StreamLimit);
1549 }
1550 let connect = method == b"CONNECT";
1551 if method.is_empty()
1552 || !method.iter().all(|&b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_')
1553 || !valid_value(scheme)
1554 || !valid_value(authority)
1555 || (!connect && (path.is_empty() || !valid_value(path)))
1556 {
1557 return Err(Error::InvalidHeader);
1558 }
1559 Self::check_fields(fields)?;
1560 let pseudo: [(&[u8], &[u8]); 4] = [(b":method", method), (b":scheme", scheme), (b":authority", authority), (b":path", path)];
1562 let sent: Vec<(&[u8], &[u8])> = pseudo.into_iter().filter(|(n, v)| !(connect && (*n == b":scheme" || *n == b":path")) && !(*n == b":authority" && v.is_empty())).collect();
1563 self.check_list_size(&sent, fields)?;
1564 let id = self.next_stream_id;
1565 self.next_stream_id += 2;
1566 let s = Stream {
1567 send_window: self.peer_initial_window as i64,
1568 recv_window: self.stream_effective as i64,
1569 local_end: end_stream,
1570 open: true,
1571 final_sent: true,
1572 head: method == b"HEAD",
1573 ..Stream::default()
1574 };
1575 self.streams.insert(id, s);
1576 self.open_count += 1;
1577 self.write_block(id, end_stream, |enc, out| {
1578 enc.field(b":method", method, out);
1579 if !connect {
1580 enc.field(b":scheme", scheme, out);
1581 }
1582 if !authority.is_empty() {
1583 enc.field(b":authority", authority, out);
1584 }
1585 if !connect {
1586 enc.field(b":path", path, out);
1587 }
1588 for (n, v) in fields {
1589 enc.field(n, v, out);
1590 }
1591 });
1592 Ok(id)
1593 }
1594
1595 pub fn send_trailers(&mut self, stream: u32, fields: &[(&[u8], &[u8])]) -> Result<(), Error> {
1597 Self::check_fields(fields)?;
1598 self.sendable(stream)?;
1599 self.check_list_size(&[], fields)?;
1600 let s = self.streams.get_mut(&stream).expect("checked");
1601 if !s.final_sent {
1602 return Err(Error::HeadersNotSent);
1603 }
1604 s.local_end = true;
1605 self.write_block(stream, true, |enc, out| {
1606 for (n, v) in fields {
1607 enc.field(n, v, out);
1608 }
1609 });
1610 self.update(stream);
1611 Ok(())
1612 }
1613
1614 pub fn send_data(&mut self, stream: u32, data: &[u8], end_stream: bool) -> Result<usize, Error> {
1619 self.sendable(stream)?;
1620 let room = self.cfg.max_send_buffer.saturating_sub(self.pending()) as i64;
1621 let max_frame = self.peer_max_frame;
1622 let s = self.streams.get_mut(&stream).expect("checked");
1623 if !s.final_sent {
1624 return Err(Error::HeadersNotSent);
1625 }
1626 let cap = s.send_window.min(self.send_window).min(room).max(0) as usize;
1627 let n = data.len().min(cap);
1628 let fin = end_stream && n == data.len();
1629 if n < data.len() && !s.blocked {
1630 s.blocked = true;
1631 self.blocked.push(stream);
1632 }
1633 if n == 0 && !fin {
1634 return Ok(0);
1635 }
1636 s.send_window -= n as i64;
1637 self.send_window -= n as i64;
1638 if n == 0 {
1639 frame::write_data(&mut self.out, stream, &[], true);
1640 } else {
1641 let mut chunks = data[..n].chunks(max_frame).peekable();
1642 while let Some(c) = chunks.next() {
1643 frame::write_data(&mut self.out, stream, c, fin && chunks.peek().is_none());
1644 }
1645 }
1646 if fin {
1647 s.local_end = true;
1648 self.update(stream);
1649 }
1650 Ok(n)
1651 }
1652
1653 pub fn poll_writable(&mut self) -> Option<u32> {
1657 if self.send_window <= 0 || self.pending() >= self.cfg.max_send_buffer || self.phase == Phase::Closed {
1658 return None;
1659 }
1660 let mut i = 0;
1661 while i < self.blocked.len() {
1662 let id = self.blocked[i];
1663 match self.streams.get_mut(&id) {
1664 Some(s) if s.blocked && !s.reset && !s.local_end => {
1665 if s.send_window > 0 {
1666 s.blocked = false;
1667 self.blocked.swap_remove(i);
1668 return Some(id);
1669 }
1670 i += 1;
1671 }
1672 Some(s) => {
1673 s.blocked = false;
1674 self.blocked.swap_remove(i);
1675 }
1676 None => {
1677 self.blocked.swap_remove(i);
1678 }
1679 }
1680 }
1681 None
1682 }
1683
1684 pub fn reset(&mut self, stream: u32, code: ErrorCode) {
1686 if self.phase == Phase::Closed || !self.streams.get(&stream).is_some_and(|s| !s.closed()) {
1687 return;
1688 }
1689 self.mark_reset(stream);
1690 let _ = self.send_rst(stream, code, false);
1691 self.update(stream);
1692 }
1693
1694 pub fn stream_finished(&mut self, stream: u32) {
1698 let Some(s) = self.streams.get_mut(&stream) else { return };
1699 if s.handler {
1700 s.handler = false;
1701 self.handlers -= 1;
1702 }
1703 if !s.closed() && self.phase != Phase::Closed {
1704 let code = if s.local_end { ErrorCode::NO_ERROR } else { ErrorCode::CANCEL };
1705 self.mark_reset(stream);
1706 let _ = self.send_rst(stream, code, false);
1707 }
1708 if let Some(s) = self.streams.get_mut(&stream) {
1709 if !s.closed() {
1710 s.reset = true;
1712 }
1713 }
1714 self.update(stream);
1715 }
1716
1717 pub fn ping(&mut self, data: [u8; 8]) {
1719 if self.phase != Phase::Closed {
1720 frame::write_ping(&mut self.out, data, false);
1721 }
1722 }
1723
1724 pub fn shutdown(&mut self, now: u64) {
1729 self.now = now;
1730 if self.phase == Phase::Closed || self.goaway_sent.is_some() || self.graceful_deadline.is_some() {
1731 return;
1732 }
1733 if self.role == Role::Server && self.phase == Phase::Open {
1734 frame::write_goaway(&mut self.out, MAX_WINDOW, ErrorCode::NO_ERROR, b"");
1735 frame::write_ping(&mut self.out, SHUTDOWN_PING, false);
1736 self.graceful_deadline = Some(now + self.cfg.graceful_timeout_ms);
1737 } else {
1738 self.final_goaway();
1739 }
1740 }
1741
1742 fn final_goaway(&mut self) {
1743 self.graceful_deadline = None;
1744 if self.goaway_sent.is_none() && self.phase != Phase::Closed {
1745 frame::write_goaway(&mut self.out, self.last_peer_stream, ErrorCode::NO_ERROR, b"");
1746 self.goaway_sent = Some(self.last_peer_stream);
1747 }
1748 }
1749
1750 pub fn close(&mut self, code: ErrorCode, debug: &[u8]) {
1752 if self.phase == Phase::Closed {
1753 return;
1754 }
1755 frame::write_goaway(&mut self.out, self.last_peer_stream, code, debug);
1756 self.phase = Phase::Closed;
1757 self.close_code = Some(code);
1758 self.settings_deadline = None;
1759 self.graceful_deadline = None;
1760 }
1761}