Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.23/src/conn/unbuffered.rs
Line
Count
Source
1
//! Unbuffered connection API
2
3
use alloc::vec::Vec;
4
use core::num::NonZeroUsize;
5
use core::{fmt, mem};
6
#[cfg(feature = "std")]
7
use std::error::Error as StdError;
8
9
use super::UnbufferedConnectionCommon;
10
use crate::client::ClientConnectionData;
11
use crate::msgs::deframer::buffers::DeframerSliceBuffer;
12
use crate::server::ServerConnectionData;
13
use crate::Error;
14
15
impl UnbufferedConnectionCommon<ClientConnectionData> {
16
    /// Processes the TLS records in `incoming_tls` buffer until a new [`UnbufferedStatus`] is
17
    /// reached.
18
0
    pub fn process_tls_records<'c, 'i>(
19
0
        &'c mut self,
20
0
        incoming_tls: &'i mut [u8],
21
0
    ) -> UnbufferedStatus<'c, 'i, ClientConnectionData> {
22
0
        self.process_tls_records_common(incoming_tls, |_| None, |_, _, ()| unreachable!())
23
0
    }
24
}
25
26
impl UnbufferedConnectionCommon<ServerConnectionData> {
27
    /// Processes the TLS records in `incoming_tls` buffer until a new [`UnbufferedStatus`] is
28
    /// reached.
29
0
    pub fn process_tls_records<'c, 'i>(
30
0
        &'c mut self,
31
0
        incoming_tls: &'i mut [u8],
32
0
    ) -> UnbufferedStatus<'c, 'i, ServerConnectionData> {
33
0
        self.process_tls_records_common(
34
0
            incoming_tls,
35
0
            |conn| conn.pop_early_data(),
36
0
            |conn, incoming_tls, chunk| ReadEarlyData::new(conn, incoming_tls, chunk).into(),
37
        )
38
0
    }
39
}
40
41
impl<Data> UnbufferedConnectionCommon<Data> {
42
0
    fn process_tls_records_common<'c, 'i, T>(
43
0
        &'c mut self,
44
0
        incoming_tls: &'i mut [u8],
45
0
        mut check: impl FnMut(&mut Self) -> Option<T>,
46
0
        execute: impl FnOnce(&'c mut Self, &'i mut [u8], T) -> ConnectionState<'c, 'i, Data>,
47
0
    ) -> UnbufferedStatus<'c, 'i, Data> {
48
0
        let mut buffer = DeframerSliceBuffer::new(incoming_tls);
49
0
        let mut buffer_progress = self.core.hs_deframer.progress();
50
51
0
        let (discard, state) = loop {
52
0
            if let Some(value) = check(self) {
53
0
                break (buffer.pending_discard(), execute(self, incoming_tls, value));
54
0
            }
55
56
0
            if let Some(chunk) = self
57
0
                .core
58
0
                .common_state
59
0
                .received_plaintext
60
0
                .pop()
61
            {
62
0
                break (
63
0
                    buffer.pending_discard(),
64
0
                    ReadTraffic::new(self, incoming_tls, chunk).into(),
65
0
                );
66
0
            }
67
68
0
            if let Some(chunk) = self
69
0
                .core
70
0
                .common_state
71
0
                .sendable_tls
72
0
                .pop()
73
            {
74
0
                break (
75
0
                    buffer.pending_discard(),
76
0
                    EncodeTlsData::new(self, chunk).into(),
77
0
                );
78
0
            }
79
80
0
            let deframer_output =
81
0
                match self
82
0
                    .core
83
0
                    .deframe(None, buffer.filled_mut(), &mut buffer_progress)
84
                {
85
0
                    Err(err) => {
86
0
                        buffer.queue_discard(buffer_progress.take_discard());
87
0
                        return UnbufferedStatus {
88
0
                            discard: buffer.pending_discard(),
89
0
                            state: Err(err),
90
0
                        };
91
                    }
92
0
                    Ok(r) => r,
93
                };
94
95
0
            if let Some(msg) = deframer_output {
96
0
                let mut state =
97
0
                    match mem::replace(&mut self.core.state, Err(Error::HandshakeNotComplete)) {
98
0
                        Ok(state) => state,
99
0
                        Err(e) => {
100
0
                            buffer.queue_discard(buffer_progress.take_discard());
101
0
                            self.core.state = Err(e.clone());
102
0
                            return UnbufferedStatus {
103
0
                                discard: buffer.pending_discard(),
104
0
                                state: Err(e),
105
0
                            };
106
                        }
107
                    };
108
109
0
                match self.core.process_msg(msg, state, None) {
110
0
                    Ok(new) => state = new,
111
112
0
                    Err(e) => {
113
0
                        buffer.queue_discard(buffer_progress.take_discard());
114
0
                        self.core.state = Err(e.clone());
115
0
                        return UnbufferedStatus {
116
0
                            discard: buffer.pending_discard(),
117
0
                            state: Err(e),
118
0
                        };
119
                    }
120
                }
121
122
0
                buffer.queue_discard(buffer_progress.take_discard());
123
124
0
                self.core.state = Ok(state);
125
0
            } else if self.wants_write {
126
0
                break (
127
0
                    buffer.pending_discard(),
128
0
                    TransmitTlsData { conn: self }.into(),
129
0
                );
130
0
            } else if self
131
0
                .core
132
0
                .common_state
133
0
                .has_received_close_notify
134
0
                && !self.emitted_peer_closed_state
135
            {
136
0
                self.emitted_peer_closed_state = true;
137
0
                break (buffer.pending_discard(), ConnectionState::PeerClosed);
138
0
            } else if self
139
0
                .core
140
0
                .common_state
141
0
                .has_received_close_notify
142
0
                && self
143
0
                    .core
144
0
                    .common_state
145
0
                    .has_sent_close_notify
146
            {
147
0
                break (buffer.pending_discard(), ConnectionState::Closed);
148
0
            } else if self
149
0
                .core
150
0
                .common_state
151
0
                .may_send_application_data
152
            {
153
0
                break (
154
0
                    buffer.pending_discard(),
155
0
                    ConnectionState::WriteTraffic(WriteTraffic { conn: self }),
156
0
                );
157
            } else {
158
0
                break (buffer.pending_discard(), ConnectionState::BlockedHandshake);
159
            }
160
        };
161
162
0
        UnbufferedStatus {
163
0
            discard,
164
0
            state: Ok(state),
165
0
        }
166
0
    }
Unexecuted instantiation: <rustls::conn::UnbufferedConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::process_tls_records_common::<(), <rustls::conn::UnbufferedConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::process_tls_records::{closure#0}, <rustls::conn::UnbufferedConnectionCommon<rustls::client::client_conn::ClientConnectionData>>::process_tls_records::{closure#1}>
Unexecuted instantiation: <rustls::conn::UnbufferedConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::process_tls_records_common::<alloc::vec::Vec<u8>, <rustls::conn::UnbufferedConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::process_tls_records::{closure#0}, <rustls::conn::UnbufferedConnectionCommon<rustls::server::server_conn::ServerConnectionData>>::process_tls_records::{closure#1}>
167
}
168
169
/// The current status of the `UnbufferedConnection*`
170
#[must_use]
171
#[derive(Debug)]
172
pub struct UnbufferedStatus<'c, 'i, Data> {
173
    /// Number of bytes to discard
174
    ///
175
    /// After the `state` field of this object has been handled, `discard` bytes must be
176
    /// removed from the *front* of the `incoming_tls` buffer that was passed to
177
    /// the [`UnbufferedConnectionCommon::process_tls_records`] call that returned this object.
178
    ///
179
    /// This discard operation MUST happen *before*
180
    /// [`UnbufferedConnectionCommon::process_tls_records`] is called again.
181
    pub discard: usize,
182
183
    /// The current state of the handshake process
184
    ///
185
    /// This value MUST be handled prior to calling
186
    /// [`UnbufferedConnectionCommon::process_tls_records`] again. See the documentation on the
187
    /// variants of [`ConnectionState`] for more details.
188
    pub state: Result<ConnectionState<'c, 'i, Data>, Error>,
189
}
190
191
/// The state of the [`UnbufferedConnectionCommon`] object
192
#[non_exhaustive] // for forwards compatibility; to support caller-side certificate verification
193
pub enum ConnectionState<'c, 'i, Data> {
194
    /// One, or more, application data records are available
195
    ///
196
    /// See [`ReadTraffic`] for more details on how to use the enclosed object to access
197
    /// the received data.
198
    ReadTraffic(ReadTraffic<'c, 'i, Data>),
199
200
    /// Connection has been cleanly closed by the peer.
201
    ///
202
    /// This state is encountered at most once by each connection -- it is
203
    /// "edge" triggered, rather than "level" triggered.
204
    ///
205
    /// It delimits the data received from the peer, meaning you can be sure you
206
    /// have received all the data the peer sent.
207
    ///
208
    /// No further application data will be received from the peer, so no further
209
    /// `ReadTraffic` states will be produced.
210
    ///
211
    /// However, it is possible to _send_ further application data via `WriteTraffic`
212
    /// states, or close the connection cleanly by calling
213
    /// [`WriteTraffic::queue_close_notify()`].
214
    PeerClosed,
215
216
    /// Connection has been cleanly closed by both us and the peer.
217
    ///
218
    /// This is a terminal state.  No other states will be produced for this
219
    /// connection.
220
    Closed,
221
222
    /// One, or more, early (RTT-0) data records are available
223
    ReadEarlyData(ReadEarlyData<'c, 'i, Data>),
224
225
    /// A Handshake record is ready for encoding
226
    ///
227
    /// Call [`EncodeTlsData::encode`] on the enclosed object, providing an `outgoing_tls`
228
    /// buffer to store the encoding
229
    EncodeTlsData(EncodeTlsData<'c, Data>),
230
231
    /// Previously encoded handshake records need to be transmitted
232
    ///
233
    /// Transmit the contents of the `outgoing_tls` buffer that was passed to previous
234
    /// [`EncodeTlsData::encode`] calls to the peer.
235
    ///
236
    /// After transmitting the contents, call [`TransmitTlsData::done`] on the enclosed object.
237
    /// The transmitted contents MUST not be sent to the peer more than once so they SHOULD be
238
    /// discarded at this point.
239
    ///
240
    /// At some stages of the handshake process, it's possible to send application-data alongside
241
    /// handshake records. Call [`TransmitTlsData::may_encrypt_app_data`] on the enclosed
242
    /// object to probe if that's allowed.
243
    TransmitTlsData(TransmitTlsData<'c, Data>),
244
245
    /// More TLS data is needed to continue with the handshake
246
    ///
247
    /// Request more data from the peer and append the contents to the `incoming_tls` buffer that
248
    /// was passed to [`UnbufferedConnectionCommon::process_tls_records`].
249
    BlockedHandshake,
250
251
    /// The handshake process has been completed.
252
    ///
253
    /// [`WriteTraffic::encrypt`] can be called on the enclosed object to encrypt application
254
    /// data into an `outgoing_tls` buffer. Similarly, [`WriteTraffic::queue_close_notify`] can
255
    /// be used to encrypt a close_notify alert message into a buffer to signal the peer that the
256
    /// connection is being closed. Data written into `outgoing_buffer` by either method MAY be
257
    /// transmitted to the peer during this state.
258
    ///
259
    /// Once this state has been reached, data MAY be requested from the peer and appended to an
260
    /// `incoming_tls` buffer that will be passed to a future
261
    /// [`UnbufferedConnectionCommon::process_tls_records`] invocation. When enough data has been
262
    /// appended to `incoming_tls`, [`UnbufferedConnectionCommon::process_tls_records`] will yield
263
    /// the [`ConnectionState::ReadTraffic`] state.
264
    WriteTraffic(WriteTraffic<'c, Data>),
265
}
266
267
impl<'c, 'i, Data> From<ReadTraffic<'c, 'i, Data>> for ConnectionState<'c, 'i, Data> {
268
0
    fn from(v: ReadTraffic<'c, 'i, Data>) -> Self {
269
0
        Self::ReadTraffic(v)
270
0
    }
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::client::client_conn::ClientConnectionData> as core::convert::From<rustls::conn::unbuffered::ReadTraffic<rustls::client::client_conn::ClientConnectionData>>>::from
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::server::server_conn::ServerConnectionData> as core::convert::From<rustls::conn::unbuffered::ReadTraffic<rustls::server::server_conn::ServerConnectionData>>>::from
271
}
272
273
impl<'c, 'i, Data> From<ReadEarlyData<'c, 'i, Data>> for ConnectionState<'c, 'i, Data> {
274
0
    fn from(v: ReadEarlyData<'c, 'i, Data>) -> Self {
275
0
        Self::ReadEarlyData(v)
276
0
    }
277
}
278
279
impl<'c, Data> From<EncodeTlsData<'c, Data>> for ConnectionState<'c, '_, Data> {
280
0
    fn from(v: EncodeTlsData<'c, Data>) -> Self {
281
0
        Self::EncodeTlsData(v)
282
0
    }
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::client::client_conn::ClientConnectionData> as core::convert::From<rustls::conn::unbuffered::EncodeTlsData<rustls::client::client_conn::ClientConnectionData>>>::from
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::server::server_conn::ServerConnectionData> as core::convert::From<rustls::conn::unbuffered::EncodeTlsData<rustls::server::server_conn::ServerConnectionData>>>::from
283
}
284
285
impl<'c, Data> From<TransmitTlsData<'c, Data>> for ConnectionState<'c, '_, Data> {
286
0
    fn from(v: TransmitTlsData<'c, Data>) -> Self {
287
0
        Self::TransmitTlsData(v)
288
0
    }
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::client::client_conn::ClientConnectionData> as core::convert::From<rustls::conn::unbuffered::TransmitTlsData<rustls::client::client_conn::ClientConnectionData>>>::from
Unexecuted instantiation: <rustls::conn::unbuffered::ConnectionState<rustls::server::server_conn::ServerConnectionData> as core::convert::From<rustls::conn::unbuffered::TransmitTlsData<rustls::server::server_conn::ServerConnectionData>>>::from
289
}
290
291
impl<Data> fmt::Debug for ConnectionState<'_, '_, Data> {
292
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293
0
        match self {
294
0
            Self::ReadTraffic(..) => f.debug_tuple("ReadTraffic").finish(),
295
296
0
            Self::PeerClosed => write!(f, "PeerClosed"),
297
298
0
            Self::Closed => write!(f, "Closed"),
299
300
0
            Self::ReadEarlyData(..) => f.debug_tuple("ReadEarlyData").finish(),
301
302
0
            Self::EncodeTlsData(..) => f.debug_tuple("EncodeTlsData").finish(),
303
304
0
            Self::TransmitTlsData(..) => f
305
0
                .debug_tuple("TransmitTlsData")
306
0
                .finish(),
307
308
0
            Self::BlockedHandshake => f
309
0
                .debug_tuple("BlockedHandshake")
310
0
                .finish(),
311
312
0
            Self::WriteTraffic(..) => f.debug_tuple("WriteTraffic").finish(),
313
        }
314
0
    }
315
}
316
317
/// Application data is available
318
pub struct ReadTraffic<'c, 'i, Data> {
319
    _conn: &'c mut UnbufferedConnectionCommon<Data>,
320
    // for forwards compatibility; to support in-place decryption in the future
321
    _incoming_tls: &'i mut [u8],
322
    chunk: Vec<u8>,
323
    taken: bool,
324
}
325
326
impl<'c, 'i, Data> ReadTraffic<'c, 'i, Data> {
327
0
    fn new(
328
0
        _conn: &'c mut UnbufferedConnectionCommon<Data>,
329
0
        _incoming_tls: &'i mut [u8],
330
0
        chunk: Vec<u8>,
331
0
    ) -> Self {
332
0
        Self {
333
0
            _conn,
334
0
            _incoming_tls,
335
0
            chunk,
336
0
            taken: false,
337
0
        }
338
0
    }
Unexecuted instantiation: <rustls::conn::unbuffered::ReadTraffic<rustls::client::client_conn::ClientConnectionData>>::new
Unexecuted instantiation: <rustls::conn::unbuffered::ReadTraffic<rustls::server::server_conn::ServerConnectionData>>::new
339
340
    /// Decrypts and returns the next available app-data record
341
    // TODO deprecate in favor of `Iterator` implementation, which requires in-place decryption
342
0
    pub fn next_record(&mut self) -> Option<Result<AppDataRecord<'_>, Error>> {
343
0
        if self.taken {
344
0
            None
345
        } else {
346
0
            self.taken = true;
347
0
            Some(Ok(AppDataRecord {
348
0
                discard: 0,
349
0
                payload: &self.chunk,
350
0
            }))
351
        }
352
0
    }
353
354
    /// Returns the payload size of the next app-data record *without* decrypting it
355
    ///
356
    /// Returns `None` if there are no more app-data records
357
0
    pub fn peek_len(&self) -> Option<NonZeroUsize> {
358
0
        if self.taken {
359
0
            None
360
        } else {
361
0
            NonZeroUsize::new(self.chunk.len())
362
        }
363
0
    }
364
}
365
366
/// Early application-data is available.
367
pub struct ReadEarlyData<'c, 'i, Data> {
368
    _conn: &'c mut UnbufferedConnectionCommon<Data>,
369
    // for forwards compatibility; to support in-place decryption in the future
370
    _incoming_tls: &'i mut [u8],
371
    chunk: Vec<u8>,
372
    taken: bool,
373
}
374
375
impl<'c, 'i, Data> ReadEarlyData<'c, 'i, Data> {
376
0
    fn new(
377
0
        _conn: &'c mut UnbufferedConnectionCommon<Data>,
378
0
        _incoming_tls: &'i mut [u8],
379
0
        chunk: Vec<u8>,
380
0
    ) -> Self {
381
0
        Self {
382
0
            _conn,
383
0
            _incoming_tls,
384
0
            chunk,
385
0
            taken: false,
386
0
        }
387
0
    }
388
}
389
390
impl ReadEarlyData<'_, '_, ServerConnectionData> {
391
    /// decrypts and returns the next available app-data record
392
    // TODO deprecate in favor of `Iterator` implementation, which requires in-place decryption
393
0
    pub fn next_record(&mut self) -> Option<Result<AppDataRecord<'_>, Error>> {
394
0
        if self.taken {
395
0
            None
396
        } else {
397
0
            self.taken = true;
398
0
            Some(Ok(AppDataRecord {
399
0
                discard: 0,
400
0
                payload: &self.chunk,
401
0
            }))
402
        }
403
0
    }
404
405
    /// returns the payload size of the next app-data record *without* decrypting it
406
    ///
407
    /// returns `None` if there are no more app-data records
408
0
    pub fn peek_len(&self) -> Option<NonZeroUsize> {
409
0
        if self.taken {
410
0
            None
411
        } else {
412
0
            NonZeroUsize::new(self.chunk.len())
413
        }
414
0
    }
415
}
416
417
/// A decrypted application-data record
418
pub struct AppDataRecord<'i> {
419
    /// Number of additional bytes to discard
420
    ///
421
    /// This number MUST be added to the value of [`UnbufferedStatus.discard`] *prior* to the
422
    /// discard operation. See [`UnbufferedStatus.discard`] for more details
423
    pub discard: usize,
424
425
    /// The payload of the app-data record
426
    pub payload: &'i [u8],
427
}
428
429
/// Allows encrypting app-data
430
pub struct WriteTraffic<'c, Data> {
431
    conn: &'c mut UnbufferedConnectionCommon<Data>,
432
}
433
434
impl<Data> WriteTraffic<'_, Data> {
435
    /// Encrypts `application_data` into the `outgoing_tls` buffer
