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