Coverage Report

Created: 2025-12-31 06:11

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