436
    ///
437
    /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
438
    /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
439
0
    pub fn encrypt(
440
0
        &mut self,
441
0
        application_data: &[u8],
442
0
        outgoing_tls: &mut [u8],
443
0
    ) -> Result<usize, EncryptError> {
444
0
        self.conn
445
0
            .core
446
0
            .maybe_refresh_traffic_keys();
447
0
        self.conn
448
0
            .core
449
0
            .common_state
450
0
            .write_plaintext(application_data.into(), outgoing_tls)
451
0
    }
452
453
    /// Encrypts a close_notify warning alert in `outgoing_tls`
454
    ///
455
    /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
456
    /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
457
0
    pub fn queue_close_notify(&mut self, outgoing_tls: &mut [u8]) -> Result<usize, EncryptError> {
458
0
        self.conn
459
0
            .core
460
0
            .common_state
461
0
            .eager_send_close_notify(outgoing_tls)
462
0
    }
463
464
    /// Arranges for a TLS1.3 `key_update` to be sent.
465
    ///
466
    /// This consumes the `WriteTraffic` state:  to actually send the message,
467
    /// call [`UnbufferedConnectionCommon::process_tls_records`] again which will
468
    /// return a `ConnectionState::EncodeTlsData` that emits the `key_update`
469
    /// message.
