1use super::{
2 store, Buffer, BufferStatus, Codec, Config, Counts, Frame, Prioritize, Prioritized, Store,
3 Stream, StreamId, StreamIdOverflow, WindowSize,
4};
5use crate::codec::UserError;
6use crate::frame::{self, Reason};
7use crate::proto::{self, Error, Initiator};
8
9use bytes::Buf;
10use tokio::io::AsyncWrite;
11
12use std::cmp::Ordering;
13use std::io;
14use std::task::{Context, Poll, Waker};
15
16#[derive(Debug)]
18pub(super) struct Send {
19 next_stream_id: Result<StreamId, StreamIdOverflow>,
21
22 max_stream_id: StreamId,
30
31 init_window_sz: WindowSize,
33
34 prioritize: Prioritize,
36
37 is_push_enabled: bool,
38
39 is_extended_connect_protocol_enabled: bool,
41}
42
43#[derive(Debug)]
45pub(crate) enum PollReset {
46 AwaitingHeaders,
47 Streaming,
48}
49
50impl Send {
51 pub fn new(config: &Config) -> Self {
53 Send {
54 init_window_sz: config.remote_init_window_sz,
55 max_stream_id: StreamId::MAX,
56 next_stream_id: Ok(config.local_next_stream_id),
57 prioritize: Prioritize::new(config),
58 is_push_enabled: true,
59 is_extended_connect_protocol_enabled: false,
60 }
61 }
62
63 pub fn init_window_sz(&self) -> WindowSize {
65 self.init_window_sz
66 }
67
68 pub fn open(&mut self) -> Result<StreamId, UserError> {
69 let stream_id = self.ensure_next_stream_id()?;
70 self.next_stream_id = stream_id.next_id();
71 Ok(stream_id)
72 }
73
74 pub fn reserve_local(&mut self) -> Result<StreamId, UserError> {
75 let stream_id = self.ensure_next_stream_id()?;
76 self.next_stream_id = stream_id.next_id();
77 Ok(stream_id)
78 }
79
80 fn check_headers(fields: &http::HeaderMap) -> Result<(), UserError> {
81 if fields.contains_key(http::header::CONNECTION)
83 || fields.contains_key(http::header::TRANSFER_ENCODING)
84 || fields.contains_key(http::header::UPGRADE)
85 || fields.contains_key("keep-alive")
86 || fields.contains_key("proxy-connection")
87 {
88 tracing::debug!("illegal connection-specific headers found");
89 return Err(UserError::MalformedHeaders);
90 } else if let Some(te) = fields.get(http::header::TE) {
91 if te != "trailers" {
92 tracing::debug!("illegal connection-specific headers found");
93 return Err(UserError::MalformedHeaders);
94 }
95 }
96 Ok(())
97 }
98
99 pub fn send_push_promise<B>(
100 &mut self,
101 frame: frame::PushPromise,
102 buffer: &mut Buffer<Frame<B>>,
103 stream: &mut store::Ptr,
104 task: &mut Option<Waker>,
105 ) -> Result<(), UserError> {
106 if !self.is_push_enabled {
107 return Err(UserError::PeerDisabledServerPush);
108 }
109
110 tracing::trace!(
111 "send_push_promise; frame={:?}; init_window={:?}",
112 frame,
113 self.init_window_sz
114 );
115
116 Self::check_headers(frame.fields())?;
117
118 self.prioritize
120 .queue_frame(frame.into(), buffer, stream, task);
121
122 Ok(())
123 }
124
125 pub fn send_headers<B>(
126 &mut self,
127 frame: frame::Headers,
128 buffer: &mut Buffer<Frame<B>>,
129 stream: &mut store::Ptr,
130 counts: &mut Counts,
131 task: &mut Option<Waker>,
132 ) -> Result<(), UserError> {
133 tracing::trace!(
134 "send_headers; frame={:?}; init_window={:?}",
135 frame,
136 self.init_window_sz
137 );
138
139 Self::check_headers(frame.fields())?;
140
141 let end_stream = frame.is_end_stream();
142
143 stream.state.send_open(end_stream)?;
145
146 let mut pending_open = false;
147 if counts.peer().is_local_init(frame.stream_id()) && !stream.is_pending_push {
148 self.prioritize.queue_open(stream);
149 pending_open = true;
150 }
151
152 self.prioritize
157 .queue_frame(frame.into(), buffer, stream, task);
158
159 if pending_open {
162 if let Some(task) = task.take() {
163 task.wake();
164 }
165 }
166
167 Ok(())
168 }
169
170 pub fn send_interim_informational_headers<B>(
173 &mut self,
174 frame: frame::Headers,
175 buffer: &mut Buffer<Frame<B>>,
176 stream: &mut store::Ptr,
177 _counts: &mut Counts,
178 task: &mut Option<Waker>,
179 ) -> Result<(), UserError> {
180 tracing::trace!(
181 "send_interim_informational_headers; frame={:?}; stream_id={:?}",
182 frame,
183 frame.stream_id()
184 );
185
186 Self::check_headers(frame.fields())?;
188
189 debug_assert!(frame.is_informational(),
190 "Frame must be informational (1xx status code) at this point. Validation should happen at the public API boundary.");
191 debug_assert!(!frame.is_end_stream(),
192 "Informational frames must not have end_stream flag set. Validation should happen at the internal send informational header streams.");
193
194 self.prioritize
197 .queue_frame(frame.into(), buffer, stream, task);
198
199 Ok(())
200 }
201
202 pub fn send_reset<B>(
204 &mut self,
205 reason: Reason,
206 initiator: Initiator,
207 buffer: &mut Buffer<Frame<B>>,
208 stream: &mut store::Ptr,
209 counts: &mut Counts,
210 task: &mut Option<Waker>,
211 ) {
212 let is_reset = stream.state.is_reset();
213 let is_closed = stream.state.is_closed();
214 let is_empty = stream.pending_send.is_empty();
215 let stream_id = stream.id;
216
217 tracing::trace!(
218 "send_reset(..., reason={:?}, initiator={:?}, stream={:?}, ..., \
219 is_reset={:?}; is_closed={:?}; pending_send.is_empty={:?}; \
220 state={:?} \
221 ",
222 reason,
223 initiator,
224 stream_id,
225 is_reset,
226 is_closed,
227 is_empty,
228 stream.state
229 );
230
231 if is_reset {
232 tracing::trace!(
234 " -> not sending RST_STREAM ({:?} is already reset)",
235 stream_id
236 );
237 return;
238 }
239
240 stream.set_reset(reason, initiator);
242
243 if is_closed && is_empty {
246 tracing::trace!(
247 " -> not sending explicit RST_STREAM ({:?} was closed \
248 and send queue was flushed)",
249 stream_id
250 );
251 return;
252 }
253
254 if !stream.is_pending_open {
262 self.prioritize.clear_queue(buffer, stream);
269 }
270
271 let frame = frame::Reset::new(stream.id, reason);
272
273 tracing::trace!("send_reset -- queueing; frame={:?}", frame);
274 self.prioritize
275 .queue_frame(frame.into(), buffer, stream, task);
276 self.prioritize.reclaim_all_capacity(stream, counts);
277 }
278
279 pub fn schedule_implicit_reset(
280 &mut self,
281 stream: &mut store::Ptr,
282 reason: Reason,
283 counts: &mut Counts,
284 task: &mut Option<Waker>,
285 ) {
286 if stream.state.is_closed() {
287 return;
289 }
290
291 stream.state.set_scheduled_reset(reason);
292
293 self.prioritize.reclaim_reserved_capacity(stream, counts);
294 self.prioritize.schedule_send(stream, task);
295 }
296
297 pub fn send_data<B>(
298 &mut self,
299 frame: frame::Data<B>,
300 buffer: &mut Buffer<Frame<B>>,
301 stream: &mut store::Ptr,
302 counts: &mut Counts,
303 task: &mut Option<Waker>,
304 ) -> Result<(), UserError>
305 where
306 B: Buf,
307 {
308 self.prioritize
309 .send_data(frame, buffer, stream, counts, task)
310 }
311
312 pub fn send_trailers<B>(
313 &mut self,
314 frame: frame::Headers,
315 buffer: &mut Buffer<Frame<B>>,
316 stream: &mut store::Ptr,
317 counts: &mut Counts,
318 task: &mut Option<Waker>,
319 ) -> Result<(), UserError> {
320 Self::check_headers(frame.fields())?;
329
330 if !stream.state.is_send_streaming() {
332 return Err(UserError::UnexpectedFrameType);
333 }
334
335 stream.state.send_close();
336
337 tracing::trace!("send_trailers -- queuing; frame={:?}", frame);
338 self.prioritize
339 .queue_frame(frame.into(), buffer, stream, task);
340
341 self.prioritize.reserve_capacity(0, stream, counts);
343
344 Ok(())
345 }
346
347 pub fn buffer_pending<T, B>(
348 &mut self,
349 buffer: &mut Buffer<Frame<B>>,
350 store: &mut Store,
351 counts: &mut Counts,
352 dst: &mut Codec<T, Prioritized<B>>,
353 ) -> io::Result<BufferStatus>
354 where
355 T: AsyncWrite + Unpin,
356 B: Buf,
357 {
358 self.prioritize.buffer_pending(buffer, store, counts, dst)
359 }
360
361 pub fn reclaim_written_frame<T, B>(
362 &mut self,
363 buffer: &mut Buffer<Frame<B>>,
364 store: &mut Store,
365 dst: &mut Codec<T, Prioritized<B>>,
366 ) -> bool
367 where
368 B: Buf,
369 {
370 self.prioritize.reclaim_written_frame(buffer, store, dst)
371 }
372
373 pub fn reserve_capacity(
375 &mut self,
376 capacity: WindowSize,
377 stream: &mut store::Ptr,
378 counts: &mut Counts,
379 ) {
380 self.prioritize.reserve_capacity(capacity, stream, counts)
381 }
382
383 pub fn poll_capacity(
384 &mut self,
385 cx: &Context,
386 stream: &mut store::Ptr,
387 ) -> Poll<Option<Result<WindowSize, UserError>>> {
388 if !stream.state.is_send_streaming() {
389 return Poll::Ready(None);
390 }
391
392 if !stream.send_capacity_inc {
393 stream.wait_send(cx);
394 return Poll::Pending;
395 }
396
397 stream.send_capacity_inc = false;
398
399 let capacity = self.capacity(stream);
400
401 if capacity == 0 {
404 stream.wait_send(cx);
405 return Poll::Pending;
406 }
407
408 Poll::Ready(Some(Ok(capacity)))
409 }
410
411 pub fn capacity(&self, stream: &mut store::Ptr) -> WindowSize {
413 stream.capacity(self.prioritize.max_buffer_size())
414 }
415
416 pub fn poll_reset(
417 &self,
418 cx: &Context,
419 stream: &mut Stream,
420 mode: PollReset,
421 ) -> Poll<Result<Reason, crate::Error>> {
422 match stream.state.ensure_reason(mode)? {
423 Some(reason) => Poll::Ready(Ok(reason)),
424 None => {
425 stream.wait_send(cx);
426 Poll::Pending
427 }
428 }
429 }
430
431 pub fn recv_connection_window_update(
432 &mut self,
433 frame: frame::WindowUpdate,
434 store: &mut Store,
435 counts: &mut Counts,
436 ) -> Result<(), Reason> {
437 self.prioritize
438 .recv_connection_window_update(frame.size_increment(), store, counts)
439 }
440
441 pub fn recv_stream_window_update<B>(
442 &mut self,
443 sz: WindowSize,
444 buffer: &mut Buffer<Frame<B>>,
445 stream: &mut store::Ptr,
446 counts: &mut Counts,
447 task: &mut Option<Waker>,
448 ) -> Result<(), Reason> {
449 if let Err(e) = self.prioritize.recv_stream_window_update(sz, stream) {
450 tracing::debug!("recv_stream_window_update !!; err={:?}", e);
451
452 self.send_reset(
453 Reason::FLOW_CONTROL_ERROR,
454 Initiator::Library,
455 buffer,
456 stream,
457 counts,
458 task,
459 );
460
461 return Err(e);
462 }
463
464 Ok(())
465 }
466
467 pub(super) fn recv_go_away(&mut self, last_stream_id: StreamId) -> Result<(), Error> {
468 if last_stream_id > self.max_stream_id {
469 proto_err!(conn:
477 "recv_go_away: last_stream_id ({:?}) > max_stream_id ({:?})",
478 last_stream_id, self.max_stream_id,
479 );
480 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
481 }
482
483 self.max_stream_id = last_stream_id;
484 Ok(())
485 }
486
487 pub fn handle_error<B>(
488 &mut self,
489 buffer: &mut Buffer<Frame<B>>,
490 stream: &mut store::Ptr,
491 counts: &mut Counts,
492 ) {
493 self.prioritize.clear_queue(buffer, stream);
495 self.prioritize.reclaim_all_capacity(stream, counts);
496 }
497
498 pub fn apply_remote_settings<B>(
499 &mut self,
500 settings: &frame::Settings,
501 buffer: &mut Buffer<Frame<B>>,
502 store: &mut Store,
503 counts: &mut Counts,
504 task: &mut Option<Waker>,
505 ) -> Result<(), Error> {
506 if let Some(val) = settings.is_extended_connect_protocol_enabled() {
507 self.is_extended_connect_protocol_enabled = val;
508 }
509
510 if let Some(val) = settings.initial_window_size() {
528 let old_val = self.init_window_sz;
529 self.init_window_sz = val;
530
531 match val.cmp(&old_val) {
532 Ordering::Less => {
533 let dec = old_val - val;
535 tracing::trace!("decrementing all windows; dec={}", dec);
536
537 let mut total_reclaimed = 0;
538 store.try_for_each(|mut stream| {
539 let stream = &mut *stream;
540
541 if stream.state.is_send_closed() && stream.buffered_send_data == 0 {
542 tracing::trace!(
543 "skipping send-closed stream; id={:?}; flow={:?}",
544 stream.id,
545 stream.send_flow
546 );
547
548 return Ok(());
549 }
550
551 tracing::trace!(
552 "decrementing stream window; id={:?}; decr={}; flow={:?}",
553 stream.id,
554 dec,
555 stream.send_flow
556 );
557
558 stream
560 .send_flow
561 .dec_send_window(dec)
562 .map_err(proto::Error::library_go_away)?;
563
564 let window_size = stream.send_flow.window_size();
571 let available = stream.send_flow.available().as_size();
572 let reclaimed = if available > window_size {
573 let reclaim = available - window_size;
575 stream
576 .send_flow
577 .claim_capacity(reclaim)
578 .map_err(proto::Error::library_go_away)?;
579 total_reclaimed += reclaim;
580 reclaim
581 } else {
582 0
583 };
584
585 tracing::trace!(
586 "decremented stream window; id={:?}; decr={}; reclaimed={}; flow={:?}",
587 stream.id,
588 dec,
589 reclaimed,
590 stream.send_flow
591 );
592
593 Ok::<_, proto::Error>(())
598 })?;
599
600 self.prioritize
601 .assign_connection_capacity(total_reclaimed, store, counts);
602 }
603 Ordering::Greater => {
604 let inc = val - old_val;
605
606 store.try_for_each(|mut stream| {
607 self.recv_stream_window_update(inc, buffer, &mut stream, counts, task)
608 .map_err(Error::library_go_away)
609 })?;
610 }
611 Ordering::Equal => (),
612 }
613 }
614
615 if let Some(val) = settings.is_push_enabled() {
616 self.is_push_enabled = val
617 }
618
619 Ok(())
620 }
621
622 pub fn clear_queues(&mut self, store: &mut Store, counts: &mut Counts) {
623 self.prioritize.clear_pending_capacity(store, counts);
624 self.prioritize.clear_pending_send(store, counts);
625 self.prioritize.clear_pending_open(store, counts);
626 }
627
628 pub fn ensure_not_idle(&self, id: StreamId) -> Result<(), Reason> {
629 if let Ok(next) = self.next_stream_id {
630 if id >= next {
631 return Err(Reason::PROTOCOL_ERROR);
632 }
633 }
634 Ok(())
637 }
638
639 pub fn ensure_next_stream_id(&self) -> Result<StreamId, UserError> {
640 self.next_stream_id
641 .map_err(|_| UserError::OverflowedStreamId)
642 }
643
644 pub fn may_have_created_stream(&self, id: StreamId) -> bool {
645 if let Ok(next_id) = self.next_stream_id {
646 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated(),);
648 id < next_id
649 } else {
650 true
651 }
652 }
653
654 pub(super) fn maybe_reset_next_stream_id(&mut self, id: StreamId) {
655 if let Ok(next_id) = self.next_stream_id {
656 debug_assert_eq!(id.is_server_initiated(), next_id.is_server_initiated());
658 if id >= next_id {
659 self.next_stream_id = id.next_id();
660 }
661 }
662 }
663
664 pub(crate) fn is_extended_connect_protocol_enabled(&self) -> bool {
665 self.is_extended_connect_protocol_enabled
666 }
667}