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 = self.recv.borrow().buffered;
182 if remaining > 0 {
183 self.replenish(remaining);
184 }
185 }
186}
187
188pub struct Response {
192 pub status: u16,
193 pub headers: HashMap<String, String>,
194 pub raw_headers: Vec<Header>,
195 body: ResponseBody,
196 trailers: Rc<RefCell<Option<HashMap<String, String>>>>,
199}
200
201impl Response {
202 pub fn into_body(self) -> ResponseBody {
205 self.body
206 }
207
208 pub async fn bytes(&mut self) -> Result<Vec<u8>, H2Error> {
210 let mut out = Vec::new();
211 while let Some(chunk) = self.body.next().await {
212 out.extend_from_slice(&chunk?);
213 }
214 Ok(out)
215 }
216
217 pub async fn text(&mut self) -> Result<String, H2Error> {
219 Ok(String::from_utf8_lossy(&self.bytes().await?).into_owned())
220 }
221
222 pub fn trailers(&self) -> Option<HashMap<String, String>> {
225 self.trailers.borrow().clone()
226 }
227}
228
229#[derive(Default, Clone)]
231pub struct ConnectOptions {
232 pub header_table_size: Option<usize>,
233 pub enable_push: Option<bool>,
234 pub initial_window_size: Option<u32>,
237 pub max_frame_size: Option<usize>,
238 pub connection_window_size: Option<u32>,
243 }
245
246struct Head {
249 status: u16,
250 headers: HashMap<String, String>,
251 raw: Vec<Header>,
252}
253
254fn collect_headers(raw: Vec<Header>) -> Head {
255 let mut headers: HashMap<String, String> = HashMap::new();
256 let mut status = 0u16;
257 for h in &raw {
258 if h.name == ":status" {
259 status = h.value.parse().unwrap_or(0);
260 continue;
261 }
262 if h.name.starts_with(':') {
263 continue;
264 }
265 match headers.get(&h.name) {
266 Some(existing) => {
267 let sep = if h.name == "cookie" { "; " } else { ", " };
268 let joined = format!("{existing}{sep}{}", h.value);
269 headers.insert(h.name.clone(), joined);
270 }
271 None => {
272 headers.insert(h.name.clone(), h.value.clone());
273 }
274 }
275 }
276 Head {
277 status,
278 headers,
279 raw,
280 }
281}
282
283struct StreamState {
284 id: u32,
285 send_window: SendWindow,
286 head_tx: Option<oneshot::Sender<Result<Head, H2Error>>>,
287 recv: Rc<RefCell<RecvState>>,
290 trailers: Rc<RefCell<Option<HashMap<String, String>>>>,
293 got_head: bool,
294 local_closed: bool,
297 remote_closed: bool,
299}
300
301impl StreamState {
302 fn new(id: u32, initial_send_window: i64) -> Self {
303 Self {
304 id,
305 send_window: SendWindow::new(initial_send_window),
306 head_tx: None,
307 recv: Rc::new(RefCell::new(RecvState::default())),
308 trailers: Rc::new(RefCell::new(None)),
309 got_head: false,
310 local_closed: false,
311 remote_closed: false,
312 }
313 }
314
315 fn receive_headers(&mut self, raw: Vec<Header>, end_stream: bool) {
316 if !self.got_head {
317 let head = collect_headers(raw);
318 if (100..200).contains(&head.status) {
322 return;
323 }
324 self.got_head = true;
325 if let Some(tx) = self.head_tx.take() {
326 let _ = tx.send(Ok(head));
327 }
328 } else {
329 *self.trailers.borrow_mut() = Some(collect_headers(raw).headers);
331 }
332 if end_stream {
333 self.end_body();
334 }
335 }
336
337 fn receive_data(&mut self, data: &[u8], end_stream: bool) {
338 let mut recv = self.recv.borrow_mut();
339 if !data.is_empty() && recv.error.is_none() && !recv.ended {
340 recv.queue.push_back(data.to_vec());
341 recv.buffered += data.len();
342 }
343 if end_stream {
344 recv.ended = true;
345 }
346 if let Some(w) = recv.waker.take() {
347 w.wake();
348 }
349 }
350
351 fn receive_reset(&mut self, error_code: u32) {
352 let code = ErrorCode::from_value(error_code).unwrap_or(ErrorCode::ProtocolError);
353 self.fail(H2Error::stream(
354 code,
355 format!("stream {} reset by peer", self.id),
356 self.id,
357 ));
358 }
359
360 fn fail(&mut self, err: H2Error) {
361 self.send_window.close();
362 if !self.got_head {
363 self.got_head = true;
364 if let Some(tx) = self.head_tx.take() {
365 let _ = tx.send(Err(err.clone()));
366 }
367 }
368 let mut recv = self.recv.borrow_mut();
372 if recv.error.is_none() {
373 recv.error = Some(err);
374 }
375 if let Some(w) = recv.waker.take() {
376 w.wake();
377 }
378 }
379
380 fn end_body(&mut self) {
381 let mut recv = self.recv.borrow_mut();
382 if !recv.ended {
383 recv.ended = true;
384 if let Some(w) = recv.waker.take() {
385 w.wake();
386 }
387 }
388 }
389}
390
391struct RemoteSettings {
394 initial_window_size: i64,
395 max_frame_size: usize,
396 #[allow(dead_code)]
397 header_table_size: usize,
398 #[allow(dead_code)]
399 enable_push: bool,
400 max_concurrent_streams: u32,
403}
404
405impl Default for RemoteSettings {
406 fn default() -> Self {
407 Self {
408 initial_window_size: SPEC_INITIAL_WINDOW,
409 max_frame_size: DEFAULT_MAX_FRAME_SIZE,
410 header_table_size: 4096,
411 enable_push: true,
412 max_concurrent_streams: u32::MAX,
413 }
414 }
415}
416
417enum HeaderBlockKind {
418 Response,
419 Push,
420}
421
422struct PendingHeaderBlock {
423 stream_id: u32,
424 kind: HeaderBlockKind,
425 end_stream: bool,
426 promised_stream_id: Option<u32>,
427 fragments: Vec<Vec<u8>>,
428 size: usize,
430}
431
432struct PingWaiter {
437 resolve: oneshot::Sender<Result<f64, H2Error>>,
438 sent_at: f64,
439}
440
441struct ConnState {
442 out_tx: Option<mpsc::UnboundedSender<Vec<u8>>>,
446 task_tx: mpsc::UnboundedSender<LocalBoxFuture<'static, ()>>,
448 encoder: HpackEncoder,
449 decoder: HpackDecoder,
450 frame_decoder: FrameDecoder,
451 streams: HashMap<u32, StreamState>,
452 next_stream_id: u32,
453 conn_send_window: SendWindow,
454 remote: RemoteSettings,
455 pending_header_block: Option<PendingHeaderBlock>,
456 pings: HashMap<[u8; 8], PingWaiter>,
457 ping_counter: u32,
458 slot_waiters: Vec<oneshot::Sender<()>>,
460 closed: bool,
461 close_error: Option<H2Error>,
462 goaway_received: bool,
463 highest_promised: u32,
464}
465
466impl ConnState {
467 fn write_raw(&self, bytes: Vec<u8>) {
468 if !self.closed {
469 if let Some(tx) = &self.out_tx {
470 let _ = tx.unbounded_send(bytes);
471 }
472 }
473 }
474
475 fn send_frame(&self, frame: Frame) {
476 self.write_raw(serialize_frame(&frame));
477 }
478
479 fn on_bytes(&mut self, chunk: &[u8]) {
480 let frames = match self.frame_decoder.push(chunk) {
481 Ok(f) => f,
482 Err(e) => {
483 self.connection_error(e);
484 return;
485 }
486 };
487 for frame in frames {
488 if let Err(e) = self.dispatch(frame) {
489 self.connection_error(e);
490 return;
491 }
492 }
493 }
494
495 fn dispatch(&mut self, frame: Frame) -> Result<(), H2Error> {
496 if self.pending_header_block.is_some() && !matches!(frame, Frame::Continuation { .. }) {
498 return Err(H2Error::new(
499 ErrorCode::ProtocolError,
500 "expected CONTINUATION frame",
501 ));
502 }
503
504 match frame {
505 Frame::Settings { ack, settings } => {
506 if ack {
507 return Ok(());
508 }
509 self.apply_remote_settings(&settings)?;
510 self.send_frame(Frame::Settings {
511 ack: true,
512 settings: Settings::default(),
513 });
514 }
515 Frame::Headers {
516 stream_id,
517 header_block_fragment,
518 end_stream,
519 end_headers,
520 ..
521 } => {
522 let size = header_block_fragment.len();
523 self.pending_header_block = Some(PendingHeaderBlock {
524 stream_id,
525 kind: HeaderBlockKind::Response,
526 end_stream,
527 promised_stream_id: None,
528 fragments: vec![header_block_fragment],
529 size,
530 });
531 self.guard_header_block_size()?;
532 if end_headers {
533 self.complete_header_block()?;
534 }
535 }
536 Frame::Continuation {
537 stream_id,
538 header_block_fragment,
539 end_headers,
540 } => {
541 match &mut self.pending_header_block {
542 Some(pb) if pb.stream_id == stream_id => {
543 pb.size += header_block_fragment.len();
544 pb.fragments.push(header_block_fragment);
545 }
546 _ => {
547 return Err(H2Error::new(
548 ErrorCode::ProtocolError,
549 "unexpected CONTINUATION",
550 ))
551 }
552 }
553 self.guard_header_block_size()?;
554 if end_headers {
555 self.complete_header_block()?;
556 }
557 }
558 Frame::PushPromise {
559 stream_id,
560 promised_stream_id,
561 header_block_fragment,
562 end_headers,
563 } => {
564 let size = header_block_fragment.len();
565 self.pending_header_block = Some(PendingHeaderBlock {
566 stream_id,
567 kind: HeaderBlockKind::Push,
568 end_stream: false,
569 promised_stream_id: Some(promised_stream_id),
570 fragments: vec![header_block_fragment],
571 size,
572 });
573 self.guard_header_block_size()?;
574 if end_headers {
575 self.complete_header_block()?;
576 }
577 }
578 Frame::Data {
579 stream_id,
580 data,
581 end_stream,
582 } => {
583 if let Some(s) = self.streams.get_mut(&stream_id) {
584 s.receive_data(&data, end_stream);
588 if end_stream {
589 s.remote_closed = true;
590 }
591 } else if !data.is_empty() {
592 self.send_frame(Frame::WindowUpdate {
595 stream_id: 0,
596 window_size_increment: data.len() as u32,
597 });
598 }
599 if end_stream {
604 self.retire_if_fully_closed(stream_id);
605 }
606 }
607 Frame::RstStream {
608 stream_id,
609 error_code,
610 } => {
611 if let Some(mut s) = self.streams.remove(&stream_id) {
612 s.receive_reset(error_code);
613 }
614 }
615 Frame::WindowUpdate {
616 stream_id,
617 window_size_increment,
618 } => {
619 if window_size_increment == 0 {
620 if stream_id == 0 {
621 return Err(H2Error::new(ErrorCode::ProtocolError, "zero WINDOW_UPDATE"));
622 }
623 self.reset_stream(stream_id, ErrorCode::ProtocolError);
624 return Ok(());
625 }
626 if stream_id == 0 {
627 self.conn_send_window.update(window_size_increment as i64);
628 } else if let Some(s) = self.streams.get_mut(&stream_id) {
629 s.send_window.update(window_size_increment as i64);
630 }
631 }
632 Frame::Ping { ack, opaque_data } => {
633 if ack {
634 if let Some(w) = self.pings.remove(&opaque_data) {
635 let _ = w.resolve.send(Ok(now_millis() - w.sent_at));
637 }
638 } else {
639 self.send_frame(Frame::Ping {
640 ack: true,
641 opaque_data,
642 });
643 }
644 }
645 Frame::Goaway {
646 last_stream_id,
647 error_code,
648 ..
649 } => {
650 self.goaway_received = true;
651 let code = ErrorCode::from_value(error_code).unwrap_or(ErrorCode::NoError);
652 let err = H2Error::new(code, "peer sent GOAWAY");
653 let doomed: Vec<u32> = self
654 .streams
655 .keys()
656 .copied()
657 .filter(|&id| id > last_stream_id)
658 .collect();
659 for id in doomed {
660 if let Some(mut s) = self.streams.remove(&id) {
661 s.fail(err.clone());
662 }
663 }
664 self.wake_slot_waiters(); if error_code != 0 {
666 self.destroy(err);
667 }
668 }
669 Frame::Priority { .. } => {} }
671 Ok(())
672 }
673
674 fn guard_header_block_size(&self) -> Result<(), H2Error> {
677 if let Some(pb) = &self.pending_header_block {
678 if pb.size > MAX_HEADER_BLOCK_SIZE {
679 return Err(H2Error::new(
680 ErrorCode::EnhanceYourCalm,
681 "header block exceeds the maximum size",
682 ));
683 }
684 }
685 Ok(())
686 }
687
688 fn complete_header_block(&mut self) -> Result<(), H2Error> {
689 let pb = self
690 .pending_header_block
691 .take()
692 .expect("header block present");
693 let block: Vec<u8> = if pb.fragments.len() == 1 {
694 pb.fragments.into_iter().next().unwrap()
695 } else {
696 pb.fragments.concat()
697 };
698 let headers = self.decoder.decode(&block)?;
699
700 match pb.kind {
701 HeaderBlockKind::Response => {
702 if let Some(s) = self.streams.get_mut(&pb.stream_id) {
703 s.receive_headers(headers, pb.end_stream);
704 if pb.end_stream {
705 s.remote_closed = true;
706 }
707 }
708 if pb.end_stream {
709 self.retire_if_fully_closed(pb.stream_id);
710 }
711 }
712 HeaderBlockKind::Push => {
713 let promised = pb.promised_stream_id.unwrap_or(0);
714 if promised > self.highest_promised {
715 self.highest_promised = promised;
716 }
717 self.send_frame(Frame::RstStream {
719 stream_id: promised,
720 error_code: ErrorCode::RefusedStream.value(),
721 });
722 }
723 }
724 Ok(())
725 }
726
727 fn apply_remote_settings(&mut self, s: &Settings) -> Result<(), H2Error> {
728 if let Some(iw) = s.initial_window_size {
729 if iw > 0x7fff_ffff {
731 return Err(H2Error::new(
732 ErrorCode::FlowControlError,
733 "SETTINGS_INITIAL_WINDOW_SIZE exceeds 2^31-1",
734 ));
735 }
736 let delta = iw as i64 - self.remote.initial_window_size;
737 self.remote.initial_window_size = iw as i64;
738 for stream in self.streams.values_mut() {
739 stream.send_window.adjust(delta);
740 }
741 }
742 if let Some(mfs) = s.max_frame_size {
743 if !(16384..=16_777_215).contains(&mfs) {
745 return Err(H2Error::new(
746 ErrorCode::ProtocolError,
747 "SETTINGS_MAX_FRAME_SIZE out of range",
748 ));
749 }
750 self.remote.max_frame_size = mfs as usize;
751 }
752 if let Some(hts) = s.header_table_size {
753 self.remote.header_table_size = hts as usize;
754 }
755 if let Some(ep) = s.enable_push {
756 self.remote.enable_push = ep;
757 }
758 if let Some(mcs) = s.max_concurrent_streams {
759 self.remote.max_concurrent_streams = mcs;
760 self.wake_slot_waiters(); }
762 Ok(())
763 }
764
765 fn send_headers(&self, id: u32, block: Vec<u8>, end_stream: bool) {
766 let max = self.remote.max_frame_size;
767 if block.len() <= max {
768 self.send_frame(Frame::Headers {
769 stream_id: id,
770 header_block_fragment: block,
771 end_stream,
772 end_headers: true,
773 priority: None,
774 });
775 return;
776 }
777 self.send_frame(Frame::Headers {
779 stream_id: id,
780 header_block_fragment: block[..max].to_vec(),
781 end_stream,
782 end_headers: false,
783 priority: None,
784 });
785 let mut offset = max;
786 while offset < block.len() {
787 let next = (offset + max).min(block.len());
788 self.send_frame(Frame::Continuation {
789 stream_id: id,
790 header_block_fragment: block[offset..next].to_vec(),
791 end_headers: next >= block.len(),
792 });
793 offset = next;
794 }
795 }
796
797 fn reset_stream(&mut self, id: u32, code: ErrorCode) {
798 self.send_frame(Frame::RstStream {
799 stream_id: id,
800 error_code: code.value(),
801 });
802 if let Some(mut s) = self.streams.remove(&id) {
805 s.fail(H2Error::stream(code, format!("stream {id} reset"), id));
806 }
807 self.wake_slot_waiters();
808 }
809
810 fn retire_if_fully_closed(&mut self, id: u32) {
815 let fully_closed = self
816 .streams
817 .get(&id)
818 .is_some_and(|s| s.local_closed && s.remote_closed);
819 if fully_closed {
820 self.streams.remove(&id);
821 self.wake_slot_waiters(); }
823 }
824
825 fn replenish_recv_window(&self, stream_id: u32, n: usize) {
830 if self.closed || n == 0 {
831 return;
832 }
833 let inc = n as u32;
834 if self.streams.contains_key(&stream_id) {
835 self.send_frame(Frame::WindowUpdate {
836 stream_id,
837 window_size_increment: inc,
838 });
839 }
840 self.send_frame(Frame::WindowUpdate {
841 stream_id: 0,
842 window_size_increment: inc,
843 });
844 }
845
846 fn active_streams(&self) -> usize {
851 self.streams.keys().filter(|id| *id % 2 == 1).count()
852 }
853
854 fn can_open_stream(&self) -> bool {
856 self.active_streams() < self.remote.max_concurrent_streams as usize
857 }
858
859 fn wake_slot_waiters(&mut self) {
861 for tx in self.slot_waiters.drain(..) {
862 let _ = tx.send(());
863 }
864 }
865
866 fn connection_error(&mut self, err: H2Error) {
867 self.send_frame(Frame::Goaway {
868 last_stream_id: self.highest_promised,
869 error_code: err.code.value(),
870 debug_data: Vec::new(),
871 });
872 self.destroy(err);
873 }
874
875 fn destroy(&mut self, err: H2Error) {
876 if self.closed {
877 return;
878 }
879 self.closed = true;
880 self.close_error = Some(err.clone());
881 self.conn_send_window.close();
882 let ids: Vec<u32> = self.streams.keys().copied().collect();
883 for id in ids {
884 if let Some(mut s) = self.streams.remove(&id) {
885 s.fail(err.clone());
886 }
887 }
888 for (_, w) in self.pings.drain() {
890 let _ = w.resolve.send(Err(err.clone()));
891 }
892 self.wake_slot_waiters(); self.out_tx = None;
896 }
897}
898
899#[derive(Clone)]
901pub struct H2Connection {
902 shared: Rc<RefCell<ConnState>>,
903}
904
905impl H2Connection {
906 pub fn is_closed(&self) -> bool {
908 self.shared.borrow().closed
909 }
910
911 pub fn active_streams(&self) -> usize {
914 self.shared.borrow().active_streams()
915 }
916
917 pub fn can_open_stream(&self) -> bool {
922 self.shared.borrow().can_open_stream()
923 }
924
925 pub async fn request(&self, mut init: RequestInit) -> Result<Response, H2Error> {
929 let body = std::mem::take(&mut init.body);
930 let has_body = !body.is_empty();
931
932 loop {
936 let rx = {
937 let mut st = self.shared.borrow_mut();
938 if st.closed {
939 return Err(st.close_error.clone().unwrap_or_else(|| {
940 H2Error::new(ErrorCode::InternalError, "connection closed")
941 }));
942 }
943 if st.goaway_received {
944 return Err(H2Error::new(
945 ErrorCode::RefusedStream,
946 "connection is going away",
947 ));
948 }
949 if st.can_open_stream() {
950 None
951 } else {
952 let (tx, rx) = oneshot::channel();
953 st.slot_waiters.push(tx);
954 Some(rx)
955 }
956 };
957 match rx {
958 None => break,
959 Some(rx) => {
960 let _ = rx.await;
961 }
962 }
963 }
964
965 let id;
966 let head_rx;
967 let recv;
968 let task_tx;
969 let trailers;
970 {
971 let mut st = self.shared.borrow_mut();
972 if st.closed {
973 return Err(st.close_error.clone().unwrap_or_else(|| {
974 H2Error::new(ErrorCode::InternalError, "connection closed")
975 }));
976 }
977 if st.goaway_received {
978 return Err(H2Error::new(
979 ErrorCode::RefusedStream,
980 "connection is going away",
981 ));
982 }
983
984 id = st.next_stream_id;
985 st.next_stream_id += 2;
986
987 let (htx, hrx) = oneshot::channel();
988 let initial = st.remote.initial_window_size;
989 let mut stream = StreamState::new(id, initial);
990 stream.head_tx = Some(htx);
991 stream.local_closed = !has_body;
993 trailers = stream.trailers.clone();
994 recv = stream.recv.clone(); st.streams.insert(id, stream);
996 head_rx = hrx;
997
998 let headers = build_request_headers(&init);
999 let block = st.encoder.encode(&headers);
1000 st.send_headers(id, block, !has_body);
1001 task_tx = st.task_tx.clone();
1002 }
1003
1004 if has_body {
1008 let pump = pump_body(self.shared.clone(), id, body);
1009 let _ = task_tx.unbounded_send(pump.boxed_local());
1010 }
1011
1012 match head_rx.await {
1013 Ok(Ok(head)) => Ok(Response {
1014 status: head.status,
1015 headers: head.headers,
1016 raw_headers: head.raw,
1017 body: ResponseBody {
1018 recv,
1019 conn: Rc::downgrade(&self.shared),
1020 stream_id: id,
1021 },
1022 trailers,
1023 }),
1024 Ok(Err(e)) => Err(e),
1025 Err(_canceled) => Err(self
1026 .shared
1027 .borrow()
1028 .close_error
1029 .clone()
1030 .unwrap_or_else(|| H2Error::new(ErrorCode::InternalError, "connection closed"))),
1031 }
1032 }
1033
1034 pub async fn ping(&self) -> Result<f64, H2Error> {
1036 let rx = {
1037 let mut st = self.shared.borrow_mut();
1038 if st.closed {
1039 return Err(st.close_error.clone().unwrap_or_else(|| {
1040 H2Error::new(ErrorCode::InternalError, "connection closed")
1041 }));
1042 }
1043 st.ping_counter = st.ping_counter.wrapping_add(1);
1044 let mut opaque = [0u8; 8];
1045 opaque[4..8].copy_from_slice(&st.ping_counter.to_be_bytes());
1046 let (tx, rx) = oneshot::channel();
1047 st.pings.insert(
1048 opaque,
1049 PingWaiter {
1050 resolve: tx,
1051 sent_at: now_millis(),
1052 },
1053 );
1054 st.send_frame(Frame::Ping {
1055 ack: false,
1056 opaque_data: opaque,
1057 });
1058 rx
1059 };
1060 match rx.await {
1063 Ok(res) => res,
1064 Err(_canceled) => Err(H2Error::new(ErrorCode::InternalError, "connection closed")),
1065 }
1066 }
1067
1068 pub fn close(&self) {
1070 let mut st = self.shared.borrow_mut();
1071 if st.closed {
1072 return;
1073 }
1074 st.send_frame(Frame::Goaway {
1075 last_stream_id: st.highest_promised,
1076 error_code: 0,
1077 debug_data: Vec::new(),
1078 });
1079 st.destroy(H2Error::new(
1080 ErrorCode::NoError,
1081 "connection closed by client",
1082 ));
1083 }
1084}
1085
1086async fn pump_body(shared: Rc<RefCell<ConnState>>, id: u32, body: RequestBody) {
1091 let mut chunks: LocalBoxStream<'static, Vec<u8>> = match body {
1092 RequestBody::Empty => return,
1093 RequestBody::Bytes(bytes) => stream::once(async move { bytes }).boxed_local(),
1094 RequestBody::Stream(s) => s,
1095 };
1096 while let Some(chunk) = chunks.next().await {
1097 if chunk.is_empty() {
1098 continue;
1099 }
1100 if !pump_chunk(&shared, id, &chunk).await {
1101 return; }
1103 }
1104 let mut st = shared.borrow_mut();
1105 if st.streams.contains_key(&id) {
1108 st.send_frame(Frame::Data {
1109 stream_id: id,
1110 data: Vec::new(),
1111 end_stream: true,
1112 });
1113 if let Some(s) = st.streams.get_mut(&id) {
1114 s.local_closed = true;
1115 }
1116 st.retire_if_fully_closed(id);
1118 }
1119}
1120
1121async fn pump_chunk(shared: &Rc<RefCell<ConnState>>, id: u32, chunk: &[u8]) -> bool {
1125 let mut offset = 0;
1126 while offset < chunk.len() {
1127 let alive = poll_fn(|cx| {
1129 let mut st = shared.borrow_mut();
1130 if st.closed || !st.streams.contains_key(&id) {
1131 return Poll::Ready(false);
1132 }
1133 let conn_ready = st.conn_send_window.is_ready();
1134 let stream_ready = st
1135 .streams
1136 .get(&id)
1137 .map(|s| s.send_window.is_ready())
1138 .unwrap_or(false);
1139 if conn_ready && stream_ready {
1140 Poll::Ready(true)
1141 } else {
1142 if !conn_ready {
1143 st.conn_send_window.register_waker(cx.waker());
1144 }
1145 if !stream_ready {
1146 if let Some(s) = st.streams.get_mut(&id) {
1147 s.send_window.register_waker(cx.waker());
1148 }
1149 }
1150 Poll::Pending
1151 }
1152 })
1153 .await;
1154 if !alive {
1155 return false;
1156 }
1157
1158 let mut st = shared.borrow_mut();
1159 if st.closed
1160 || st
1161 .streams
1162 .get(&id)
1163 .map(|s| s.send_window.is_closed())
1164 .unwrap_or(true)
1165 {
1166 return false;
1167 }
1168 let conn_w = st.conn_send_window.value();
1169 let stream_w = st.streams.get(&id).unwrap().send_window.value();
1170 let max = st.remote.max_frame_size as i64;
1171 let remaining = (chunk.len() - offset) as i64;
1172 let grant = remaining.min(conn_w).min(stream_w).min(max);
1173 if grant <= 0 {
1174 continue; }
1176 st.conn_send_window.consume(grant);
1177 st.streams.get_mut(&id).unwrap().send_window.consume(grant);
1178 let slice = chunk[offset..offset + grant as usize].to_vec();
1179 st.send_frame(Frame::Data {
1180 stream_id: id,
1181 data: slice,
1182 end_stream: false,
1183 });
1184 offset += grant as usize;
1185 }
1186 true
1187}
1188
1189#[cfg(target_arch = "wasm32")]
1194fn now_millis() -> f64 {
1195 js_sys::Date::now()
1196}
1197
1198#[cfg(not(target_arch = "wasm32"))]
1199fn now_millis() -> f64 {
1200 use std::time::{SystemTime, UNIX_EPOCH};
1201 SystemTime::now()
1202 .duration_since(UNIX_EPOCH)
1203 .map(|d| d.as_secs_f64() * 1000.0)
1204 .unwrap_or(0.0)
1205}
1206
1207fn build_request_headers(init: &RequestInit) -> Vec<Header> {
1208 let method = init
1209 .method
1210 .clone()
1211 .unwrap_or_else(|| "GET".into())
1212 .to_uppercase();
1213 let scheme = init.scheme.clone().unwrap_or_else(|| "http".into());
1214 let path = init.path.clone().unwrap_or_else(|| "/".into());
1215
1216 let mut headers = vec![
1217 Header::new(":method", method),
1218 Header::new(":scheme", scheme),
1219 ];
1220 if let Some(auth) = &init.authority {
1221 headers.push(Header::new(":authority", auth.clone()));
1222 }
1223 headers.push(Header::new(":path", path));
1224
1225 for (raw_name, value) in &init.headers {
1226 let name = raw_name.to_ascii_lowercase();
1227 if name.starts_with(':') || FORBIDDEN_HEADERS.contains(&name.as_str()) {
1228 continue;
1229 }
1230 if name == "authorization" || name == "cookie" {
1231 headers.push(Header::never_indexed(name, value.clone()));
1232 } else {
1233 headers.push(Header::new(name, value.clone()));
1234 }
1235 }
1236 headers
1237}
1238
1239pub fn connect(
1246 transport: Transport,
1247 options: ConnectOptions,
1248) -> (H2Connection, impl Future<Output = ()>) {
1249 let (out_tx, out_rx) = mpsc::unbounded();
1250 let (task_tx, task_rx) = mpsc::unbounded();
1251
1252 let local_max_frame_size = options.max_frame_size.unwrap_or(DEFAULT_MAX_FRAME_SIZE);
1253 let local_initial_window = options.initial_window_size.unwrap_or(1024 * 1024);
1254 let conn_recv_window = options.connection_window_size.unwrap_or(64 * 1024 * 1024);
1255 let header_table_size = options.header_table_size.unwrap_or(4096);
1256 let enable_push = options.enable_push.unwrap_or(true);
1257
1258 let state = ConnState {
1259 out_tx: Some(out_tx),
1260 task_tx,
1261 encoder: HpackEncoder::new(),
1262 decoder: HpackDecoder::new(header_table_size),
1263 frame_decoder: FrameDecoder::new(local_max_frame_size),
1264 streams: HashMap::new(),
1265 next_stream_id: 1,
1266 conn_send_window: SendWindow::new(SPEC_INITIAL_WINDOW),
1267 remote: RemoteSettings::default(),
1268 pending_header_block: None,
1269 pings: HashMap::new(),
1270 ping_counter: 0,
1271 slot_waiters: Vec::new(),
1272 closed: false,
1273 close_error: None,
1274 goaway_received: false,
1275 highest_promised: 0,
1276 };
1277 let shared = Rc::new(RefCell::new(state));
1278
1279 {
1281 let st = shared.borrow();
1282 st.write_raw(CONNECTION_PREFACE.to_vec());
1283 st.send_frame(Frame::Settings {
1284 ack: false,
1285 settings: Settings {
1286 header_table_size: Some(header_table_size as u32),
1287 enable_push: Some(enable_push),
1288 initial_window_size: Some(local_initial_window),
1289 max_frame_size: Some(local_max_frame_size as u32),
1290 ..Default::default()
1291 },
1292 });
1293 let grow = conn_recv_window as i64 - SPEC_INITIAL_WINDOW;
1297 if grow > 0 {
1298 st.send_frame(Frame::WindowUpdate {
1299 stream_id: 0,
1300 window_size_increment: grow as u32,
1301 });
1302 }
1303 }
1304
1305 let driver = drive(
1306 shared.clone(),
1307 transport.reader,
1308 transport.writer,
1309 out_rx,
1310 task_rx,
1311 );
1312 (H2Connection { shared }, driver)
1313}
1314
1315async fn drive(
1316 shared: Rc<RefCell<ConnState>>,
1317 mut reader: crate::transport::ByteStream,
1318 mut writer: crate::transport::ByteSink,
1319 mut out_rx: mpsc::UnboundedReceiver<Vec<u8>>,
1320 task_rx: mpsc::UnboundedReceiver<LocalBoxFuture<'static, ()>>,
1321) {
1322 let read = {
1323 let shared = shared.clone();
1324 async move {
1325 while let Some(chunk) = reader.next().await {
1326 if !chunk.is_empty() {
1327 shared.borrow_mut().on_bytes(&chunk);
1328 }
1329 if shared.borrow().closed {
1330 break;
1331 }
1332 }
1333 shared
1334 .borrow_mut()
1335 .destroy(H2Error::new(ErrorCode::NoError, "transport closed by peer"));
1336 }
1337 };
1338
1339 let write = async move {
1340 while let Some(bytes) = out_rx.next().await {
1341 if writer.send(bytes).await.is_err() {
1342 shared.borrow_mut().destroy(H2Error::new(
1343 ErrorCode::InternalError,
1344 "transport write failed",
1345 ));
1346 break;
1347 }
1348 }
1349 };
1350
1351 let tasks = run_tasks(task_rx);
1354
1355 let read = read.fuse();
1361 let tasks = tasks.fuse();
1362 let write = write.fuse();
1363 futures::pin_mut!(read, write, tasks);
1364 futures::future::poll_fn(|cx| {
1365 let _ = read.as_mut().poll(cx);
1366 let _ = tasks.as_mut().poll(cx);
1367 write.as_mut().poll(cx)
1368 })
1369 .await;
1370}
1371
1372async fn run_tasks(mut task_rx: mpsc::UnboundedReceiver<LocalBoxFuture<'static, ()>>) {
1375 let mut pending: FuturesUnordered<LocalBoxFuture<'static, ()>> = FuturesUnordered::new();
1376 poll_fn(move |cx| {
1377 while let Poll::Ready(Some(task)) = task_rx.poll_next_unpin(cx) {
1379 pending.push(task);
1380 }
1381 while let Poll::Ready(Some(())) = pending.poll_next_unpin(cx) {}
1383 Poll::Pending
1384 })
1385 .await
1386}