470
    ///
471
    /// See [`ConnectionCommon::refresh_traffic_keys()`] for full documentation,
472
    /// including why you might call this and in what circumstances it will fail.
473
    ///
474
    /// [`ConnectionCommon::refresh_traffic_keys()`]: crate::ConnectionCommon::refresh_traffic_keys
475
0
    pub fn refresh_traffic_keys(self) -> Result<(), Error> {
476
0
        self.conn.core.refresh_traffic_keys()
477
0
    }
478
}
479
480
/// A handshake record must be encoded
481
pub struct EncodeTlsData<'c, Data> {
482
    conn: &'c mut UnbufferedConnectionCommon<Data>,
483
    chunk: Option<Vec<u8>>,
484
}
485
486
impl<'c, Data> EncodeTlsData<'c, Data> {
487
0
    fn new(conn: &'c mut UnbufferedConnectionCommon<Data>, chunk: Vec<u8>) -> Self {
488
0
        Self {
489
0
            conn,
490
0
            chunk: Some(chunk),
491
0
        }
492
0
    }
Unexecuted instantiation: <rustls::conn::unbuffered::EncodeTlsData<rustls::client::client_conn::ClientConnectionData>>::new
Unexecuted instantiation: <rustls::conn::unbuffered::EncodeTlsData<rustls::server::server_conn::ServerConnectionData>>::new
493
494
    /// Encodes a handshake record into the `outgoing_tls` buffer
495
    ///
496
    /// Returns the number of bytes that were written into `outgoing_tls`, or an error if
497
    /// the provided buffer is too small. In the error case, `outgoing_tls` is not modified
498
0
    pub fn encode(&mut self, outgoing_tls: &mut [u8]) -> Result<usize, EncodeError> {
499
0
        let Some(chunk) = self.chunk.take() else {
500
0
            return Err(EncodeError::AlreadyEncoded);
501
        };
502
503
0
        let required_size = chunk.len();
504
505
0
        if required_size > outgoing_tls.len() {
506
0
            self.chunk = Some(chunk);
507
0
            Err(InsufficientSizeError { required_size }.into())
508
        } else {
509
0
            let written = chunk.len();
510
0
            outgoing_tls[..written].copy_from_slice(&chunk);
511
512
0
            self.conn.wants_write = true;
513
514
0
            Ok(written)
515
        }
516
0
    }
517
}
518
519
/// Previously encoded TLS data must be transmitted
520
pub struct TransmitTlsData<'c, Data> {
521
    pub(crate) conn: &'c mut UnbufferedConnectionCommon<Data>,
