1use alloc::vec::Vec;
2use core::marker::PhantomData;
3use core::mem;
4use core::ops::Range;
5use std::io::{self, Read};
6
7use super::send::{SendOutput, SendPath};
8use super::split::SendAdapter;
9use crate::SideData;
10use crate::common_state::{
11 ConnectionOutput, Event, Output, OutputEvent, Side, UnborrowedPayload, maybe_send_fatal_alert,
12};
13use crate::conn::private::SideOutput;
14use crate::conn::{ConnectionCommon, StateMachine};
15use crate::crypto::cipher::{Decrypted, DecryptionState, EncodableVersion, Payload, Record};
16use crate::enums::{ContentType, HandshakeType, ProtocolVersion};
17use crate::error::{AlertDescription, Error, PeerMisbehaved};
18use crate::msgs::{
19 AlertLevel, AlertLevelName, AlertMessagePayload, Deframed, Deframer, Delocator,
20 HandshakeAlignedProof, Locator, Message, MessagePayload,
21};
22use crate::quic::QuicOutput;
23use crate::tracing::{trace, warn};
24
25pub(crate) struct MessageIter<'a, 'm, Side: SideData, Send: SendOutput + 'a> {
26 pub(super) input: &'m mut dyn TlsInputBuffer,
27 pub(super) tls: &'a mut Vec<u8>,
28 pub(super) recv: &'a mut ReceivePath,
29 pub(super) state: &'a mut Result<Side::State, Error>,
30 pub(super) output: JoinOutput<'a, Send>,
31 pub(super) mode: MessageIterMode,
32}
33
34impl<'a, 'm, Side: SideData> MessageIter<'a, 'm, Side, SendPath> {
35 pub(crate) fn new(
36 input: &'m mut dyn TlsInputBuffer,
37 tls: &'a mut Vec<u8>,
38 quic: Option<&'a mut dyn QuicOutput>,
39 conn: &'a mut ConnectionCommon<Side>,
40 mode: MessageIterMode,
41 ) -> Self {
42 Self {
43 input,
44 tls,
45 recv: &mut conn.common.recv,
46 state: &mut conn.state,
47 output: JoinOutput {
48 outputs: &mut conn.common.outputs,
49 quic,
50 send: &mut conn.common.send,
51 side: &mut conn.side,
52 },
53 mode,
54 }
55 }
56}
57
58impl<'a, 'm, 's, Side: SideData> MessageIter<'a, 'm, Side, SendAdapter<'s>> {
59 pub(super) fn receive(
60 input: &'m mut dyn TlsInputBuffer,
61 tls: &'a mut Vec<u8>,
62 state: &'a mut Result<Side::State, Error>,
63 recv: &'a mut ReceivePath,
64 output: JoinOutput<'a, SendAdapter<'s>>,
65 mode: MessageIterMode,
66 ) -> Self {
67 Self {
68 input,
69 tls,
70 recv,
71 state,
72 output,
73 mode,
74 }
75 }
76}
77
78impl<'a, 'm, Side: SideData, Send: SendOutput + 'a> MessageIter<'a, 'm, Side, Send> {
79 pub(crate) fn next(&mut self, early_only: bool) -> Option<Result<UnborrowedPayload, Error>> {
80 let mut st = match mem::replace(self.state, Err(Error::HandshakeNotComplete)) {
81 Ok(state) => state,
82 Err(e) => {
83 *self.state = Err(e.clone());
84 return Some(Err(e));
85 }
86 };
87
88 let mut plaintext = None;
89 while st.wants_input() {
90 let buffer = self.input.slice_mut();
91 let locator = Locator::new(buffer);
92 let res = self.recv.deframe(buffer);
93
94 let mut output = CaptureAppData {
95 recv: self.recv,
96 tls: self.tls,
97 other: &mut self.output,
98 plaintext_locator: &locator,
99 received_plaintext: &mut plaintext,
100 _message_lifetime: PhantomData,
101 };
102
103 let opt_record = match res {
104 Ok(opt_record) => opt_record,
105 Err(e) => {
106 maybe_send_fatal_alert(output.other.send, &e, output.tls);
107 if let Error::DecryptError = e {
108 st.handle_decrypt_error();
109 }
110 *self.state = Err(e.clone());
111 return Some(Err(e));
112 }
113 };
114
115 let Some(record) = opt_record else {
116 break;
117 };
118
119 let Decrypted {
120 plaintext: record,
121 want_close_before_decrypt,
122 } = record;
123
124 if want_close_before_decrypt {
125 output.other.send.send_alert(
126 AlertLevel::Warning,
127 AlertDescription::CloseNotify,
128 output.tls,
129 );
130 } else if record.payload.is_empty()
131 && matches!(record.typ, ContentType::Handshake | ContentType::Alert)
132 {
133 output.other.send.send_alert(
135 AlertLevel::Fatal,
136 AlertDescription::UnexpectedMessage,
137 output.tls,
138 );
139 let error = Error::from(PeerMisbehaved::EmptyFragment);
140 *self.state = Err(error.clone());
141 return Some(Err(error));
142 }
143
144 let hs_aligned = output.recv.deframer.aligned();
145 let result =
146 match output
147 .recv
148 .receive_record(record, hs_aligned, output.tls, output.other.send)
149 {
150 Ok(Some(input)) => st.handle(input, &mut output),
151 Ok(None) => Ok(st),
152 Err(e) => Err(e),
153 };
154
155 match result {
156 Ok(new) => st = new,
157 Err(e) => {
158 maybe_send_fatal_alert(output.other.send, &e, output.tls);
159 *self.state = Err(e.clone());
160 return Some(Err(e));
161 }
162 }
163
164 if matches!(self.mode, MessageIterMode::All) && !st.wants_input() {
165 st = match st.handle_without_input(&mut output) {
166 Ok(st) => st,
167 Err(err) => {
168 maybe_send_fatal_alert(output.other.send, &err, output.tls);
169 *self.state = Err(err.clone());
170 return Some(Err(err));
171 }
172 };
173 }
174
175 if self.recv.has_received_close_notify {
176 self.input
181 .discard(self.recv.deframer.take_discard());
182
183 let entirety = self.input.slice_mut().len();
185 self.recv.deframer.set_discard(entirety);
186 self.input.received_close_notify();
187 break;
188 }
189
190 match plaintext.take() {
191 Some(DataKind::Traffic(payload)) if !early_only => {
192 *self.state = Ok(st);
193 return Some(Ok(payload));
194 }
195 Some(DataKind::Early(payload)) if early_only => {
196 *self.state = Ok(st);
197 return Some(Ok(payload));
198 }
199 _ => {}
200 }
201
202 if (early_only || matches!(self.mode, MessageIterMode::Handshake)) && st.is_traffic() {
204 break;
205 }
206 }
207
208 *self.state = Ok(st);
209 None
210 }
211}
212
213pub(crate) enum MessageIterMode {
214 All,
216
217 Handshake,
221}
222
223pub(crate) struct ReceivePath {
224 side: Side,
225 pub(crate) decrypt_state: DecryptionState,
226 pub(crate) may_receive_application_data: bool,
227 pub(crate) has_received_close_notify: bool,
229 temper_counters: TemperCounters,
230 pub(crate) negotiated_version: Option<ProtocolVersion>,
231 pub(crate) deframer: Deframer,
232
233 seen_consecutive_empty_fragments: u8,
236
237 pub(crate) tls13_tickets_received: u32,
238}
239
240impl ReceivePath {
241 pub(crate) fn new(side: Side) -> Self {
242 Self {
243 side,
244 decrypt_state: DecryptionState::new(),
245 may_receive_application_data: false,
246 has_received_close_notify: false,
247 temper_counters: TemperCounters::default(),
248 negotiated_version: None,
249 deframer: Deframer::default(),
250 seen_consecutive_empty_fragments: 0,
251 tls13_tickets_received: 0,
252 }
253 }
254
255 fn deframe<'b>(&mut self, buffer: &'b mut [u8]) -> Result<Option<Decrypted<'b>>, Error> {
257 let locator = Locator::new(buffer);
258
259 let mut want_close_before_decrypt = false;
260 loop {
261 if let Some(span) = self.deframer.complete_span() {
263 let plaintext = self.deframer.record(span, buffer);
264
265 self.decrypt_state
267 .finish_trial_decryption();
268
269 return Ok(Some(Decrypted {
270 plaintext,
271 want_close_before_decrypt,
272 }));
273 }
274
275 let (record, bounds) = loop {
276 match self.deframe_decrypted(buffer, &locator)? {
277 DeframeResult::Decrypted(decrypted, bounds) => break (decrypted, bounds),
278 DeframeResult::DecryptionFailed => continue,
279 DeframeResult::None => return Ok(None),
280 }
281 };
282
283 want_close_before_decrypt = record.want_close_before_decrypt;
284 let Decrypted {
285 plaintext: record,
286 want_close_before_decrypt: _,
287 } = record;
288
289 if self.deframer.aligned().is_none() && record.typ != ContentType::Handshake {
290 return Err(PeerMisbehaved::MessageInterleavedWithHandshakeMessage.into());
295 }
296
297 match (record.payload.len(), record.typ) {
298 (0, _) => {
299 if self.seen_consecutive_empty_fragments
300 == ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX
301 {
302 return Err(PeerMisbehaved::TooManyEmptyFragments.into());
303 }
304 self.seen_consecutive_empty_fragments += 1;
305 }
306 (_, ContentType::Handshake | ContentType::ApplicationData) => {
307 self.seen_consecutive_empty_fragments = 0;
308 }
309 (_, _) => {}
310 };
311
312 let unborrowed = InboundUnborrowedRecord::unborrow(&locator, record);
320
321 if unborrowed.typ != ContentType::Handshake {
322 let record = unborrowed.reborrow(&Delocator::new(buffer));
323 self.deframer.discard_processed();
324 return Ok(Some(Decrypted {
325 plaintext: record,
326 want_close_before_decrypt,
327 }));
328 }
329
330 let record = unborrowed.reborrow(&Delocator::new(buffer));
331 self.deframer
332 .input_message(record.version.version(), bounds, buffer);
333 self.deframer.coalesce(buffer)?;
334 }
335 }
336
337 fn deframe_decrypted<'b>(
338 &mut self,
339 buffer: &'b mut [u8],
340 locator: &Locator,
341 ) -> Result<DeframeResult<'b>, Error> {
342 let (record, bounds) = match self.deframer.deframe(buffer) {
343 Some(Ok(Deframed { record, bounds })) => (record, bounds),
344 Some(Err(err)) => return Err(err),
345 None => return Ok(DeframeResult::None),
346 };
347
348 let allowed_plaintext = match record.typ {
349 ContentType::ChangeCipherSpec => true,
351 ContentType::Alert
358 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
359 && !self.decrypt_state.has_decrypted()
360 && record.payload.len() <= 2 =>
361 {
362 true
363 }
364 _ => false,
366 };
367
368 if allowed_plaintext && !self.deframer.is_active() {
369 return Ok(DeframeResult::Decrypted(
370 Decrypted {
371 plaintext: record.into_plain_record(),
372 want_close_before_decrypt: false,
373 },
374 bounds,
375 ));
376 }
377
378 match self
379 .decrypt_state
380 .decrypt_incoming(record)?
381 {
382 Some(decrypted) => {
383 let bounds = locator.locate(decrypted.plaintext.payload);
385 Ok(DeframeResult::Decrypted(decrypted, bounds))
386 }
387
388 None if self.deframer.aligned().is_none() => {
391 Err(PeerMisbehaved::RejectedEarlyDataInterleavedWithHandshakeMessage.into())
392 }
393
394 None => Ok(DeframeResult::DecryptionFailed),
396 }
397 }
398
399 pub(crate) fn receive_record<'a>(
409 &mut self,
410 record: Record<&'a [u8]>,
411 aligned_handshake: Option<HandshakeAlignedProof>,
412 tls: &mut Vec<u8>,
413 send: &mut dyn SendOutput,
414 ) -> Result<Option<Input<'a>>, Error> {
415 if record.typ == ContentType::ChangeCipherSpec && self.drop_tls13_ccs(&record)? {
417 trace!("Dropping CCS");
418 return Ok(None);
419 }
420
421 let message = Message::try_from(record)?;
423
424 if let MessagePayload::Alert(alert) = &message.payload {
426 self.process_alert(alert)?;
427 return Ok(None);
428 }
429
430 if self.reject_renegotiation_request(&message, tls, send)? {
433 return Ok(None);
434 }
435
436 Ok(Some(Input {
437 message,
438 aligned_handshake,
439 }))
440 }
441
442 fn drop_tls13_ccs(&mut self, record: &Record<&'_ [u8]>) -> Result<bool, Error> {
443 if self.may_receive_application_data
444 || !matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
445 {
446 return Ok(false);
447 }
448
449 if !record.is_valid_ccs() {
450 return Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into());
454 }
455
456 self.temper_counters
457 .received_tls13_change_cipher_spec()?;
458 Ok(true)
459 }
460
461 fn reject_renegotiation_request(
462 &mut self,
463 msg: &Message<'_>,
464 tls: &mut Vec<u8>,
465 send: &mut dyn SendOutput,
466 ) -> Result<bool, Error> {
467 if !self.may_receive_application_data
468 || matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
469 {
470 return Ok(false);
471 }
472
473 let reject_ty = match self.side {
474 Side::Client => HandshakeType::HelloRequest,
475 Side::Server => HandshakeType::ClientHello,
476 };
477
478 if msg.handshake_type() != Some(reject_ty) {
479 return Ok(false);
480 }
481 self.temper_counters
482 .received_renegotiation_request()?;
483 let desc = AlertDescription::NoRenegotiation;
484 warn!("sending warning alert {desc:?}");
485 send.send_alert(AlertLevel::Warning, desc, tls);
486 Ok(true)
487 }
488
489 fn process_alert(&mut self, alert: &AlertMessagePayload) -> Result<(), Error> {
490 if AlertLevelName::try_from(alert.level).is_err() {
492 return Err(PeerMisbehaved::IllegalAlertLevel(alert.level.0, alert.description).into());
493 }
494
495 if self.may_receive_application_data && alert.description == AlertDescription::CloseNotify {
498 self.has_received_close_notify = true;
499 return Ok(());
500 }
501
502 let err = Error::AlertReceived(alert.description);
505 if alert.level == AlertLevel::Warning {
506 self.temper_counters
507 .received_warning_alert()?;
508 if matches!(self.negotiated_version, Some(ProtocolVersion::TLSv1_3))
509 && alert.description != AlertDescription::UserCanceled
510 {
511 return Err(PeerMisbehaved::IllegalWarningAlert(alert.description).into());
512 }
513
514 if alert.description != AlertDescription::UserCanceled || cfg!(debug_assertions) {
517 warn!("TLS alert warning received: {alert:?}");
518 }
519
520 return Ok(());
521 }
522
523 Err(err)
524 }
525}
526
527enum DeframeResult<'b> {
528 Decrypted(Decrypted<'b>, Range<usize>),
529 DecryptionFailed,
530 None,
531}
532
533struct CaptureAppData<'a, 'j, 'm, Send: SendOutput + 'a> {
534 recv: &'a mut ReceivePath,
535 other: &'a mut JoinOutput<'j, Send>,
536 tls: &'a mut Vec<u8>,
537 plaintext_locator: &'a Locator,
542 received_plaintext: &'a mut Option<DataKind<UnborrowedPayload>>,
549 _message_lifetime: PhantomData<&'m ()>,
550}
551
552impl<'a, 'm, Send: SendOutput + 'a> Output<'m> for CaptureAppData<'a, '_, 'm, Send> {
553 fn emit(&mut self, ev: Event) {
554 self.other.side.emit(ev)
555 }
556
557 fn output(&mut self, ev: OutputEvent<'_>) {
558 if let OutputEvent::ProtocolVersion(ver) = ev {
559 self.recv.negotiated_version = Some(ver);
560 self.other.send.negotiated_version(ver);
561 }
562 self.other.outputs.handle(ev);
563 }
564
565 fn send_msg(&mut self, m: Message<'_>, must_encrypt: bool) {
566 match self.other.quic.as_deref_mut() {
567 Some(quic) => quic.send_msg(m, must_encrypt),
568 None => self
569 .other
570 .send
571 .send_msg(m, must_encrypt, self.tls),
572 }
573 }
574
575 fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
576 match &mut self.other.quic {
577 Some(quic) => Some(*quic),
578 None => None,
579 }
580 }
581
582 fn received_plaintext(&mut self, payload: DataKind<Payload<'m>>) {
583 let previous = self
590 .received_plaintext
591 .replace(match payload {
592 DataKind::Early(p) => {
593 DataKind::Early(UnborrowedPayload::unborrow(self.plaintext_locator, p))
594 }
595 DataKind::Traffic(p) => {
596 DataKind::Traffic(UnborrowedPayload::unborrow(self.plaintext_locator, p))
597 }
598 });
599 debug_assert!(previous.is_none(), "overwrote plaintext data");
600 }
601
602 fn start_traffic(&mut self) {
603 self.recv.may_receive_application_data = true;
604 self.other.send.start_traffic();
605 }
606
607 fn receive(&mut self) -> &mut ReceivePath {
608 self.recv
609 }
610
611 fn send(&mut self) -> &mut dyn SendOutput {
612 self.other.send
613 }
614}
615
616pub(crate) enum DataKind<T> {
617 Early(T),
618 Traffic(T),
619}
620
621pub(super) struct JoinOutput<'a, Send: SendOutput + 'a> {
622 pub(super) outputs: &'a mut dyn ConnectionOutput,
623 pub(super) quic: Option<&'a mut dyn QuicOutput>,
624 pub(super) send: &'a mut Send,
625 pub(super) side: &'a mut dyn SideOutput,
626}
627
628pub(super) struct Discard;
629
630impl ConnectionOutput for Discard {
631 fn handle(&mut self, _ev: OutputEvent<'_>) {}
632}
633
634impl SideOutput for Discard {
635 fn emit(&mut self, _ev: Event) {}
636}
637
638struct TemperCounters {
641 allowed_warning_alerts: u8,
642 allowed_renegotiation_requests: u8,
643 allowed_middlebox_ccs: u8,
644}
645
646impl TemperCounters {
647 fn received_warning_alert(&mut self) -> Result<(), Error> {
648 match self.allowed_warning_alerts {
649 0 => Err(PeerMisbehaved::TooManyWarningAlertsReceived.into()),
650 _ => {
651 self.allowed_warning_alerts -= 1;
652 Ok(())
653 }
654 }
655 }
656
657 fn received_renegotiation_request(&mut self) -> Result<(), Error> {
658 match self.allowed_renegotiation_requests {
659 0 => Err(PeerMisbehaved::TooManyRenegotiationRequests.into()),
660 _ => {
661 self.allowed_renegotiation_requests -= 1;
662 Ok(())
663 }
664 }
665 }
666
667 fn received_tls13_change_cipher_spec(&mut self) -> Result<(), Error> {
668 match self.allowed_middlebox_ccs {
669 0 => Err(PeerMisbehaved::IllegalMiddleboxChangeCipherSpec.into()),
670 _ => {
671 self.allowed_middlebox_ccs -= 1;
672 Ok(())
673 }
674 }
675 }
676}
677
678impl Default for TemperCounters {
679 fn default() -> Self {
680 Self {
681 allowed_warning_alerts: 4,
684
685 allowed_renegotiation_requests: 1,
688
689 allowed_middlebox_ccs: 2,
694 }
695 }
696}
697
698pub(crate) struct TrafficTemperCounters {
699 allowed_consecutive_handshake_messages: u8,
700}
701
702impl TrafficTemperCounters {
703 pub(crate) fn received_handshake_message(&mut self) -> Result<(), Error> {
704 match self.allowed_consecutive_handshake_messages {
705 0 => Err(PeerMisbehaved::TooManyConsecutiveHandshakeMessagesAfterHandshake.into()),
706 _ => {
707 self.allowed_consecutive_handshake_messages -= 1;
708 Ok(())
709 }
710 }
711 }
712
713 pub(crate) fn received_app_data(&mut self) {
714 self.allowed_consecutive_handshake_messages = Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES;
715 }
716
717 const MAX_CONSECUTIVE_HANDSHAKE_MESSAGES: u8 = 32;
720}
721
722impl Default for TrafficTemperCounters {
723 fn default() -> Self {
724 Self {
725 allowed_consecutive_handshake_messages: Self::MAX_CONSECUTIVE_HANDSHAKE_MESSAGES,
726 }
727 }
728}
729
730pub(crate) struct Input<'a> {
731 pub(crate) message: Message<'a>,
732 pub(crate) aligned_handshake: Option<HandshakeAlignedProof>,
733}
734
735impl Input<'_> {
736 pub(crate) fn check_aligned_handshake(&self) -> Result<HandshakeAlignedProof, Error> {
741 self.aligned_handshake
742 .ok_or_else(|| PeerMisbehaved::KeyEpochWithPendingFragment.into())
743 }
744}
745
746struct InboundUnborrowedRecord {
749 typ: ContentType,
750 version: EncodableVersion,
751 bounds: Range<usize>,
752}
753
754impl InboundUnborrowedRecord {
755 fn unborrow(locator: &Locator, record: Record<&'_ [u8]>) -> Self {
756 Self {
757 typ: record.typ,
758 version: record.version,
759 bounds: locator.locate(record.payload),
760 }
761 }
762
763 fn reborrow<'b>(self, delocator: &Delocator<'b>) -> Record<&'b [u8]> {
764 Record {
765 typ: self.typ,
766 version: self.version,
767 payload: delocator.slice_from_range(&self.bounds),
768 }
769 }
770}
771
772#[derive(Default, Debug)]
774pub struct VecInput {
775 buf: Vec<u8>,
779
780 used: usize,
782
783 has_seen_eof: bool,
785
786 received_close_notify: bool,
788}
789
790impl VecInput {
791 pub(crate) fn discard(&mut self, taken: usize) {
793 if taken < self.used {
794 self.buf
808 .copy_within(taken..self.used, 0);
809 self.used -= taken;
810 } else if taken >= self.used {
811 self.used = 0;
812 }
813 }
814
815 pub(crate) fn filled_mut(&mut self) -> &mut [u8] {
816 &mut self.buf[..self.used]
817 }
818
819 pub fn read(&mut self, rd: &mut dyn Read) -> io::Result<usize> {
825 if self.received_close_notify {
826 return Ok(0);
827 } else if let Err(err) = self.prepare_read() {
828 return Err(io::Error::new(io::ErrorKind::InvalidData, err));
829 }
830
831 let new_bytes = rd.read(&mut self.buf[self.used..])?;
836 if new_bytes == 0 {
837 self.has_seen_eof = true;
838 }
839
840 self.used += new_bytes;
841 Ok(new_bytes)
842 }
843
844 fn prepare_read(&mut self) -> Result<(), &'static str> {
846 const MAX_HANDSHAKE_SIZE: usize = 0xffff;
850
851 const READ_SIZE: usize = 4096;
852
853 if self.used >= MAX_HANDSHAKE_SIZE {
859 return Err("message buffer full");
860 }
861
862 let need_capacity = Ord::min(MAX_HANDSHAKE_SIZE, self.used + READ_SIZE);
868 if need_capacity > self.buf.len() {
869 self.buf.resize(need_capacity, 0);
870 } else if self.used == 0 || self.buf.len() > MAX_HANDSHAKE_SIZE {
871 self.buf.resize(need_capacity, 0);
872 self.buf.shrink_to(need_capacity);
873 }
874
875 Ok(())
876 }
877}
878
879impl TlsInputBuffer for VecInput {
880 fn slice_mut(&mut self) -> &mut [u8] {
881 self.filled_mut()
882 }
883
884 fn discard(&mut self, num_bytes: usize) {
885 self.discard(num_bytes)
886 }
887
888 fn received_close_notify(&mut self) {
889 self.received_close_notify = true;
890 }
891
892 fn has_seen_eof(&self) -> bool {
893 self.has_seen_eof
894 }
895}
896
897#[derive(Debug)]
899pub struct SliceInput<'a> {
900 buf: &'a mut [u8],
902 discard: usize,
904 has_seen_eof: bool,
906 received_close_notify: bool,
908}
909
910impl<'a> SliceInput<'a> {
911 pub fn new(buf: &'a mut [u8]) -> Self {
913 Self {
914 buf,
915 discard: 0,
916 has_seen_eof: false,
917 received_close_notify: false,
918 }
919 }
920
921 pub fn into_used(self) -> usize {
923 self.discard
924 }
925}
926
927impl TlsInputBuffer for SliceInput<'_> {
928 fn slice_mut(&mut self) -> &mut [u8] {
929 &mut self.buf[self.discard..]
930 }
931
932 fn discard(&mut self, num_bytes: usize) {
933 self.discard += num_bytes;
934 }
935
936 fn received_close_notify(&mut self) {
937 self.received_close_notify = true;
938 }
939
940 fn has_seen_eof(&self) -> bool {
941 self.has_seen_eof
942 }
943}
944
945pub trait TlsInputBuffer {
947 fn slice_mut(&mut self) -> &mut [u8];
957
958 fn discard(&mut self, num_bytes: usize);
971
972 fn received_close_notify(&mut self);
976
977 fn has_seen_eof(&self) -> bool;
981}
982
983const ALLOWED_CONSECUTIVE_EMPTY_FRAGMENTS_MAX: u8 = 32;