1use std::cell::RefCell;
16use std::collections::{HashMap, VecDeque};
17use std::future::Future;
18use std::pin::Pin;
19use std::rc::{Rc, Weak};
20use std::task::{Context, Poll, Waker};
21
22use futures::channel::{mpsc, oneshot};
23use futures::future::{poll_fn, LocalBoxFuture};
24use futures::stream::{self, FuturesUnordered, LocalBoxStream};
25use futures::{FutureExt, SinkExt, Stream, StreamExt};
26
27use crate::errors::{ErrorCode, H2Error};
28use crate::flow::SendWindow;
29use crate::frames::{serialize_frame, Frame, FrameDecoder, Settings, DEFAULT_MAX_FRAME_SIZE};
30use crate::hpack::{Header, HpackDecoder, HpackEncoder};
31use crate::transport::Transport;
32
33const CONNECTION_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
34const SPEC_INITIAL_WINDOW: i64 = 65535;
35const MAX_HEADER_BLOCK_SIZE: usize = 1 << 20; const FORBIDDEN_HEADERS: [&str; 6] = [
39 "connection",
40 "host",
41 "keep-alive",
42 "proxy-connection",
43 "transfer-encoding",
44 "upgrade",
45];
46
47#[derive(Default)]
51pub struct RequestInit {
52 pub method: Option<String>,
53 pub path: Option<String>,
54 pub authority: Option<String>,
55 pub scheme: Option<String>,
56 pub headers: Vec<(String, String)>,
57 pub body: RequestBody,
60}
61
62#[derive(Default)]
67pub enum RequestBody {
68 #[default]
70 Empty,
71 Bytes(Vec<u8>),
73 Stream(LocalBoxStream<'static, Vec<u8>>),
75}
76
77impl RequestBody {
78 pub fn stream<S>(chunks: S) -> Self
80 where
81 S: Stream<Item = Vec<u8>> + 'static,
82 {
83 RequestBody::Stream(chunks.boxed_local())
84 }
85
86 fn is_empty(&self) -> bool {
89 match self {
90 RequestBody::Empty => true,
91 RequestBody::Bytes(b) => b.is_empty(),
92 RequestBody::Stream(_) => false,
93 }
94 }
95}
96
97impl From<Vec<u8>> for RequestBody {
98 fn from(v: Vec<u8>) -> Self {
99 RequestBody::Bytes(v)
100 }
101}
102impl From<&[u8]> for RequestBody {
103 fn from(v: &[u8]) -> Self {
104 RequestBody::Bytes(v.to_vec())
105 }
106}
107impl From<String> for RequestBody {
108 fn from(v: String) -> Self {
109 RequestBody::Bytes(v.into_bytes())
110 }
111}
112impl From<&str> for RequestBody {
113 fn from(v: &str) -> Self {
114 RequestBody::Bytes(v.as_bytes().to_vec())
115 }
116}
117
118#[derive(Default)]
123struct RecvState {
124 queue: VecDeque<Vec<u8>>,
125 buffered: usize,
128 ended: bool,
129 error: Option<H2Error>,
130 waker: Option<Waker>,
131}
132
133pub struct ResponseBody {
137 recv: Rc<RefCell<RecvState>>,
138 conn: Weak<RefCell<ConnState>>,
139 stream_id: u32,
140}
141
142impl ResponseBody {
143 fn replenish(&self, n: usize) {
145 if n == 0 {
146 return;
147 }
148 if let Some(conn) = self.conn.upgrade() {
149 conn.borrow().replenish_recv_window(self.stream_id, n);
150 }
151 }
152}
153
154impl Stream for ResponseBody {
155 type Item = Result<Vec<u8>, H2Error>;
156
157 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
158 let this = self.get_mut();
159 let mut recv = this.recv.borrow_mut();
160 if let Some(chunk) = recv.queue.pop_front() {
161 let n = chunk.len();
162 recv.buffered -= n;
163 drop(recv); this.replenish(n); Poll::Ready(Some(Ok(chunk)))
166 } else if let Some(e) = recv.error.take() {
167 Poll::Ready(Some(Err(e)))
168 } else if recv.ended {
169 Poll::Ready(None)
170 } else {
171 recv.waker = Some(cx.waker().clone());
172 Poll::Pending
173 }
174 }
175}
176
177impl Drop for ResponseBody {
178 fn drop(&mut self) {
179 let (remaining, still_open) = {
180 let recv = self.recv.borrow();
181 (recv.buffered, !recv.ended)
182 };
183 if remaining > 0 {
186 self.replenish(remaining);
187 }
188 if still_open {
195 if let Some(conn) = self.conn.upgrade() {
196 conn.borrow_mut().reset_stream(self.stream_id, ErrorCode::Cancel);
197 }
198 }
199 }
200}
201
202pub struct Response {
206 pub status: u16,
207 pub headers: HashMap<String, String>,
208 pub raw_headers: Vec<Header>,
209 body: ResponseBody,
210 trailers: Rc<RefCell<Option<HashMap<String, String>>>>,
213}
214
215impl Response {
216 pub fn into_body(self) -> ResponseBody {
219 self.body
220 }
221
222 pub async fn bytes(&mut self) -> Result<Vec<u8>, H2Error> {
224 let mut out = Vec::new();
225 while let Some(chunk) = self.body.next().await {
226 out.extend_from_slice(&chunk?);
227 }
228 Ok(out)
229 }
230
231 pub async fn text(&mut self) -> Result<String, H2Error> {
233 Ok(String::from_utf8_lossy(&self.bytes().await?).into_owned())
234 }
235
236 pub fn trailers(&self) -> Option<HashMap<String, String>> {
239 self.trailers.borrow().clone()
240 }
241
242 pub fn into_parts(self) -> (ResponseBody, Trailers) {
253 (self.body, Trailers(self.trailers))
254 }
255}
256
257#[derive(Clone)]
260pub struct Trailers(Rc<RefCell<Option<HashMap<String, String>>>>);
261
262impl Trailers {
263 pub fn get(&self) -> Option<HashMap<String, String>> {
265 self.0.borrow().clone()
266 }
267}
268
269#[derive(Default, Clone)]
271pub struct ConnectOptions {
272 pub header_table_size: Option<usize>,
273 pub enable_push: Option<bool>,
274 pub initial_window_size: Option<u32>,
277 pub max_frame_size: Option<usize>,
278 pub connection_window_size: Option<u32>,
283 }
285
286struct Head {
289 status: u16,
290 headers: HashMap<String, String>,
291 raw: Vec<Header>,
292}
293
294fn collect_headers(raw: Vec<Header>) -> Head {
295 let mut headers: HashMap<String, String> = HashMap::new();
296 let mut status = 0u16;
297 for h in &raw {
298 if h.name == ":status" {
299 status = h.value.parse().unwrap_or(0);
300 continue;
301 }
302 if h.name.starts_with(':') {
303 continue;
304 }
305 match headers.get(&h.name) {
306 Some(existing) => {
307 let sep = if h.name == "cookie" { "; " } else { ", " };
308 let joined = format!("{existing}{sep}{}", h.value);
309 headers.insert(h.name.clone(), joined);
310 }
311 None => {
312 headers.insert(h.name.clone(), h.value.clone());
313 }
314 }
315 }
316 Head {
317 status,
318 headers,
319 raw,
320 }
321}
322
323struct StreamState {
324 id: u32,
325 send_window: SendWindow,
326 head_tx: Option<oneshot::Sender<Result<Head, H2Error>>>,
327 recv: Rc<RefCell<RecvState>>,
330 trailers: Rc<RefCell<Option<HashMap<String, String>>>>,
333 got_head: bool,
334 local_closed: bool,
337 remote_closed: bool,
339}
340
341impl StreamState {
342 fn new(id: u32, initial_send_window: i64) -> Self {
343 Self {
344 id,
345 send_window: SendWindow::new(initial_send_window),
346 head_tx: None,
347 recv: Rc::new(RefCell::new(RecvState::default())),
348 trailers: Rc::new(RefCell::new(None)),
349 got_head: false,
350 local_closed: false,
351 remote_closed: false,
352 }
353 }
354
355 fn receive_headers(&mut self, raw: Vec<Header>, end_stream: bool) {
356 if !self.got_head {
357 let head = collect_headers(raw);
358 if (100..200).contains(&head.status) {
362 return;
363 }
364 self.got_head = true;
365 if let Some(tx) = self.head_tx.take() {
366 let _ = tx.send(Ok(head));
367 }
368 } else {
369 *self.trailers.borrow_mut() = Some(collect_headers(raw).headers);
371 }
372 if end_stream {
373 self.end_body();
374 }
375 }
376
377 fn receive_data(&mut self, data: &[u8], end_stream: bool) {
378 let mut recv = self.recv.borrow_mut();
379 if !data.is_empty() && recv.error.is_none() && !recv.ended {
380 recv.queue.push_back(data.to_vec());
381 recv.buffered += data.len();
382 }
383 if end_stream {
384 recv.ended = true;
385 }
386 if let Some(w) = recv.waker.take() {
387 w.wake();
388 }
389 }
390
391 fn receive_reset(&mut self, error_code: u32) {
392 let code = ErrorCode::from_value(error_code).unwrap_or(ErrorCode::ProtocolError);
393 self.fail(H2Error::stream(
394 code,
395 format!("stream {} reset by peer", self.id),
396 self.id,
397 ));
398 }
399
400 fn fail(&mut self, err: H2Error) {
401 self.send_window.close();
402 if !self.got_head {
403 self.got_head = true;
404 if let Some(tx) = self.head_tx.take() {
405 let _ = tx.send(Err(err.clone()));
406 }
407 }
408 let mut recv = self.recv.borrow_mut();
412 if recv.error.is_none() {
413 recv.error = Some(err);
414 }
415 recv.ended = true;
420 if let Some(w) = recv.waker.take() {
421 w.wake();
422 }
423 }
424
425 fn end_body(&mut self) {
426 let mut recv = self.recv.borrow_mut();
427 if !recv.ended {
428 recv.ended = true;
429 if let Some(w) = recv.waker.take() {
430 w.wake();
431 }
432 }
433 }
434}
435
436struct RemoteSettings {
439 initial_window_size: i64,
440 max_frame_size: usize,
441 #[allow(dead_code)]
442 header_table_size: usize,
443 #[allow(dead_code)]
444 enable_push: bool,
445 max_concurrent_streams: u32,
448}
449
450impl Default for RemoteSettings {
451 fn default() -> Self {
452 Self {
453 initial_window_size: SPEC_INITIAL_WINDOW,
454 max_frame_size: DEFAULT_MAX_FRAME_SIZE,
455 header_table_size: 4096,
456 enable_push: true,
457 max_concurrent_streams: u32::MAX,
458 }
459 }
460}
461
462enum HeaderBlockKind {
463 Response,
464 Push,
465}
466
467struct PendingHeaderBlock {
468 stream_id: u32,
469 kind: HeaderBlockKind,
470 end_stream: bool,
471 promised_stream_id: Option<u32>,
472 fragments: Vec<Vec<u8>>,
473 size: usize,
475}
476
477struct PingWaiter {
482 resolve: oneshot::Sender<Result<f64, H2Error>>,
483 sent_at: f64,
484}
485
486struct ConnState {
487 out_tx: Option<mpsc::UnboundedSender<Vec<u8>>>,
491 task_tx: mpsc::UnboundedSender<LocalBoxFuture<'static, ()>>,
493 encoder: HpackEncoder,
494 decoder: HpackDecoder,
495 frame_decoder: FrameDecoder,
496 streams: HashMap<u32, StreamState>,
497 next_stream_id: u32,
498 conn_send_window: SendWindow,
499 remote: RemoteSettings,
500 pending_header_block: Option<PendingHeaderBlock>,
501 pings: HashMap<[u8; 8], PingWaiter>,
502 ping_counter: u32,
503 slot_waiters: Vec<oneshot::Sender<()>>,
505 closed: bool,
506 close_error: Option<H2Error>,
507 goaway_received: bool,
508 highest_promised: u32,
509}
510
511impl ConnState {
512 fn write_raw(&self, bytes: Vec<u8>) {
513 if !self.closed {
514 if let Some(tx) = &self.out_tx {
515 let _ = tx.unbounded_send(bytes);
516 }
517 }
518 }
519
520 fn send_frame(&self, frame: Frame) {
521 self.write_raw(serialize_frame(&frame));
522 }
523
524 fn on_bytes(&mut self, chunk: &[u8]) {
525 let frames = match self.frame_decoder.push(chunk) {
526 Ok(f) => f,
527 Err(e) => {
528 self.connection_error(e);
529 return;
530 }
531 };
532 for frame in frames {
533 if let Err(e) = self.dispatch(frame) {
534 self.connection_error(e);
535 return;
536 }
537 }
538 }
539
540 fn dispatch(&mut self, frame: Frame) -> Result<(), H2Error> {
541 if self.pending_header_block.is_some() && !matches!(frame, Frame::Continuation { .. }) {
543 return Err(H2Error::new(
544 ErrorCode::ProtocolError,
545 "expected CONTINUATION frame",
546 ));
547 }
548
549 match frame {
550 Frame::Settings { ack, settings } => {
551 if ack {
552 return Ok(());
553 }
554 self.apply_remote_settings(&settings)?;
555 self.send_frame(Frame::Settings {
556 ack: true,
557 settings: Settings::default(),
558 });
559 }
560 Frame::Headers {
561 stream_id,
562 header_block_fragment,
563 end_stream,
564 end_headers,
565 ..
566 } => {
567 let size = header_block_fragment.len();
568 self.pending_header_block = Some(PendingHeaderBlock {
569 stream_id,
570 kind: HeaderBlockKind::Response,
571 end_stream,
572 promised_stream_id: None,
573 fragments: vec![header_block_fragment],
574 size,
575 });
576 self.guard_header_block_size()?;
577 if end_headers {
578 self.complete_header_block()?;
579 }
580 }
581 Frame::Continuation {
582 stream_id,
583 header_block_fragment,
584 end_headers,
585 } => {
586 match &mut self.pending_header_block {
587 Some(pb) if pb.stream_id == stream_id => {
588 pb.size += header_block_fragment.len();
589 pb.fragments.push(header_block_fragment);
590 }
591 _ => {
592 return Err(H2Error::new(
593 ErrorCode::ProtocolError,
594 "unexpected CONTINUATION",
595 ))
596 }
597 }
598 self.guard_header_block_size()?;
599 if end_headers {
600 self.complete_header_block()?;
601 }
602 }
603 Frame::PushPromise {
604 stream_id,
605 promised_stream_id,
606 header_block_fragment,
607 end_headers,
608 } => {
609 let size = header_block_fragment.len();
610 self.pending_header_block = Some(PendingHeaderBlock {
611 stream_id,
612 kind: HeaderBlockKind::Push,
613 end_stream: false,
614 promised_stream_id: Some(promised_stream_id),
615 fragments: vec![header_block_fragment],
616 size,
617 });
618 self.guard_header_block_size()?;
619 if end_headers {
620 self.complete_header_block()?;
621 }
622 }
623 Frame::Data {
624 stream_id,
625 data,
626 end_stream,
627 } => {
628 if let Some(s) = self.streams.get_mut(&stream_id) {
629 s.receive_data(&data, end_stream);
633 if end_stream {
634 s.remote_closed = true;
635 }
636 } else if !data.is_empty() {
637 self.send_frame(Frame::WindowUpdate {
640 stream_id: 0,
641 window_size_increment: data.len() as u32,
642 });
643 }
644 if end_stream {
649 self.retire_if_fully_closed(stream_id);
650 }
651 }
652 Frame::RstStream {
653 stream_id,
654 error_code,
655 } => {
656 if let Some(mut s) = self.streams.remove(&stream_id) {
657 s.receive_reset(error_code);
658 }
659 }
660 Frame::WindowUpdate {
661 stream_id,
662 window_size_increment,
663 } => {
664 if window_size_increment == 0 {
665 if stream_id == 0 {
666 return Err(H2Error::new(ErrorCode::ProtocolError, "zero WINDOW_UPDATE"));
667 }
668 self.reset_stream(stream_id, ErrorCode::ProtocolError);
669 return Ok(());
670 }
671 if stream_id == 0 {
672 self.conn_send_window.update(window_size_increment as i64);
673 } else if let Some(s) = self.streams.get_mut(&stream_id) {
674 s.send_window.update(window_size_increment as i64);
675 }
676 }
677 Frame::Ping { ack, opaque_data } => {
678 if ack {
679 if let Some(w) = self.pings.remove(&opaque_data) {
680 let _ = w.resolve.send(Ok(now_millis() - w.sent_at));
682 }
683 } else {
684 self.send_frame(Frame::Ping {
685 ack: true,
686 opaque_data,
687 });
688 }
689 }
690 Frame::Goaway {
691 last_stream_id,
692 error_code,
693 ..
694 } => {
695 self.goaway_received = true;
696 let code = ErrorCode::from_value(error_code).unwrap_or(ErrorCode::NoError);
697 let err = H2Error::new(code, "peer sent GOAWAY");
698 let doomed: Vec<u32> = self
699 .streams
700 .keys()
701 .copied()
702 .filter(|&id| id > last_stream_id)
703 .collect();
704 for id in doomed {
705 if let Some(mut s) = self.streams.remove(&id) {
706 s.fail(err.clone());
707 }
708 }
709 self.wake_slot_waiters(); if error_code != 0 {
711 self.destroy(err);
712 }
713 }
714 Frame::Priority { .. } => {} }
716 Ok(())
717 }
718
719 fn guard_header_block_size(&self) -> Result<(), H2Error> {
722 if let Some(pb) = &self.pending_header_block {
723 if pb.size > MAX_HEADER_BLOCK_SIZE {
724 return Err(H2Error::new(
725 ErrorCode::EnhanceYourCalm,
726 "header block exceeds the maximum size",
727 ));
728 }
729 }
730 Ok(())
731 }
732
733 fn complete_header_block(&mut self) -> Result<(), H2Error> {
734 let pb = self
735 .pending_header_block
736 .take()
737 .expect("header block present");
738 let block: Vec<u8> = if pb.fragments.len() == 1 {
739 pb.fragments.into_iter().next().unwrap()
740 } else {
741 pb.fragments.concat()
742 };
743 let headers = self.decoder.decode(&block)?;
744
745 match pb.kind {
746 HeaderBlockKind::Response => {
747 if let Some(s) = self.streams.get_mut(&pb.stream_id) {
748 s.receive_headers(headers, pb.end_stream);
749 if pb.end_stream {
750 s.remote_closed = true;
751 }
752 }
753 if pb.end_stream {
754 self.retire_if_fully_closed(pb.stream_id);
755 }
756 }
757 HeaderBlockKind::Push => {
758 let promised = pb.promised_stream_id.unwrap_or(0);
759 if promised > self.highest_promised {
760 self.highest_promised = promised;
761 }
762 self.send_frame(Frame::RstStream {
764 stream_id: promised,
765 error_code: ErrorCode::RefusedStream.value(),
766 });
767 }
768 }
769 Ok(())
770 }
771
772 fn apply_remote_settings(&mut self, s: &Settings) -> Result<(), H2Error> {
773 if let Some(iw) = s.initial_window_size {
774 if iw > 0x7fff_ffff {
776 return Err(H2Error::new(
777 ErrorCode::FlowControlError,
778 "SETTINGS_INITIAL_WINDOW_SIZE exceeds 2^31-1",
779 ));
780 }
781 let delta = iw as i64 - self.remote.initial_window_size;
782 self.remote.initial_window_size = iw as i64;
783 for stream in self.streams.values_mut() {
784 stream.send_window.adjust(delta);
785 }
786 }
787 if let Some(mfs) = s.max_frame_size {
788 if !(16384..=16_777_215).contains(&mfs) {
790 return Err(H2Error::new(
791 ErrorCode::ProtocolError,
792 "SETTINGS_MAX_FRAME_SIZE out of range",
793 ));
794 }
795 self.remote.max_frame_size = mfs as usize;
796 }
797 if let Some(hts) = s.header_table_size {
798 self.remote.header_table_size = hts as usize;
799 }
800 if let Some(ep) = s.enable_push {
801 self.remote.enable_push = ep;
802 }
803 if let Some(mcs) = s.max_concurrent_streams {
804 self.remote.max_concurrent_streams = mcs;
805 self.wake_slot_waiters(); }
807 Ok(())
808 }
809
810 fn send_headers(&self, id: u32, block: Vec<u8>, end_stream: bool) {
811 let max = self.remote.max_frame_size;
812 if block.len() <= max {
813 self.send_frame(Frame::Headers {
814 stream_id: id,
815 header_block_fragment: block,
816 end_stream,
817 end_headers: true,
818 priority: None,
819 });
820 return;
821 }
822 self.send_frame(Frame::Headers {
824 stream_id: id,
825 header_block_fragment: block[..max].to_vec(),
826 end_stream,
827 end_headers: false,
828 priority: None,
829 });
830 let mut offset = max;
831 while offset < block.len() {
832 let next = (offset + max).min(block.len());
833 self.send_frame(Frame::Continuation {
834 stream_id: id,
835 header_block_fragment: block[offset..next].to_vec(),
836 end_headers: next >= block.len(),
837 });
838 offset = next;
839 }
840 }
841
842 fn reset_stream(&mut self, id: u32, code: ErrorCode) {
843 self.send_frame(Frame::RstStream {
844 stream_id: id,
845 error_code: code.value(),
846 });
847 if let Some(mut s) = self.streams.remove(&id) {
850 s.fail(H2Error::stream(code, format!("stream {id} reset"), id));
851 }
852 self.wake_slot_waiters();
853 }
854
855 fn retire_if_fully_closed(&mut self, id: u32) {
860 let fully_closed = self
861 .streams
862 .get(&id)
863 .is_some_and(|s| s.local_closed && s.remote_closed);
864 if fully_closed {
865 self.streams.remove(&id);
866 self.wake_slot_waiters(); }
868 }
869
870 fn replenish_recv_window(&self, stream_id: u32, n: usize) {
875 if self.closed || n == 0 {
876 return;
877 }
878 let inc = n as u32;
879 if self.streams.contains_key(&stream_id) {
880 self.send_frame(Frame::WindowUpdate {
881 stream_id,
882 window_size_increment: inc,
883 });
884 }
885 self.send_frame(Frame::WindowUpdate {
886 stream_id: 0,
887 window_size_increment: inc,
888 });
889 }
890
891 fn active_streams(&self) -> usize {
896 self.streams.keys().filter(|id| *id % 2 == 1).count()
897 }
898
899 fn can_open_stream(&self) -> bool {
901 self.active_streams() < self.remote.max_concurrent_streams as usize
902 }
903
904 fn wake_slot_waiters(&mut self) {
906 for tx in self.slot_waiters.drain(..) {
907 let _ = tx.send(());
908 }
909 }
910
911 fn connection_error(&mut self, err: H2Error) {
912 self.send_frame(Frame::Goaway {
913 last_stream_id: self.highest_promised,
914 error_code: err.code.value(),
915 debug_data: Vec::new(),
916 });
917 self.destroy(err);
918 }
919
920 fn destroy(&mut self, err: H2Error) {
921 if self.closed {
922 return;
923 }
924 self.closed = true;
925 self.close_error = Some(err.clone());
926 self.conn_send_window.close();
927 let ids: Vec<u32> = self.streams.keys().copied().collect();
928 for id in ids {
929 if let Some(mut s) = self.streams.remove(&id) {
930 s.fail(err.clone());
931 }
932 }
933 for (_, w) in self.pings.drain() {
935 let _ = w.resolve.send(Err(err.clone()));
936 }
937 self.wake_slot_waiters(); self.out_tx = None;
941 }
942}
943
944#[derive(Clone)]
946pub struct H2Connection {
947 shared: Rc<RefCell<ConnState>>,
948}
949
950impl H2Connection {
951 pub fn is_closed(&self) -> bool {
953 self.shared.borrow().closed
954 }
955
956 pub fn active_streams(&self) -> usize {
959 self.shared.borrow().active_streams()
960 }
961
962 pub fn can_open_stream(&self) -> bool {
967 self.shared.borrow().can_open_stream()
968 }
969
970 pub async fn request(&self, mut init: RequestInit) -> Result<Response, H2Error> {
974 let body = std::mem::take(&mut init.body);
975 let has_body = !body.is_empty();
976
977 loop {
981 let rx = {
982 let mut st = self.shared.borrow_mut();
983 if st.closed {
984 return Err(st.close_error.clone().unwrap_or_else(|| {
985 H2Error::new(ErrorCode::InternalError, "connection closed")
986 }));
987 }
988 if st.goaway_received {
989 return Err(H2Error::new(
990 ErrorCode::RefusedStream,
991 "connection is going away",
992 ));
993 }
994 if st.can_open_stream() {
995 None
996 } else {
997 let (tx, rx) = oneshot::channel();
998 st.slot_waiters.push(tx);
999 Some(rx)
1000 }
1001 };
1002 match rx {
1003 None => break,
1004 Some(rx) => {
1005 let _ = rx.await;
1006 }
1007 }
1008 }
1009
1010 let id;
1011 let head_rx;
1012 let recv;
1013 let task_tx;
1014 let trailers;
1015 {
1016 let mut st = self.shared.borrow_mut();
1017 if st.closed {
1018 return Err(st.close_error.clone().unwrap_or_else(|| {
1019 H2Error::new(ErrorCode::InternalError, "connection closed")
1020 }));
1021 }
1022 if st.goaway_received {
1023 return Err(H2Error::new(
1024 ErrorCode::RefusedStream,
1025 "connection is going away",
1026 ));
1027 }
1028
1029 id = st.next_stream_id;
1030 st.next_stream_id += 2;
1031
1032 let (htx, hrx) = oneshot::channel();
1033 let initial = st.remote.initial_window_size;
1034 let mut stream = StreamState::new(id, initial);
1035 stream.head_tx = Some(htx);
1036 stream.local_closed = !has_body;
1038 trailers = stream.trailers.clone();
1039 recv = stream.recv.clone(); st.streams.insert(id, stream);
1041 head_rx = hrx;
1042
1043 let headers = build_request_headers(&init);
1044 let block = st.encoder.encode(&headers);
1045 st.send_headers(id, block, !has_body);
1046 task_tx = st.task_tx.clone();
1047 }
1048
1049 if has_body {
1053 let pump = pump_body(self.shared.clone(), id, body);
1054 let _ = task_tx.unbounded_send(pump.boxed_local());
1055 }
1056
1057 match head_rx.await {
1058 Ok(Ok(head)) => Ok(Response {
1059 status: head.status,
1060 headers: head.headers,
1061 raw_headers: head.raw,
1062 body: ResponseBody {
1063 recv,
1064 conn: Rc::downgrade(&self.shared),
1065 stream_id: id,
1066 },
1067 trailers,
1068 }),
1069 Ok(Err(e)) => Err(e),
1070 Err(_canceled) => Err(self
1071 .shared
1072 .borrow()
1073 .close_error
1074 .clone()
1075 .unwrap_or_else(|| H2Error::new(ErrorCode::InternalError, "connection closed"))),
1076 }
1077 }
1078
1079 pub async fn ping(&self) -> Result<f64, H2Error> {
1081 let rx = {
1082 let mut st = self.shared.borrow_mut();
1083 if st.closed {
1084 return Err(st.close_error.clone().unwrap_or_else(|| {
1085 H2Error::new(ErrorCode::InternalError, "connection closed")
1086 }));
1087 }
1088 st.ping_counter = st.ping_counter.wrapping_add(1);
1089 let mut opaque = [0u8; 8];
1090 opaque[4..8].copy_from_slice(&st.ping_counter.to_be_bytes());
1091 let (tx, rx) = oneshot::channel();
1092 st.pings.insert(
1093 opaque,
1094 PingWaiter {
1095 resolve: tx,
1096 sent_at: now_millis(),
1097 },
1098 );
1099 st.send_frame(Frame::Ping {
1100 ack: false,
1101 opaque_data: opaque,
1102 });
1103 rx
1104 };
1105 match rx.await {
1108 Ok(res) => res,
1109 Err(_canceled) => Err(H2Error::new(ErrorCode::InternalError, "connection closed")),
1110 }
1111 }
1112
1113 pub fn close(&self) {
1115 let mut st = self.shared.borrow_mut();
1116 if st.closed {
1117 return;
1118 }
1119 st.send_frame(Frame::Goaway {
1120 last_stream_id: st.highest_promised,
1121 error_code: 0,
1122 debug_data: Vec::new(),
1123 });
1124 st.destroy(H2Error::new(
1125 ErrorCode::NoError,
1126 "connection closed by client",
1127 ));
1128 }
1129}
1130
1131async fn pump_body(shared: Rc<RefCell<ConnState>>, id: u32, body: RequestBody) {
1136 let mut chunks: LocalBoxStream<'static, Vec<u8>> = match body {
1137 RequestBody::Empty => return,
1138 RequestBody::Bytes(bytes) => stream::once(async move { bytes }).boxed_local(),
1139 RequestBody::Stream(s) => s,
1140 };
1141 while let Some(chunk) = chunks.next().await {
1142 if chunk.is_empty() {
1143 continue;
1144 }
1145 if !pump_chunk(&shared, id, &chunk).await {
1146 return; }
1148 }
1149 let mut st = shared.borrow_mut();
1150 if st.streams.contains_key(&id) {
1153 st.send_frame(Frame::Data {
1154 stream_id: id,
1155 data: Vec::new(),
1156 end_stream: true,
1157 });
1158 if let Some(s) = st.streams.get_mut(&id) {
1159 s.local_closed = true;
1160 }
1161 st.retire_if_fully_closed(id);
1163 }
1164}
1165
1166async fn pump_chunk(shared: &Rc<RefCell<ConnState>>, id: u32, chunk: &[u8]) -> bool {
1170 let mut offset = 0;
1171 while offset < chunk.len() {
1172 let alive = poll_fn(|cx| {
1174 let mut st = shared.borrow_mut();
1175 if st.closed || !st.streams.contains_key(&id) {
1176 return Poll::Ready(false);
1177 }
1178 let conn_ready = st.conn_send_window.is_ready();
1179 let stream_ready = st
1180 .streams
1181 .get(&id)
1182 .map(|s| s.send_window.is_ready())
1183 .unwrap_or(false);
1184 if conn_ready && stream_ready {
1185 Poll::Ready(true)
1186 } else {
1187 if !conn_ready {
1188 st.conn_send_window.register_waker(cx.waker());
1189 }
1190 if !stream_ready {
1191 if let Some(s) = st.streams.get_mut(&id) {
1192 s.send_window.register_waker(cx.waker());
1193 }
1194 }
1195 Poll::Pending
1196 }
1197 })
1198 .await;
1199 if !alive {
1200 return false;
1201 }
1202
1203 let mut st = shared.borrow_mut();
1204 if st.closed
1205 || st
1206 .streams
1207 .get(&id)
1208 .map(|s| s.send_window.is_closed())
1209 .unwrap_or(true)
1210 {
1211 return false;
1212 }
1213 let conn_w = st.conn_send_window.value();
1214 let stream_w = st.streams.get(&id).unwrap().send_window.value();
1215 let max = st.remote.max_frame_size as i64;
1216 let remaining = (chunk.len() - offset) as i64;
1217 let grant = remaining.min(conn_w).min(stream_w).min(max);
1218 if grant <= 0 {
1219 continue; }
1221 st.conn_send_window.consume(grant);
1222 st.streams.get_mut(&id).unwrap().send_window.consume(grant);
1223 let slice = chunk[offset..offset + grant as usize].to_vec();
1224 st.send_frame(Frame::Data {
1225 stream_id: id,
1226 data: slice,
1227 end_stream: false,
1228 });
1229 offset += grant as usize;
1230 }
1231 true
1232}
1233
1234#[cfg(target_arch = "wasm32")]
1239fn now_millis() -> f64 {
1240 js_sys::Date::now()
1241}
1242
1243#[cfg(not(target_arch = "wasm32"))]
1244fn now_millis() -> f64 {
1245 use std::time::{SystemTime, UNIX_EPOCH};
1246 SystemTime::now()
1247 .duration_since(UNIX_EPOCH)
1248 .map(|d| d.as_secs_f64() * 1000.0)
1249 .unwrap_or(0.0)
1250}
1251
1252fn build_request_headers(init: &RequestInit) -> Vec<Header> {
1253 let method = init
1254 .method
1255 .clone()
1256 .unwrap_or_else(|| "GET".into())
1257 .to_uppercase();
1258 let scheme = init.scheme.clone().unwrap_or_else(|| "http".into());
1259 let path = init.path.clone().unwrap_or_else(|| "/".into());
1260
1261 let mut headers = vec![
1262 Header::new(":method", method),
1263 Header::new(":scheme", scheme),
1264 ];
1265 if let Some(auth) = &init.authority {
1266 headers.push(Header::new(":authority", auth.clone()));
1267 }
1268 headers.push(Header::new(":path", path));
1269
1270 for (raw_name, value) in &init.headers {
1271 let name = raw_name.to_ascii_lowercase();
1272 if name.starts_with(':') || FORBIDDEN_HEADERS.contains(&name.as_str()) {
1273 continue;
1274 }
1275 if name == "authorization" || name == "cookie" {
1276 headers.push(Header::never_indexed(name, value.clone()));
1277 } else {
1278 headers.push(Header::new(name, value.clone()));
1279 }
1280 }
1281 headers
1282}
1283
1284pub fn connect(
1291 transport: Transport,
1292 options: ConnectOptions,
1293) -> (H2Connection, impl Future<Output = ()>) {
1294 let (out_tx, out_rx) = mpsc::unbounded();
1295 let (task_tx, task_rx) = mpsc::unbounded();
1296
1297 let local_max_frame_size = options.max_frame_size.unwrap_or(DEFAULT_MAX_FRAME_SIZE);
1298 let local_initial_window = options.initial_window_size.unwrap_or(1024 * 1024);
1299 let conn_recv_window = options.connection_window_size.unwrap_or(64 * 1024 * 1024);
1300 let header_table_size = options.header_table_size.unwrap_or(4096);
1301 let enable_push = options.enable_push.unwrap_or(true);
1302
1303 let state = ConnState {
1304 out_tx: Some(out_tx),
1305 task_tx,
1306 encoder: HpackEncoder::new(),
1307 decoder: HpackDecoder::new(header_table_size),
1308 frame_decoder: FrameDecoder::new(local_max_frame_size),
1309 streams: HashMap::new(),
1310 next_stream_id: 1,
1311 conn_send_window: SendWindow::new(SPEC_INITIAL_WINDOW),
1312 remote: RemoteSettings::default(),
1313 pending_header_block: None,
1314 pings: HashMap::new(),
1315 ping_counter: 0,
1316 slot_waiters: Vec::new(),
1317 closed: false,
1318 close_error: None,
1319 goaway_received: false,
1320 highest_promised: 0,
1321 };
1322 let shared = Rc::new(RefCell::new(state));
1323
1324 {
1326 let st = shared.borrow();
1327 st.write_raw(CONNECTION_PREFACE.to_vec());
1328 st.send_frame(Frame::Settings {
1329 ack: false,
1330 settings: Settings {
1331 header_table_size: Some(header_table_size as u32),
1332 enable_push: Some(enable_push),
1333 initial_window_size: Some(local_initial_window),
1334 max_frame_size: Some(local_max_frame_size as u32),
1335 ..Default::default()
1336 },
1337 });
1338 let grow = conn_recv_window as i64 - SPEC_INITIAL_WINDOW;
1342 if grow > 0 {
1343 st.send_frame(Frame::WindowUpdate {
1344 stream_id: 0,
1345 window_size_increment: grow as u32,
1346 });
1347 }
1348 }
1349
1350 let driver = drive(
1351 shared.clone(),
1352 transport.reader,
1353 transport.writer,
1354 out_rx,
1355 task_rx,
1356 );
1357 (H2Connection { shared }, driver)
1358}
1359
1360async fn drive(
1361 shared: Rc<RefCell<ConnState>>,
1362 mut reader: crate::transport::ByteStream,
1363 mut writer: crate::transport::ByteSink,
1364 mut out_rx: mpsc::UnboundedReceiver<Vec<u8>>,
1365 task_rx: mpsc::UnboundedReceiver<LocalBoxFuture<'static, ()>>,
1366) {
1367 let read = {
1368 let shared = shared.clone();
1369 async move {
1370 while let Some(chunk) = reader.next().await {
1371 if !chunk.is_empty() {
1372 shared.borrow_mut().on_bytes(&chunk);
1373 }
1374 if shared.borrow().closed {
1375 break;
1376 }
1377 }
1378 shared
1379 .borrow_mut()
1380 .destroy(H2Error::new(ErrorCode::NoError, "transport closed by peer"));
1381 }
1382 };
1383
1384 let write = async move {
1385 while let Some(bytes) = out_rx.next().await {
1386 if writer.send(bytes).await.is_err() {
1387 shared.borrow_mut().destroy(H2Error::new(
1388 ErrorCode::InternalError,
1389 "transport write failed",
1390 ));
1391 break;
1392 }
1393 }
1394 };
1395
1396 let tasks = run_tasks(task_rx);
1399
1400 let read = read.fuse();
1406 let tasks = tasks.fuse();
1407 let write = write.fuse();
1408 futures::pin_mut!(read, write, tasks);
1409 futures::future::poll_fn(|cx| {
1410 let _ = read.as_mut().poll(cx);
1411 let _ = tasks.as_mut().poll(cx);
1412 write.as_mut().poll(cx)
1413 })
1414 .await;
1415}
1416
1417async fn run_tasks(mut task_rx: mpsc::UnboundedReceiver<LocalBoxFuture<'static, ()>>) {
1420 let mut pending: FuturesUnordered<LocalBoxFuture<'static, ()>> = FuturesUnordered::new();
1421 poll_fn(move |cx| {
1422 while let Poll::Ready(Some(task)) = task_rx.poll_next_unpin(cx) {
1424 pending.push(task);
1425 }
1426 while let Poll::Ready(Some(())) = pending.poll_next_unpin(cx) {}
1428 Poll::Pending
1429 })
1430 .await
1431}