522
}
523
524
impl<Data> TransmitTlsData<'_, Data> {
525
    /// Signals that the previously encoded TLS data has been transmitted
526
0
    pub fn done(self) {
527
0
        self.conn.wants_write = false;
528
0
    }
529
530
    /// Returns an adapter that allows encrypting application data
531
    ///
532
    /// If allowed at this stage of the handshake process
533
0
    pub fn may_encrypt_app_data(&mut self) -> Option<WriteTraffic<'_, Data>> {
534
0
        if self
535
0
            .conn
536
0
            .core
537
0
            .common_state
538
0
            .may_send_application_data
539
        {
540
0
            Some(WriteTraffic { conn: self.conn })
541
        } else {
542
0
            None
543
        }
544
0
    }
545
}
546
547
/// Errors that may arise when encoding a handshake record
548
#[derive(Debug)]
549
pub enum EncodeError {
550
    /// Provided buffer was too small
551
    InsufficientSize(InsufficientSizeError),
552
553
    /// The handshake record has already been encoded; do not call `encode` again
554
    AlreadyEncoded,
555
}
556
557
impl From<InsufficientSizeError> for EncodeError {
558
0
    fn from(v: InsufficientSizeError) -> Self {
559
0
        Self::InsufficientSize(v)
560
0
    }
561
}
562
563
impl fmt::Display for EncodeError {
564
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565
0
        match self {
566
0
            Self::InsufficientSize(InsufficientSizeError { required_size }) => write!(
567
0
                f,
568
0
                "cannot encode due to insufficient size, {} bytes are required",
569
                required_size
570
            ),
571
0
            Self::AlreadyEncoded => "cannot encode, data has already been encoded".fmt(f),
572
        }
573
0
    }
