1use std::collections::HashMap;
17
18use super::frame::{
19 DEFAULT_MAX_FRAME_SIZE, FrameFlags, FrameHeader, FrameKind, Setting, parse_header,
20 parse_rst_stream, parse_settings, parse_window_update, validate_payload, write_header,
21 write_setting,
22};
23use super::hpack::{HpackDecoder, HpackEncoder, HpackError};
24
25pub const CLIENT_PREFACE: &[u8; 24] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
27
28pub mod error_code {
30 pub const NO_ERROR: u32 = 0x0;
32 pub const PROTOCOL_ERROR: u32 = 0x1;
34 pub const INTERNAL_ERROR: u32 = 0x2;
36 pub const FLOW_CONTROL_ERROR: u32 = 0x3;
38 pub const STREAM_CLOSED: u32 = 0x5;
40 pub const FRAME_SIZE_ERROR: u32 = 0x6;
42 pub const REFUSED_STREAM: u32 = 0x7;
44 pub const CANCEL: u32 = 0x8;
46 pub const COMPRESSION_ERROR: u32 = 0x9;
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum Role {
53 Server,
55 Client,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum StreamState {
65 Open,
68 HalfClosedLocal,
70 HalfClosedRemote,
72 Closed,
74}
75
76#[derive(Debug)]
78pub enum Event {
79 Headers {
81 stream_id: u32,
83 end_stream: bool,
85 headers: Vec<super::hpack::Header>,
87 },
88 Trailers {
92 stream_id: u32,
94 headers: Vec<super::hpack::Header>,
96 },
97 Data {
100 stream_id: u32,
102 end_stream: bool,
104 data: Vec<u8>,
106 },
107 Reset {
109 stream_id: u32,
111 error_code: u32,
113 },
114 GoAway {
117 last_stream_id: u32,
119 error_code: u32,
121 },
122 SettingsAck,
124 WindowUpdate {
129 stream_id: u32,
131 },
132}
133
134#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub struct ConnectionError {
138 pub code: u32,
140}
141
142#[derive(Debug, Clone)]
144pub struct ConnectionConfig {
145 pub max_concurrent_streams: u32,
148 pub initial_window_size: u32,
150 pub max_frame_size: u32,
152 pub header_table_size: u32,
154 pub max_header_list_size: u32,
156}
157
158impl Default for ConnectionConfig {
159 fn default() -> Self {
160 Self {
161 max_concurrent_streams: 256,
162 initial_window_size: 512 * 1024,
163 max_frame_size: DEFAULT_MAX_FRAME_SIZE,
164 header_table_size: 4096,
165 max_header_list_size: 128 * 1024,
166 }
167 }
168}
169
170#[derive(Debug, Clone, Copy)]
171struct Stream {
172 state: StreamState,
173 recv_window: i64,
174 send_window: i64,
175 sent_end: bool,
177 peer_data: bool,
180 content_length: Option<u64>,
183 content_received: u64,
185 head_invalid: bool,
190 head_done: bool,
193}
194
195#[derive(Debug, Default)]
197struct HeaderBlockAssembler {
198 fragments: Vec<u8>,
199 stream_id: u32,
200 end_stream: bool,
201 active: bool,
202}
203
204pub struct Connection {
206 role: Role,
207 cfg: ConnectionConfig,
208 retired_windows: std::collections::HashMap<u32, i64>,
210 encoder: HpackEncoder,
211 decoder: HpackDecoder,
212
213 out: Vec<u8>,
215
216 preface_pos: usize,
218 preface_done: bool,
219
220 settings_acked: bool,
222
223 peer_max_frame: u32,
225 peer_initial_window: i64,
227
228 conn_recv_window: i64,
229 conn_send_window: i64,
230
231 next_stream_id: u32,
232 last_peer_stream_id: u32,
233
234 streams: HashMap<u32, Stream>,
235
236 header_block: HeaderBlockAssembler,
237
238 connection_error: Option<ConnectionError>,
241 goaway_sent: bool,
242 peer_goaway: Option<(u32, u32)>,
244}
245
246impl Connection {
247 #[must_use]
251 pub fn new(role: Role, cfg: ConnectionConfig) -> Self {
252 let mut conn = Self {
253 role,
254 cfg: cfg.clone(),
255 retired_windows: std::collections::HashMap::new(),
256 encoder: HpackEncoder::new(),
257 decoder: HpackDecoder::new(cfg.header_table_size),
258 out: Vec::new(),
259 preface_pos: 0,
260 preface_done: role == Role::Client,
261 settings_acked: false,
262 peer_max_frame: DEFAULT_MAX_FRAME_SIZE,
263 peer_initial_window: 65_535,
264 conn_recv_window: 65_535,
267 conn_send_window: 65_535,
268 next_stream_id: match role {
269 Role::Server => 2,
270 Role::Client => 1,
271 },
272 last_peer_stream_id: 0,
273 streams: HashMap::new(),
274 header_block: HeaderBlockAssembler::default(),
275 connection_error: None,
276 goaway_sent: false,
277 peer_goaway: None,
278 };
279
280 match role {
281 Role::Client => {
282 conn.out.extend_from_slice(CLIENT_PREFACE);
283 }
284 Role::Server => {}
285 }
286 conn.write_initial_settings();
287 conn.settings_acked = true;
289 conn
290 }
291
292 fn write_initial_settings(&mut self) {
293 let hdr_pos = self.out.len();
294 write_header(&mut self.out, 0, FrameKind::Settings, FrameFlags::EMPTY, 0);
295 let mut payload = Vec::new();
296 write_setting(&mut payload, 0x3, self.cfg.max_concurrent_streams);
297 write_setting(&mut payload, 0x4, self.cfg.initial_window_size);
298 write_setting(&mut payload, 0x5, self.cfg.max_frame_size);
299 write_setting(&mut payload, 0x6, self.cfg.max_header_list_size);
300 write_setting(&mut payload, 0x1, self.cfg.header_table_size);
301 let len = payload.len() as u32;
303 self.out[hdr_pos] = (len >> 16) as u8;
304 self.out[hdr_pos + 1] = (len >> 8) as u8;
305 self.out[hdr_pos + 2] = len as u8;
306 self.out.extend_from_slice(&payload);
307 }
308
309 #[must_use]
311 pub fn take_pending_writes(&mut self) -> Vec<u8> {
312 std::mem::take(&mut self.out)
313 }
314
315 #[must_use]
318 pub fn connection_error(&self) -> Option<ConnectionError> {
319 self.connection_error
320 }
321
322 #[must_use]
325 pub fn peer_max_frame_size(&self) -> usize {
326 self.peer_max_frame as usize
327 }
328
329 #[must_use]
332 pub fn send_budget(&self, stream_id: u32) -> usize {
333 let stream = self
334 .streams
335 .get(&stream_id)
336 .map_or(i64::MAX, |st| st.send_window);
337 self.conn_send_window
338 .min(stream)
339 .max(0)
340 .try_into()
341 .unwrap_or(0)
342 }
343
344 #[must_use]
346 pub fn stream_is_open(&self, stream_id: u32) -> bool {
347 self.streams.contains_key(&stream_id)
348 }
349
350 #[must_use]
352 pub fn conn_send_window_probe(&self) -> i64 {
353 self.conn_send_window
354 }
355
356 #[must_use]
358 pub fn stream_send_window_probe(&self, stream_id: u32) -> i64 {
359 self.streams.get(&stream_id).map_or(0, |st| st.send_window)
360 }
361
362 #[must_use]
364 pub fn debug_send_windows(&self, stream_id: u32) -> (i64, i64) {
365 (
366 self.conn_send_window,
367 self.streams.get(&stream_id).map_or(0, |st| st.send_window),
368 )
369 }
370
371 pub fn grant_send_for_test(&mut self, stream_id: u32, n: u32) {
374 self.conn_send_window += i64::from(n);
375 if let Some(st) = self.streams.get_mut(&stream_id) {
376 st.send_window += i64::from(n);
377 } else {
378 crate::dbg_trace!("GRANTDBG grant({n}) dropped: stream {stream_id} missing");
379 }
380 }
381
382 pub fn consume_send_budget(&mut self, stream_id: u32, n: usize) -> usize {
389 let Some(st) = self.streams.get_mut(&stream_id) else {
390 return 0;
391 };
392 let reserved = (n as i64)
393 .min(self.conn_send_window.max(0))
394 .min(st.send_window.max(0));
395 self.conn_send_window -= reserved;
396 st.send_window -= reserved;
397 reserved as usize
398 }
399
400 #[must_use]
402 pub fn peer_goaway(&self) -> Option<(u32, u32)> {
403 self.peer_goaway
404 }
405
406 fn conn_error(&mut self, code: u32) -> ConnectionError {
407 eprintln!("CRDBG conn_error code={code:#x}");
408 let err = ConnectionError { code };
409 if !self.goaway_sent {
410 self.goaway_sent = true;
411 let mut payload = Vec::new();
412 payload.extend_from_slice(&self.last_peer_stream_id.to_be_bytes());
413 payload.extend_from_slice(&code.to_be_bytes());
414 write_header(
415 &mut self.out,
416 payload.len() as u32,
417 FrameKind::GoAway,
418 FrameFlags::EMPTY,
419 0,
420 );
421 self.out.extend_from_slice(&payload);
422 }
423 self.connection_error = Some(err);
424 err
425 }
426
427 pub fn handle_read(&mut self, data: &[u8], events: &mut Vec<Event>) -> usize {
433 if self.connection_error.is_some() {
434 return 0;
435 }
436 let total = data.len();
437 let mut off = 0usize;
438
439 if !self.preface_done {
441 let need = CLIENT_PREFACE.len() - self.preface_pos;
442 let take = need.min(data.len());
443 if data[..take] != CLIENT_PREFACE[self.preface_pos..self.preface_pos + take] {
444 let _ = self.conn_error(error_code::PROTOCOL_ERROR);
447 return 0;
448 }
449 self.preface_pos += take;
450 off += take;
451 if self.preface_pos < CLIENT_PREFACE.len() {
452 return off; }
454 self.preface_done = true;
455 }
456
457 while off < total {
458 if self.header_block.active {
459 if total - off < 9 {
461 break; }
463 let hdr_data = &data[off..];
464 let Ok(hdr) = parse_header(hdr_data) else {
465 break;
466 };
467 if hdr.kind != FrameKind::Continuation
468 || hdr.stream_id != self.header_block.stream_id
469 {
470 let _ = self.conn_error(error_code::PROTOCOL_ERROR);
471 return off;
472 }
473 if total - off < 9 + hdr.length as usize {
474 break; }
476 let frag = &data[off + 9..off + 9 + hdr.length as usize];
477 self.header_block.fragments.extend_from_slice(frag);
478 off += 9 + hdr.length as usize;
479 if hdr.flags.end_headers() {
480 if let Err(code) = self.finish_headers(events) {
481 let _ = self.conn_error(code);
482 return off;
483 }
484 }
485 continue;
486 }
487
488 if total - off < 9 {
489 break; }
491 let hdr_data = &data[off..];
492 let Ok(hdr) = parse_header(hdr_data) else {
493 break;
494 };
495 if total - off < 9 + hdr.length as usize {
496 break; }
498 let payload = &data[off + 9..off + 9 + hdr.length as usize];
499 off += 9 + hdr.length as usize;
500
501 match hdr.kind {
506 FrameKind::Data
507 | FrameKind::Headers
508 | FrameKind::Continuation
509 | FrameKind::RstStream
510 | FrameKind::PushPromise => {
511 if hdr.stream_id == 0 || hdr.stream_id & 1 == 0 {
512 let _ = self.conn_error(error_code::PROTOCOL_ERROR);
513 return off;
514 }
515 }
516 FrameKind::Settings | FrameKind::Ping | FrameKind::GoAway => {
517 if hdr.stream_id != 0 {
518 let _ = self.conn_error(error_code::PROTOCOL_ERROR);
519 return off;
520 }
521 }
522 FrameKind::WindowUpdate => {}
523 FrameKind::Priority => {}
524 FrameKind::Unknown(_) => {}
525 }
526
527 match self.handle_frame(&hdr, payload, events) {
528 Ok(()) => {}
529 Err(code) => {
530 let _ = self.conn_error(code);
531 return off;
532 }
533 }
534 if self.connection_error.is_some() {
535 return off;
536 }
537 }
538 off
539 }
540
541 fn handle_frame(
542 &mut self,
543 hdr: &FrameHeader,
544 payload: &[u8],
545 events: &mut Vec<Event>,
546 ) -> Result<(), u32> {
547 match hdr.kind {
548 FrameKind::Settings => self.handle_settings(hdr, payload, events),
549 FrameKind::Ping => self.handle_ping(hdr, payload),
550 FrameKind::WindowUpdate => {
551 eprintln!("CRDBG wu stream={} len={}", hdr.stream_id, payload.len());
552 self.handle_window_update(hdr, payload, events)
553 }
554 FrameKind::GoAway => {
555 if payload.len() < 8 {
556 return Err(error_code::FRAME_SIZE_ERROR);
557 }
558 let last = u32::from_be_bytes([payload[0], payload[1], payload[2], payload[3]]);
559 let code = u32::from_be_bytes([payload[4], payload[5], payload[6], payload[7]]);
560 self.peer_goaway = Some((last, code));
561 events.push(Event::GoAway {
562 last_stream_id: last,
563 error_code: code,
564 });
565 Ok(())
566 }
567 FrameKind::RstStream => {
568 let code = parse_rst_stream(payload).map_err(|_| error_code::FRAME_SIZE_ERROR)?;
569 let id = hdr.stream_id;
570 if self.streams.contains_key(&id) {
571 if let Some(st) = self.streams.get_mut(&id) {
572 st.state = StreamState::Closed;
573 }
574 self.streams.remove(&id);
575 } else if self.is_peer_idle(id) {
576 return Err(error_code::PROTOCOL_ERROR);
579 }
580 events.push(Event::Reset {
581 stream_id: id,
582 error_code: code,
583 });
584 Ok(())
585 }
586 FrameKind::Headers => {
587 eprintln!(
588 "CRDBG headers stream={} len={}",
589 hdr.stream_id,
590 payload.len()
591 );
592 self.handle_headers(hdr, payload, events)?;
593 Ok(())
594 }
595 FrameKind::Continuation => {
596 Err(error_code::PROTOCOL_ERROR)
599 }
600 FrameKind::Data => {
601 eprintln!("CRDBG data stream={} len={}", hdr.stream_id, payload.len());
602 self.handle_data(hdr, payload, events)
603 }
604 FrameKind::Priority => {
605 if hdr.stream_id == 0 {
610 return Err(error_code::PROTOCOL_ERROR);
611 }
612 if payload.len() != 5 {
613 return Err(error_code::FRAME_SIZE_ERROR);
614 }
615 let dep = u32::from_be_bytes([payload[0], payload[1], payload[2], payload[3]])
616 & 0x7fff_ffff;
617 if dep == hdr.stream_id {
618 return Err(error_code::PROTOCOL_ERROR);
619 }
620 Ok(())
621 }
622 FrameKind::PushPromise => {
623 Err(error_code::REFUSED_STREAM)
626 }
627 FrameKind::Unknown(_) => Ok(()),
628 }
629 }
630
631 fn handle_settings(
632 &mut self,
633 hdr: &FrameHeader,
634 payload: &[u8],
635 events: &mut Vec<Event>,
636 ) -> Result<(), u32> {
637 if hdr.flags.ack() {
638 if !self.settings_acked {
639 return Err(error_code::PROTOCOL_ERROR);
640 }
641 self.settings_acked = false;
642 return Ok(());
643 }
644 let settings = parse_settings(payload).map_err(|_| error_code::FRAME_SIZE_ERROR)?;
645 for setting in &settings {
646 match *setting {
647 Setting::MaxFrameSize(v) => {
648 if !(DEFAULT_MAX_FRAME_SIZE..=16_777_215).contains(&v) {
649 return Err(error_code::PROTOCOL_ERROR);
650 }
651 self.peer_max_frame = v;
652 }
653 Setting::InitialWindowSize(v) => {
654 if v > (1 << 30) - 1 {
655 return Err(error_code::FLOW_CONTROL_ERROR);
656 }
657 let delta = i64::from(v) - self.peer_initial_window;
658 self.peer_initial_window = i64::from(v);
659 if delta > 0 {
660 for st in self.streams.values_mut() {
661 st.send_window += delta;
662 }
663 events.push(Event::WindowUpdate { stream_id: 0 });
666 } else {
667 for st in self.streams.values_mut() {
668 st.send_window += delta;
669 }
670 }
671 }
672 Setting::EnablePush(v) if v > 1 => {
675 return Err(error_code::PROTOCOL_ERROR);
676 }
677 Setting::HeaderTableSize(_) => {
678 }
680 _ => {}
681 }
682 }
683 write_header(
685 &mut self.out,
686 0,
687 FrameKind::Settings,
688 FrameFlags::from_u8(0x01),
689 0,
690 );
691 Ok(())
692 }
693
694 fn handle_ping(&mut self, hdr: &FrameHeader, payload: &[u8]) -> Result<(), u32> {
695 if payload.len() != 8 {
696 return Err(error_code::FRAME_SIZE_ERROR);
697 }
698 if hdr.flags.ack() {
699 return Ok(()); }
701 write_header(
702 &mut self.out,
703 8,
704 FrameKind::Ping,
705 FrameFlags::from_u8(0x01),
706 0,
707 );
708 self.out.extend_from_slice(payload);
709 Ok(())
710 }
711
712 fn handle_window_update(
713 &mut self,
714 hdr: &FrameHeader,
715 payload: &[u8],
716 events: &mut Vec<Event>,
717 ) -> Result<(), u32> {
718 let inc = parse_window_update(payload).map_err(|_| error_code::FRAME_SIZE_ERROR)?;
719 if inc == 0 {
720 return Err(error_code::PROTOCOL_ERROR);
721 }
722 let inc = i64::from(inc);
723 if hdr.stream_id == 0 {
724 self.conn_send_window += inc;
725 if self.conn_send_window > (1 << 31) - 1 {
726 return Err(error_code::FLOW_CONTROL_ERROR);
727 }
728 } else if let Some(st) = self.streams.get_mut(&hdr.stream_id) {
729 st.send_window += inc;
730 } else {
731 let cur = self
738 .retired_windows
739 .get(&hdr.stream_id)
740 .copied()
741 .unwrap_or(0);
742 let updated = cur + inc;
743 if updated > (1 << 31) - 1 {
744 write_header(
745 &mut self.out,
746 4,
747 FrameKind::RstStream,
748 FrameFlags::EMPTY,
749 hdr.stream_id,
750 );
751 self.out
752 .extend_from_slice(&error_code::FLOW_CONTROL_ERROR.to_be_bytes());
753 return Err(error_code::FLOW_CONTROL_ERROR);
754 }
755 self.retired_windows.insert(hdr.stream_id, updated);
756 }
757 events.push(Event::WindowUpdate {
758 stream_id: hdr.stream_id,
759 });
760 Ok(())
761 }
762
763 fn handle_headers(
764 &mut self,
765 hdr: &FrameHeader,
766 payload: &[u8],
767 events: &mut Vec<Event>,
768 ) -> Result<(), u32> {
769 use super::frame::validate_payload;
770 if payload.len() > self.cfg.max_frame_size as usize {
772 return Err(error_code::FRAME_SIZE_ERROR);
773 }
774 let Ok(split) = validate_payload(hdr, payload, self.peer_max_frame) else {
775 return Err(error_code::FRAME_SIZE_ERROR);
776 };
777 if hdr.stream_id & 1 == 0 {
781 return Err(error_code::PROTOCOL_ERROR);
782 }
783
784 let known = self.streams.contains_key(&hdr.stream_id);
788 if !known && hdr.stream_id <= self.last_peer_stream_id {
789 return Err(error_code::PROTOCOL_ERROR);
790 }
791 if let Some(st) = self.streams.get(&hdr.stream_id) {
794 if matches!(
795 st.state,
796 StreamState::HalfClosedRemote | StreamState::Closed
797 ) {
798 return Err(error_code::STREAM_CLOSED);
799 }
800 }
801 if !known
802 && self.role == Role::Server
803 && self.streams.len() >= self.cfg.max_concurrent_streams as usize
804 {
805 write_header(
807 &mut self.out,
808 4,
809 FrameKind::RstStream,
810 FrameFlags::EMPTY,
811 hdr.stream_id,
812 );
813 self.out
814 .extend_from_slice(&error_code::REFUSED_STREAM.to_be_bytes());
815 return Ok(());
816 }
817 self.last_peer_stream_id = hdr.stream_id;
818
819 let mut frag = &payload[split.content_start..split.content_end];
823 if hdr.flags.priority() {
824 if frag.len() < 5 {
825 return Err(error_code::FRAME_SIZE_ERROR);
826 }
827 let dep = u32::from_be_bytes([frag[0], frag[1], frag[2], frag[3]]) & 0x7fff_ffff;
828 if dep == hdr.stream_id {
829 return Err(error_code::PROTOCOL_ERROR);
830 }
831 frag = &frag[5..];
832 }
833
834 let end_stream = hdr.flags.end_stream();
835 if hdr.flags.end_headers() {
836 let headers = {
837 let mut bd = HpackBlockDecoder {
838 fragments: frag.to_vec(),
839 decoder: &mut self.decoder,
840 };
841 bd.decode_all()
842 };
843 match headers {
844 Ok(headers) => {
845 let are_trailers = self
848 .streams
849 .get(&hdr.stream_id)
850 .is_some_and(|st| st.peer_data);
851 if self.role == Role::Server {
852 let head_dup = self
856 .streams
857 .get(&hdr.stream_id)
858 .is_some_and(|st| st.head_done && !st.peer_data);
859 if head_dup {
860 write_header(
861 &mut self.out,
862 4,
863 FrameKind::RstStream,
864 FrameFlags::EMPTY,
865 hdr.stream_id,
866 );
867 self.out
868 .extend_from_slice(&error_code::PROTOCOL_ERROR.to_be_bytes());
869 return Ok(());
870 }
871 let head_cl = self.check_request_headers(
872 hdr.stream_id,
873 end_stream,
874 &headers,
875 are_trailers,
876 );
877 if head_cl.is_err() {
878 write_header(
881 &mut self.out,
882 4,
883 FrameKind::RstStream,
884 FrameFlags::EMPTY,
885 hdr.stream_id,
886 );
887 self.out
888 .extend_from_slice(&error_code::PROTOCOL_ERROR.to_be_bytes());
889 return Ok(());
890 }
891 self.ensure_stream(hdr.stream_id, end_stream);
892 if let (Some(st), Some(cl)) =
893 (self.streams.get_mut(&hdr.stream_id), head_cl.unwrap())
894 {
895 st.content_length = Some(cl);
896 st.head_done = true;
897 }
898 } else {
899 self.ensure_stream(hdr.stream_id, end_stream);
900 }
901 if end_stream {
902 if let Some(st) = self.streams.get_mut(&hdr.stream_id) {
903 st.state = StreamState::HalfClosedRemote;
904 }
905 }
906 if are_trailers {
907 events.push(Event::Trailers {
908 stream_id: hdr.stream_id,
909 headers,
910 });
911 } else {
912 events.push(Event::Headers {
913 stream_id: hdr.stream_id,
914 end_stream,
915 headers,
916 });
917 }
918 return Ok(());
919 }
920 Err(_) => return Err(error_code::COMPRESSION_ERROR),
921 }
922 }
923
924 self.header_block = HeaderBlockAssembler {
926 fragments: frag.to_vec(),
927 stream_id: hdr.stream_id,
928 end_stream,
929 active: true,
930 };
931 Ok(())
932 }
933
934 fn finish_headers(&mut self, events: &mut Vec<Event>) -> Result<(), u32> {
935 let (stream_id, end_stream) = (self.header_block.stream_id, self.header_block.end_stream);
936 let mut decoder = HpackBlockDecoder {
937 fragments: std::mem::take(&mut self.header_block.fragments),
938 decoder: &mut self.decoder,
939 };
940 self.header_block.active = false;
941 match decoder.decode_all() {
942 Ok(headers) => {
943 let are_trailers = self.streams.get(&stream_id).is_some_and(|st| st.peer_data);
945 if self.role == Role::Server {
946 let head_dup = self
949 .streams
950 .get(&stream_id)
951 .is_some_and(|st| st.head_done && !st.peer_data);
952 if head_dup {
953 write_header(
954 &mut self.out,
955 4,
956 FrameKind::RstStream,
957 FrameFlags::EMPTY,
958 stream_id,
959 );
960 self.out
961 .extend_from_slice(&error_code::PROTOCOL_ERROR.to_be_bytes());
962 return Ok(());
963 }
964 let head_cl =
965 self.check_request_headers(stream_id, end_stream, &headers, are_trailers);
966 if head_cl.is_err() {
967 write_header(
968 &mut self.out,
969 4,
970 FrameKind::RstStream,
971 FrameFlags::EMPTY,
972 stream_id,
973 );
974 self.out
975 .extend_from_slice(&error_code::PROTOCOL_ERROR.to_be_bytes());
976 return Ok(());
977 }
978 self.ensure_stream(stream_id, end_stream);
979 if let (Some(st), Some(cl)) =
980 (self.streams.get_mut(&stream_id), head_cl.unwrap())
981 {
982 st.content_length = Some(cl);
983 st.head_done = true;
984 }
985 } else {
986 self.ensure_stream(stream_id, end_stream);
987 }
988 if end_stream {
989 if let Some(st) = self.streams.get_mut(&stream_id) {
990 st.state = StreamState::HalfClosedRemote;
991 }
992 }
993 if are_trailers {
994 events.push(Event::Trailers { stream_id, headers });
995 } else {
996 events.push(Event::Headers {
997 stream_id,
998 end_stream,
999 headers,
1000 });
1001 }
1002 Ok(())
1003 }
1004 Err(_) => Err(error_code::COMPRESSION_ERROR),
1005 }
1006 }
1007
1008 fn is_peer_idle(&self, stream_id: u32) -> bool {
1012 let peer_parity = match self.role {
1013 Role::Server => stream_id & 1 == 1,
1014 Role::Client => stream_id & 1 == 0,
1015 };
1016 peer_parity && stream_id > self.last_peer_stream_id
1017 }
1018
1019 fn check_request_headers(
1025 &self,
1026 stream_id: u32,
1027 end_stream: bool,
1028 headers: &[super::hpack::Header],
1029 trailers: bool,
1030 ) -> Result<Option<u64>, ()> {
1031 let _ = stream_id;
1032 let mut pseudo_seen = false;
1033 let mut regular_seen = false;
1034 let mut method_seen = false;
1035 let mut scheme_seen = false;
1036 let mut path_seen = false;
1037 let mut content_length: Option<u64> = None;
1038 for header in headers {
1039 let (name, value) = (&header.name, &header.value);
1040 if name.iter().any(|b| b.is_ascii_uppercase()) {
1041 return Err(());
1042 }
1043 if name.first() == Some(&b':') {
1044 if regular_seen {
1047 return Err(());
1048 }
1049 match name.as_slice() {
1050 b":method" => {
1051 if method_seen {
1052 return Err(());
1053 }
1054 method_seen = true;
1055 }
1056 b":scheme" => {
1057 if scheme_seen {
1058 return Err(());
1059 }
1060 scheme_seen = true;
1061 }
1062 b":path" => {
1063 if path_seen {
1064 return Err(());
1065 }
1066 path_seen = true;
1067 }
1068 b":authority" => {}
1071 _ => {
1072 return Err(());
1074 }
1075 }
1076 } else {
1077 regular_seen = true;
1078 if name == b"te" && !value.eq_ignore_ascii_case(b"trailers") {
1079 return Err(());
1080 }
1081 if name == b"content-length" {
1082 content_length = std::str::from_utf8(value)
1083 .ok()
1084 .and_then(|s| s.parse::<u64>().ok());
1085 if content_length.is_none() {
1086 return Err(());
1087 }
1088 }
1089 }
1090 }
1091 if trailers && (pseudo_seen || !end_stream) {
1092 return Err(());
1093 }
1094 if !trailers && !(method_seen && scheme_seen && path_seen) {
1095 return Err(());
1099 }
1100 Ok(content_length)
1101 }
1102
1103 fn ensure_stream(&mut self, id: u32, end_stream: bool) {
1104 let entry = self.streams.entry(id).or_insert(Stream {
1105 state: StreamState::Open,
1106 recv_window: i64::from(self.cfg.initial_window_size),
1107 send_window: self.peer_initial_window,
1108 sent_end: false,
1109 peer_data: false,
1110 content_length: None,
1111 content_received: 0,
1112 head_invalid: false,
1113 head_done: false,
1114 });
1115 if end_stream {
1116 let retire = entry.sent_end;
1117 entry.state = StreamState::HalfClosedRemote;
1118 if retire {
1120 self.streams.remove(&id);
1121 }
1122 }
1123 }
1124
1125 fn handle_data(
1126 &mut self,
1127 hdr: &FrameHeader,
1128 payload: &[u8],
1129 events: &mut Vec<Event>,
1130 ) -> Result<(), u32> {
1131 if payload.len() > self.cfg.max_frame_size as usize {
1133 return Err(error_code::FRAME_SIZE_ERROR);
1134 }
1135 let Ok(split) = validate_payload(hdr, payload, self.peer_max_frame) else {
1136 return Err(error_code::FRAME_SIZE_ERROR);
1137 };
1138 let id = hdr.stream_id;
1139
1140 let Some(st) = self.streams.get_mut(&id) else {
1141 return Err(error_code::STREAM_CLOSED);
1143 };
1144 if st.state == StreamState::Closed || st.state == StreamState::HalfClosedRemote {
1145 return Err(error_code::STREAM_CLOSED);
1146 }
1147
1148 let content = &payload[split.content_start..split.content_end];
1149 self.conn_recv_window -= content.len() as i64;
1151 st.recv_window -= content.len() as i64;
1152 if !content.is_empty() {
1153 st.peer_data = true;
1154 }
1155 st.content_received += content.len() as u64;
1156
1157 let end_stream = hdr.flags.end_stream();
1158 if end_stream {
1159 if let Some(cl) = st.content_length {
1161 if st.content_received != cl {
1162 return Err(error_code::PROTOCOL_ERROR);
1163 }
1164 }
1165 st.state = StreamState::HalfClosedRemote;
1166 }
1167 events.push(Event::Data {
1168 stream_id: id,
1169 end_stream,
1170 data: content.to_vec(),
1171 });
1172 Ok(())
1173 }
1174
1175 pub fn release_capacity(&mut self, stream_id: u32, n: usize) {
1178 let n = n as i64;
1179 self.conn_recv_window += n;
1186 if n > 0 {
1187 write_header(
1188 &mut self.out,
1189 4,
1190 FrameKind::WindowUpdate,
1191 FrameFlags::EMPTY,
1192 0,
1193 );
1194 self.out.extend_from_slice(&(n as u32).to_be_bytes());
1195 }
1196 if let Some(st) = self.streams.get_mut(&stream_id) {
1197 st.recv_window += n;
1198 if n > 0 {
1199 write_header(
1200 &mut self.out,
1201 4,
1202 FrameKind::WindowUpdate,
1203 FrameFlags::EMPTY,
1204 stream_id,
1205 );
1206 self.out.extend_from_slice(&(n as u32).to_be_bytes());
1207 }
1208 }
1209 }
1210
1211 pub fn open_stream(&mut self, stream_id: u32) {
1214 self.streams.entry(stream_id).or_insert(Stream {
1215 state: StreamState::Open,
1216 recv_window: i64::from(self.cfg.initial_window_size),
1217 send_window: self.peer_initial_window,
1218 sent_end: false,
1219 peer_data: false,
1220 content_length: None,
1221 content_received: 0,
1222 head_invalid: false,
1223 head_done: false,
1224 });
1225 }
1226
1227 pub fn alloc_stream_id(&mut self) -> u32 {
1229 let id = self.next_stream_id;
1230 self.next_stream_id += 2;
1231 self.open_stream(id);
1232 id
1233 }
1234
1235 pub fn send_headers(
1239 &mut self,
1240 stream_id: u32,
1241 headers: &[(Vec<u8>, Vec<u8>)],
1242 end_stream: bool,
1243 ) {
1244 let mut block = Vec::new();
1245 self.encoder.encode(headers, &mut block);
1246
1247 let fits = block.len() <= self.peer_max_frame as usize;
1251 let max_frag = self.peer_max_frame as usize;
1252 let first = &block[..block.len().min(max_frag)];
1253 let mut flags = if end_stream { 0x04 | 0x01 } else { 0x04 };
1254 if !fits {
1255 flags &= !0x04;
1256 }
1257 write_header(
1258 &mut self.out,
1259 first.len() as u32,
1260 FrameKind::Headers,
1261 FrameFlags::from_u8(flags & 0x04 | if end_stream && fits { 0x01 } else { 0 }),
1262 stream_id,
1263 );
1264 self.out.extend_from_slice(first);
1265
1266 let mut rest = &block[first.len()..];
1267 while !rest.is_empty() {
1268 let n = rest.len().min(max_frag);
1269 let last = n == rest.len();
1270 write_header(
1271 &mut self.out,
1272 n as u32,
1273 FrameKind::Continuation,
1274 FrameFlags::from_u8(if last { 0x04 } else { 0 }),
1275 stream_id,
1276 );
1277 self.out.extend_from_slice(&rest[..n]);
1278 rest = &rest[n..];
1279 }
1280 if end_stream {
1281 let mut retire = false;
1282 if let Some(st) = self.streams.get_mut(&stream_id) {
1283 st.sent_end = true;
1284 st.state = match st.state {
1285 StreamState::HalfClosedRemote => {
1286 retire = true; StreamState::Closed
1288 }
1289 _ => StreamState::HalfClosedLocal,
1290 };
1291 }
1292 if retire {
1293 self.streams.remove(&stream_id);
1294 }
1295 }
1296 }
1297
1298 pub fn send_data(&mut self, stream_id: u32, data: &[u8], end_stream: bool) -> usize {
1302 let cap = self
1303 .streams
1304 .get(&stream_id)
1305 .map(|st| st.send_window.min(self.conn_send_window))
1306 .unwrap_or(0);
1307 let cap = (cap.max(0) as usize).min(self.peer_max_frame as usize);
1308 let n = data.len().min(cap);
1309 if n == 0 {
1310 return 0;
1311 }
1312
1313 let last = n == data.len();
1314 let flags = if last && end_stream { 0x01 } else { 0x00 };
1315 write_header(
1316 &mut self.out,
1317 n as u32,
1318 FrameKind::Data,
1319 FrameFlags::from_u8(flags),
1320 stream_id,
1321 );
1322 self.out.extend_from_slice(&data[..n]);
1323
1324 self.conn_send_window -= n as i64;
1325 let mut retire = false;
1326 if let Some(st) = self.streams.get_mut(&stream_id) {
1327 st.send_window -= n as i64;
1328 if last && end_stream {
1329 st.sent_end = true;
1330 st.state = match st.state {
1331 StreamState::HalfClosedRemote => {
1332 retire = true; StreamState::Closed
1334 }
1335 _ => StreamState::HalfClosedLocal,
1336 };
1337 }
1338 }
1339 if retire {
1340 self.streams.remove(&stream_id);
1341 }
1342 n
1343 }
1344
1345 pub fn send_rst_stream(&mut self, stream_id: u32, code: u32) {
1347 write_header(
1348 &mut self.out,
1349 4,
1350 FrameKind::RstStream,
1351 FrameFlags::EMPTY,
1352 stream_id,
1353 );
1354 self.out.extend_from_slice(&code.to_be_bytes());
1355 self.streams.remove(&stream_id);
1356 }
1357
1358 pub fn send_ping(&mut self, payload: &[u8; 8]) {
1360 write_header(&mut self.out, 8, FrameKind::Ping, FrameFlags::EMPTY, 0);
1361 self.out.extend_from_slice(payload);
1362 }
1363
1364 pub fn send_goaway(&mut self, error_code: u32) {
1366 if self.goaway_sent {
1367 return;
1368 }
1369 self.goaway_sent = true;
1370 let mut payload = Vec::new();
1371 payload.extend_from_slice(&self.last_peer_stream_id.to_be_bytes());
1372 payload.extend_from_slice(&error_code.to_be_bytes());
1373 write_header(
1374 &mut self.out,
1375 payload.len() as u32,
1376 FrameKind::GoAway,
1377 FrameFlags::EMPTY,
1378 0,
1379 );
1380 self.out.extend_from_slice(&payload);
1381 }
1382}
1383
1384struct HpackBlockDecoder<'a> {
1386 fragments: Vec<u8>,
1387 decoder: &'a mut HpackDecoder,
1388}
1389
1390impl HpackBlockDecoder<'_> {
1391 fn decode_all(&mut self) -> Result<Vec<super::hpack::Header>, HpackError> {
1392 self.decoder.decode(&self.fragments)
1393 }
1394}
1395
1396#[cfg(test)]
1397mod conn_tests {
1398 use super::*;
1399
1400 fn server() -> Connection {
1401 Connection::new(Role::Server, ConnectionConfig::default())
1402 }
1403
1404 fn client_conn() -> Connection {
1405 Connection::new(Role::Client, ConnectionConfig::default())
1406 }
1407
1408 fn frame_bytes(kind: FrameKind, flags: u8, stream_id: u32, payload: &[u8]) -> Vec<u8> {
1409 let mut out = Vec::new();
1410 write_header(
1411 &mut out,
1412 payload.len() as u32,
1413 kind,
1414 FrameFlags::from_u8(flags),
1415 stream_id,
1416 );
1417 out.extend_from_slice(payload);
1418 out
1419 }
1420
1421 #[test]
1423 fn server_acknowledges_client_settings() {
1424 let mut c = server();
1425 let mut events = Vec::new();
1426 let mut preface_and_settings = CLIENT_PREFACE.to_vec();
1429 write_header(
1430 &mut preface_and_settings,
1431 6,
1432 FrameKind::Settings,
1433 FrameFlags::EMPTY,
1434 0,
1435 );
1436 write_setting(&mut preface_and_settings, 0x3, 128);
1437 c.handle_read(&preface_and_settings, &mut events);
1438 assert!(events.is_empty());
1439 let writes = c.take_pending_writes();
1440 assert_eq!(writes.len(), 39 + 9, "expected SETTINGS + ACK: {writes:?}");
1442 assert_eq!(writes[39 + 4] & 0x01, 0x01, "ACK flag");
1444 }
1445
1446 #[test]
1447 fn bad_preface_is_connection_error() {
1448 let mut c = server();
1449 let mut events = Vec::new();
1450 c.handle_read(b"NOT THE PREFACE", &mut events);
1451 assert_eq!(
1452 c.connection_error().map(|e| e.code),
1453 Some(error_code::PROTOCOL_ERROR)
1454 );
1455 }
1456
1457 #[test]
1459 fn server_headers_end_stream() {
1460 let mut c = server();
1461 let mut events = Vec::new();
1462 c.handle_read(CLIENT_PREFACE, &mut events);
1463 let _ = c.take_pending_writes();
1464
1465 let block = [0x82, 0x86, 0x84]; c.handle_read(
1468 &frame_bytes(FrameKind::Headers, 0x05, 1, &block),
1469 &mut events,
1470 );
1471 assert_eq!(events.len(), 1);
1472 match &events[0] {
1473 Event::Headers {
1474 stream_id,
1475 end_stream,
1476 headers,
1477 } => {
1478 assert_eq!(*stream_id, 1);
1479 assert!(*end_stream);
1480 assert!(!headers.is_empty());
1481 }
1482 other => panic!("expected headers event: {other:?}"),
1483 }
1484 }
1485
1486 #[test]
1488 fn even_stream_id_from_client_is_error() {
1489 let mut c = server();
1490 let mut events = Vec::new();
1491 c.handle_read(CLIENT_PREFACE, &mut events);
1492 let _ = c.take_pending_writes();
1493
1494 c.handle_read(
1495 &frame_bytes(FrameKind::Headers, 0x05, 2, &[0x82, 0x86, 0x84]),
1496 &mut events,
1497 );
1498 assert_eq!(
1499 c.connection_error().map(|e| e.code),
1500 Some(error_code::PROTOCOL_ERROR)
1501 );
1502 }
1503
1504 #[test]
1506 fn data_on_unknown_stream_is_error() {
1507 let mut c = server();
1508 let mut events = Vec::new();
1509 c.handle_read(CLIENT_PREFACE, &mut events);
1510 let _ = c.take_pending_writes();
1511
1512 c.handle_read(&frame_bytes(FrameKind::Data, 0x00, 5, b"x"), &mut events);
1513 assert_eq!(
1514 c.connection_error().map(|e| e.code),
1515 Some(error_code::STREAM_CLOSED)
1516 );
1517 }
1518
1519 #[test]
1521 fn data_relay_with_flow_accounting() {
1522 let mut c = server();
1523 let mut events = Vec::new();
1524 c.handle_read(CLIENT_PREFACE, &mut events);
1525 let _ = c.take_pending_writes();
1526
1527 c.handle_read(
1529 &frame_bytes(FrameKind::Headers, 0x04, 1, &[0x82, 0x86, 0x84]),
1530 &mut events,
1531 );
1532 assert_eq!(events.len(), 1, "headers event");
1533
1534 c.handle_read(
1536 &frame_bytes(FrameKind::Data, 0x01, 1, b"payload"),
1537 &mut events,
1538 );
1539 assert_eq!(events.len(), 2);
1540 match &events[1] {
1541 Event::Data {
1542 stream_id,
1543 end_stream,
1544 data,
1545 } => {
1546 assert_eq!(*stream_id, 1);
1547 assert!(*end_stream);
1548 assert_eq!(data, b"payload");
1549 }
1550 other => panic!("expected data event: {other:?}"),
1551 }
1552 }
1553
1554 #[test]
1556 fn release_capacity_emits_window_updates() {
1557 let mut c = server();
1558 let mut events = Vec::new();
1559 c.handle_read(CLIENT_PREFACE, &mut events);
1560 let _ = c.take_pending_writes();
1561
1562 c.handle_read(
1565 &frame_bytes(FrameKind::Headers, 0x04, 1, &[0x82, 0x86, 0x84]),
1566 &mut events,
1567 );
1568
1569 let chunk = vec![0u8; 16384];
1574 for _ in 0..8 {
1575 c.handle_read(&frame_bytes(FrameKind::Data, 0x00, 1, &chunk), &mut events);
1576 c.release_capacity(1, chunk.len());
1577 }
1578 let writes = c.take_pending_writes();
1579 assert_eq!(
1580 writes.len(),
1581 16 * 13,
1582 "8 conn + 8 stream WINDOW_UPDATEs (9 hdr + 4 payload each)"
1583 );
1584 }
1585
1586 #[test]
1588 fn ping_gets_pong() {
1589 let mut c = server();
1590 let mut events = Vec::new();
1591 c.handle_read(CLIENT_PREFACE, &mut events);
1592 let _ = c.take_pending_writes();
1593
1594 c.handle_read(
1595 &frame_bytes(FrameKind::Ping, 0x00, 0, &[7u8; 8]),
1596 &mut events,
1597 );
1598 let writes = c.take_pending_writes();
1599 assert_eq!(writes.len(), 9 + 8);
1600 assert_eq!(writes[4], 0x01);
1602 assert_eq!(&writes[9..17], &[7u8; 8]);
1603 }
1604
1605 #[test]
1607 fn goaway_event() {
1608 let mut c = server();
1609 let mut events = Vec::new();
1610 c.handle_read(CLIENT_PREFACE, &mut events);
1611 let _ = c.take_pending_writes();
1612
1613 let mut payload = Vec::new();
1614 payload.extend_from_slice(&7u32.to_be_bytes());
1615 payload.extend_from_slice(&2u32.to_be_bytes());
1616 c.handle_read(
1617 &frame_bytes(FrameKind::GoAway, 0x00, 0, &payload),
1618 &mut events,
1619 );
1620 assert_eq!(events.len(), 1);
1621 match &events[0] {
1622 Event::GoAway {
1623 last_stream_id,
1624 error_code,
1625 } => {
1626 assert_eq!(*last_stream_id, 7);
1627 assert_eq!(*error_code, 2);
1628 }
1629 other => panic!("expected goaway: {other:?}"),
1630 }
1631 }
1632
1633 #[test]
1635 fn settings_initial_window_delta() {
1636 let mut c = client_conn();
1637 let mut events = Vec::new();
1638 c.handle_read(&frame_bytes(FrameKind::Settings, 0x00, 0, &[]), &mut events);
1639
1640 let id = c.alloc_stream_id();
1642 assert_eq!(id, 1);
1643
1644 let mut payload = Vec::new();
1647 write_setting(&mut payload, 0x4, 1_048_576);
1648 c.handle_read(
1649 &frame_bytes(FrameKind::Settings, 0x00, 0, &payload),
1650 &mut events,
1651 );
1652
1653 let mut sent = 0usize;
1657 while sent < 65535 {
1658 let want = 16384.min(65535 - sent);
1659 let data = vec![0u8; want];
1660 let n = c.send_data(id, &data, false);
1661 assert_eq!(n, want, "frame at {sent}");
1662 sent += n;
1663 }
1664 let n2 = c.send_data(id, &[0u8; 16384], false);
1668 assert_eq!(n2, 0, "connection window exhausted");
1669
1670 let conn_payload = {
1673 let mut p = 100_000u32.to_be_bytes().to_vec();
1674 p[0] &= 0x7f;
1675 p
1676 };
1677 c.handle_read(
1678 &frame_bytes(FrameKind::WindowUpdate, 0x00, 0, &conn_payload),
1679 &mut events,
1680 );
1681 let n3 = c.send_data(id, &[0u8; 16384], false);
1682 assert_eq!(n3, 16384, "send resumes once both windows have credit");
1683 }
1684
1685 #[test]
1689 fn client_receives_response_headers() {
1690 let mut c = client_conn();
1691 let _ = c.take_pending_writes();
1693
1694 c.open_stream(1);
1696 let mut events = Vec::new();
1697 c.handle_read(
1699 &frame_bytes(FrameKind::Headers, 0x05, 1, &[0x88]),
1700 &mut events,
1701 );
1702 assert_eq!(events.len(), 1);
1703 match &events[0] {
1704 Event::Headers {
1705 stream_id,
1706 end_stream,
1707 headers,
1708 } => {
1709 assert_eq!(*stream_id, 1);
1710 assert!(*end_stream);
1711 assert_eq!(headers[0].name, b":status");
1712 assert_eq!(headers[0].value, b"200");
1713 }
1714 other => panic!("expected headers: {other:?}"),
1715 }
1716 }
1717
1718 #[test]
1721 fn client_receives_response_trailers() {
1722 let mut c = client_conn();
1723 let _ = c.take_pending_writes();
1724 let mut events = Vec::new();
1725
1726 c.open_stream(1);
1729 c.handle_read(
1731 &frame_bytes(FrameKind::Headers, 0x04, 1, &[0x88]),
1732 &mut events,
1733 );
1734 c.handle_read(
1736 &frame_bytes(FrameKind::Data, 0x00, 1, b"grpc-payload"),
1737 &mut events,
1738 );
1739 let mut trailers = Vec::new();
1741 trailers.extend_from_slice(&[0x00, 0x0b]);
1742 trailers.extend_from_slice(b"grpc-status");
1743 trailers.extend_from_slice(&[0x01, b'0']);
1744 c.handle_read(
1745 &frame_bytes(FrameKind::Headers, 0x05, 1, &trailers),
1746 &mut events,
1747 );
1748
1749 let kinds: Vec<&str> = events
1750 .iter()
1751 .filter_map(|ev| match ev {
1752 Event::Headers { .. } => Some("headers"),
1753 Event::Data { .. } => Some("data"),
1754 Event::Trailers { .. } => Some("trailers"),
1755 _ => None,
1756 })
1757 .collect();
1758 assert_eq!(kinds, vec!["headers", "data", "trailers"], "{events:?}");
1759 match &events[2] {
1760 Event::Trailers { headers, .. } => {
1761 assert_eq!(headers[0].name, b"grpc-status");
1762 }
1763 other => panic!("expected trailers: {other:?}"),
1764 }
1765 }
1766
1767 #[test]
1770 fn request_trailers_surfaces_as_trailers_event() {
1771 let mut c = server();
1772 let mut events = Vec::new();
1773 let mut flight = CLIENT_PREFACE.to_vec();
1775 flight.extend_from_slice(&frame_bytes(FrameKind::Settings, 0x00, 0, &[]));
1776 c.handle_read(&flight, &mut events);
1777 let _ = c.take_pending_writes();
1778
1779 c.handle_read(
1783 &frame_bytes(FrameKind::Headers, 0x04, 1, &[0x83, 0x86, 0x84]),
1784 &mut events,
1785 );
1786 c.handle_read(
1787 &frame_bytes(FrameKind::Data, 0x00, 1, b"payload"),
1788 &mut events,
1789 );
1790 let mut trailers = Vec::new();
1793 trailers.extend_from_slice(&[0x00, 0x0b]);
1794 trailers.extend_from_slice(b"grpc-status");
1795 trailers.extend_from_slice(&[0x01, b'0']);
1796 c.handle_read(
1797 &frame_bytes(FrameKind::Headers, 0x05, 1, &trailers),
1798 &mut events,
1799 );
1800
1801 let kinds: Vec<&str> = events
1802 .iter()
1803 .filter_map(|ev| match ev {
1804 Event::Headers { .. } => Some("headers"),
1805 Event::Data { .. } => Some("data"),
1806 Event::Trailers { .. } => Some("trailers"),
1807 _ => None,
1808 })
1809 .collect();
1810 assert_eq!(kinds, vec!["headers", "data", "trailers"], "{events:?}");
1811 match &events[2] {
1812 Event::Trailers { stream_id, headers } => {
1813 assert_eq!(*stream_id, 1);
1814 assert_eq!(headers[0].name, b"grpc-status");
1815 assert_eq!(headers[0].value, b"0");
1816 }
1817 other => panic!("expected trailers: {other:?}"),
1818 }
1819 }
1820
1821 #[test]
1824 fn client_rejects_even_stream_headers() {
1825 let mut c = client_conn();
1826 let _ = c.take_pending_writes();
1827 let mut events = Vec::new();
1828 c.handle_read(
1829 &frame_bytes(FrameKind::Headers, 0x05, 2, &[0x88]),
1830 &mut events,
1831 );
1832 assert_eq!(
1833 c.connection_error().map(|e| e.code),
1834 Some(error_code::PROTOCOL_ERROR)
1835 );
1836 }
1837
1838 #[test]
1840 fn continuation_assembles_block() {
1841 let mut c = server();
1842 let mut events = Vec::new();
1843 c.handle_read(CLIENT_PREFACE, &mut events);
1844 let _ = c.take_pending_writes();
1845
1846 c.handle_read(
1849 &frame_bytes(FrameKind::Headers, 0x01, 1, &[0x82, 0x86]),
1850 &mut events,
1851 );
1852 assert!(events.is_empty(), "block not yet complete");
1853
1854 c.handle_read(
1856 &frame_bytes(FrameKind::Continuation, 0x04, 1, &[0x84]),
1857 &mut events,
1858 );
1859 assert_eq!(events.len(), 1);
1860 match &events[0] {
1861 Event::Headers {
1862 end_stream,
1863 headers,
1864 ..
1865 } => {
1866 assert!(*end_stream);
1867 assert!(headers.len() >= 2);
1868 }
1869 other => panic!("expected headers: {other:?}"),
1870 }
1871 }
1872
1873 #[test]
1875 fn interrupted_header_block_is_error() {
1876 let mut c = server();
1877 let mut events = Vec::new();
1878 c.handle_read(CLIENT_PREFACE, &mut events);
1879 let _ = c.take_pending_writes();
1880
1881 c.handle_read(
1882 &frame_bytes(FrameKind::Headers, 0x01, 1, &[0x82, 0x86, 0x84]),
1883 &mut events,
1884 );
1885 c.handle_read(
1886 &frame_bytes(FrameKind::Ping, 0x00, 0, &[7u8; 8]),
1887 &mut events,
1888 );
1889 assert_eq!(
1890 c.connection_error().map(|e| e.code),
1891 Some(error_code::PROTOCOL_ERROR)
1892 );
1893 }
1894
1895 #[test]
1897 fn hpack_corruption_is_compression_error() {
1898 let mut c = server();
1899 let mut events = Vec::new();
1900 c.handle_read(CLIENT_PREFACE, &mut events);
1901 let _ = c.take_pending_writes();
1902
1903 c.handle_read(
1905 &frame_bytes(FrameKind::Headers, 0x05, 1, &[0x80]),
1906 &mut events,
1907 );
1908 assert_eq!(
1909 c.connection_error().map(|e| e.code),
1910 Some(error_code::COMPRESSION_ERROR)
1911 );
1912 }
1913
1914 #[test]
1918 fn send_headers_splits_into_continuations() {
1919 let mut c = client_conn();
1920 let _ = c.take_pending_writes(); let id = c.alloc_stream_id();
1922 let big = vec![b'a'; 40_960];
1924 let headers = vec![
1925 (b":method".to_vec(), b"GET".to_vec()),
1926 (b"x-big".to_vec(), big),
1927 ];
1928 c.send_headers(id, &headers, true);
1929 let writes = c.take_pending_writes();
1930 let mut off = 0usize;
1932 let mut kinds = Vec::new();
1933 while off < writes.len() {
1934 let len =
1935 u32::from_be_bytes([0, writes[off], writes[off + 1], writes[off + 2]]) as usize;
1936 kinds.push((writes[off + 3], writes[off + 4]));
1937 off += 9 + len;
1938 }
1939 assert!(kinds.len() >= 2, "expected split frames: {kinds:?}");
1940 let (first_kind, first_flags) = kinds[0];
1941 assert_eq!(first_kind, 0x01, "HEADERS");
1942 assert_eq!(first_flags & 0x04, 0, "END_HEADERS clear on first frame");
1943 let (last_kind, last_flags) = *kinds.last().expect("nonempty");
1944 assert_eq!(last_kind, 0x09, "CONTINUATION");
1945 assert_eq!(last_flags & 0x04, 0x04, "END_HEADERS on last frame");
1946 }
1947
1948 #[test]
1950 fn data_after_end_stream_is_stream_closed() {
1951 let mut c = server();
1952 let mut events = Vec::new();
1953 c.handle_read(CLIENT_PREFACE, &mut events);
1954 let _ = c.take_pending_writes();
1955
1956 c.handle_read(
1958 &frame_bytes(FrameKind::Headers, 0x05, 1, &[0x82, 0x86, 0x84]),
1959 &mut events,
1960 );
1961 assert_eq!(events.len(), 1);
1962 c.handle_read(&frame_bytes(FrameKind::Data, 0x00, 1, b"late"), &mut events);
1964 assert_eq!(
1965 c.connection_error().map(|e| e.code),
1966 Some(error_code::STREAM_CLOSED)
1967 );
1968 }
1969
1970 #[test]
1972 fn unexpected_settings_ack_is_protocol_error() {
1973 let mut c = server();
1974 let mut events = Vec::new();
1975 let mut preface = CLIENT_PREFACE.to_vec();
1978 preface.extend_from_slice(&frame_bytes(FrameKind::Settings, 0x00, 0, &[]));
1979 preface.extend_from_slice(&frame_bytes(FrameKind::Settings, 0x01, 0, &[]));
1980 c.handle_read(&preface, &mut events);
1981 assert!(c.connection_error().is_none());
1982 let _ = c.take_pending_writes();
1983
1984 c.handle_read(&frame_bytes(FrameKind::Settings, 0x01, 0, &[]), &mut events);
1986 assert_eq!(
1987 c.connection_error().map(|e| e.code),
1988 Some(error_code::PROTOCOL_ERROR)
1989 );
1990 }
1991
1992 #[test]
1994 fn send_data_respects_flow_control() {
1995 let mut c = client_conn();
1996 let id = c.alloc_stream_id();
1997
1998 for expected in [16384usize, 16384, 16384, 16383] {
2003 let data = vec![0u8; expected];
2004 let n = c.send_data(id, &data, false);
2005 assert_eq!(n, expected);
2006 }
2007 assert_eq!(c.send_data(id, &[0u8; 1000], false), 0, "window exhausted");
2009
2010 let mut events = Vec::new();
2014 let mut payload = 200_000u32.to_be_bytes().to_vec();
2015 payload[0] &= 0x7f; c.handle_read(
2017 &frame_bytes(FrameKind::WindowUpdate, 0x00, id, &payload),
2018 &mut events,
2019 );
2020 assert_eq!(c.send_data(id, &[0u8; 100], false), 0, "conn window empty");
2021
2022 let conn_payload = {
2024 let mut p = (65_535u32 + 200_000).to_be_bytes().to_vec();
2025 p[0] &= 0x7f;
2026 p
2027 };
2028 c.handle_read(
2029 &frame_bytes(FrameKind::WindowUpdate, 0x00, 0, &conn_payload),
2030 &mut events,
2031 );
2032 let n = c.send_data(id, &[0u8; 16384], false);
2033 assert_eq!(n, 16384, "send resumes after credit");
2034 }
2035}