574
}
575
576
#[cfg(feature = "std")]
577
impl StdError for EncodeError {}
578
579
/// Errors that may arise when encrypting application data
580
#[derive(Debug)]
581
pub enum EncryptError {
582
    /// Provided buffer was too small
583
    InsufficientSize(InsufficientSizeError),
584
585
    /// Encrypter has been exhausted
586
    EncryptExhausted,
587
}
588
589
impl From<InsufficientSizeError> for EncryptError {
590
0
    fn from(v: InsufficientSizeError) -> Self {
591
0
        Self::InsufficientSize(v)
592
0
    }
593
}
594
595
impl fmt::Display for EncryptError {
596
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597
0
        match self {
598
0
            Self::InsufficientSize(InsufficientSizeError { required_size }) => write!(
599
0
                f,
600
0
                "cannot encrypt due to insufficient size, {required_size} bytes are required"
601
            ),
602
0
            Self::EncryptExhausted => f.write_str("encrypter has been exhausted"),
603
        }
604
0
    }
605
}
606
607
#[cfg(feature = "std")]
608
impl StdError for EncryptError {}
609
610
/// Provided buffer was too small
611
#[derive(Clone, Copy, Debug)]
612
pub struct InsufficientSizeError {
613
    /// buffer must be at least this size
614
    pub required_size: usize,
615
}