Skip to main content

rustls/
stream.rs

1use core::ops::{Deref, DerefMut};
2use std::io::{BufRead, ErrorKind, IoSlice, Read, Result, Write};
3
4use crate::conn::{ConnectionCommon, SideData};
5
6/// This type implements `io::Read` and `io::Write`, encapsulating
7/// a Connection `C` and an underlying transport `T`, such as a socket.
8///
9/// Relies on [`ConnectionCommon::complete_io()`] to perform the necessary I/O.
10///
11/// This allows you to use a rustls Connection like a normal stream.
12#[derive(Debug)]
13pub struct Stream<'a, C: 'a + ?Sized, T: 'a + Read + Write + ?Sized> {
14    /// Our TLS connection
15    pub conn: &'a mut C,
16
17    /// The underlying transport, like a socket
18    pub sock: &'a mut T,
19}
20
21impl<'a, C, T, S> Stream<'a, C, T>
22where
23    C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
24    T: 'a + Read + Write,
25    S: SideData,
26{
27    /// Make a new Stream using the Connection `conn` and socket-like object
28    /// `sock`.  This does not fail and does no IO.
29    pub fn new(conn: &'a mut C, sock: &'a mut T) -> Self {
30        Self { conn, sock }
31    }
32
33    /// If we're handshaking, complete all the IO for that.
34    /// If we have data to write, write it all.
35    fn complete_prior_io(&mut self) -> Result<()> {
36        if self.conn.is_handshaking() {
37            self.conn.complete_io(self.sock)?;
38        }
39
40        if self.conn.wants_write() {
41            self.conn.complete_io(self.sock)?;
42        }
43
44        Ok(())
45    }
46
47    fn prepare_read(&mut self) -> Result<()> {
48        // Return buffered plaintext without doing any IO: `complete_io()` does not read
49        // while plaintext is buffered, so blocked writes would otherwise hide it.
50        if !self.conn.received_plaintext.is_empty() {
51            return Ok(());
52        }
53
54        self.complete_prior_io()?;
55
56        // We call complete_io() in a loop since a single call may read only
57        // a partial packet from the underlying transport, or may only write
58        // pending TLS data (like an alert queued while processing received
59        // records). A full packet is needed to get more plaintext, which we
60        // must do if EOF has not been hit.
61        while self.conn.wants_read() {
62            let (read, written) = self.conn.complete_io(self.sock)?;
63            if read == 0 && written == 0 {
64                break;
65            }
66        }
67
68        Ok(())
69    }
70
71    // Implements `BufRead::fill_buf` but with more flexible lifetimes, so StreamOwned can reuse it
72    fn fill_buf(mut self) -> Result<&'a [u8]>
73    where
74        S: 'a,
75    {
76        self.prepare_read()?;
77        self.conn.reader().into_first_chunk()
78    }
79}
80
81impl<'a, C, T, S> Read for Stream<'a, C, T>
82where
83    C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
84    T: 'a + Read + Write,
85    S: SideData,
86{
87    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
88        self.prepare_read()?;
89        self.conn.reader().read(buf)
90    }
91
92    #[cfg(read_buf)]
93    fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_, u8>) -> Result<()> {
94        self.prepare_read()?;
95        self.conn.reader().read_buf(cursor)
96    }
97}
98
99impl<'a, C, T, S> BufRead for Stream<'a, C, T>
100where
101    C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
102    T: 'a + Read + Write,
103    S: 'a + SideData,
104{
105    fn fill_buf(&mut self) -> Result<&[u8]> {
106        // reborrow to get an owned `Stream`
107        Stream {
108            conn: self.conn,
109            sock: self.sock,
110        }
111        .fill_buf()
112    }
113
114    fn consume(&mut self, amt: usize) {
115        self.conn.reader().consume(amt)
116    }
117}
118
119impl<'a, C, T, S> Write for Stream<'a, C, T>
120where
121    C: 'a + DerefMut + Deref<Target = ConnectionCommon<S>>,
122    T: 'a + Read + Write,
123    S: SideData,
124{
125    fn write(&mut self, buf: &[u8]) -> Result<usize> {
126        self.complete_prior_io()?;
127
128        let len = self.conn.writer().write(buf)?;
129
130        // Try to write the underlying transport here, but don't let
131        // any errors mask the fact we've consumed `len` bytes.
132        // Callers will learn of permanent errors on the next call.
133        let _ = self.conn.complete_io(self.sock);
134
135        Ok(len)
136    }
137
138    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
139        self.complete_prior_io()?;
140
141        let len = self
142            .conn
143            .writer()
144            .write_vectored(bufs)?;
145
146        // Try to write the underlying transport here, but don't let
147        // any errors mask the fact we've consumed `len` bytes.
148        // Callers will learn of permanent errors on the next call.
149        let _ = self.conn.complete_io(self.sock);
150
151        Ok(len)
152    }
153
154    fn flush(&mut self) -> Result<()> {
155        self.complete_prior_io()?;
156
157        // `complete_prior_io()` may return after making only partial progress, so
158        // keep writing until all TLS output has been handed to the transport.
159        while self.conn.wants_write() {
160            match self.conn.write_tls(self.sock) {
161                Ok(0) => return Err(ErrorKind::WriteZero.into()),
162                Ok(_) => {}
163                Err(err) if err.kind() == ErrorKind::Interrupted => {}
164                Err(err) => return Err(err),
165            }
166        }
167
168        // Always flush the transport, even if we had no TLS output: an earlier
169        // flush (for example, from within `write()`) may have failed.
170        self.sock.flush()?;
171
172        // Report any fatal error the connection encountered after an earlier `write()`
173        // had already accepted its plaintext (for example, while processing received data).
174        self.conn.writer().flush()
175    }
176}
177
178/// This type implements `io::Read` and `io::Write`, encapsulating
179/// and owning a Connection `C` and an underlying transport `T`, such as a socket.
180///
181/// Relies on [`ConnectionCommon::complete_io()`] to perform the necessary I/O.
182///
183/// This allows you to use a rustls Connection like a normal stream.
184#[derive(Debug)]
185pub struct StreamOwned<C: Sized, T: Read + Write + Sized> {
186    /// Our connection
187    pub conn: C,
188
189    /// The underlying transport, like a socket
190    pub sock: T,
191}
192
193impl<C, T, S> StreamOwned<C, T>
194where
195    C: DerefMut + Deref<Target = ConnectionCommon<S>>,
196    T: Read + Write,
197    S: SideData,
198{
199    /// Make a new StreamOwned taking the Connection `conn` and socket-like
200    /// object `sock`.  This does not fail and does no IO.
201    ///
202    /// This is the same as `Stream::new` except `conn` and `sock` are
203    /// moved into the StreamOwned.
204    pub fn new(conn: C, sock: T) -> Self {
205        Self { conn, sock }
206    }
207
208    /// Get a reference to the underlying socket
209    pub fn get_ref(&self) -> &T {
210        &self.sock
211    }
212
213    /// Get a mutable reference to the underlying socket
214    pub fn get_mut(&mut self) -> &mut T {
215        &mut self.sock
216    }
217
218    /// Extract the `conn` and `sock` parts from the `StreamOwned`
219    pub fn into_parts(self) -> (C, T) {
220        (self.conn, self.sock)
221    }
222}
223
224impl<'a, C, T, S> StreamOwned<C, T>
225where
226    C: DerefMut + Deref<Target = ConnectionCommon<S>>,
227    T: Read + Write,
228    S: SideData,
229{
230    fn as_stream(&'a mut self) -> Stream<'a, C, T> {
231        Stream {
232            conn: &mut self.conn,
233            sock: &mut self.sock,
234        }
235    }
236}
237
238impl<C, T, S> Read for StreamOwned<C, T>
239where
240    C: DerefMut + Deref<Target = ConnectionCommon<S>>,
241    T: Read + Write,
242    S: SideData,
243{
244    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
245        self.as_stream().read(buf)
246    }
247
248    #[cfg(read_buf)]
249    fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_, u8>) -> Result<()> {
250        self.as_stream().read_buf(cursor)
251    }
252}
253
254impl<C, T, S> BufRead for StreamOwned<C, T>
255where
256    C: DerefMut + Deref<Target = ConnectionCommon<S>>,
257    T: Read + Write,
258    S: 'static + SideData,
259{
260    fn fill_buf(&mut self) -> Result<&[u8]> {
261        self.as_stream().fill_buf()
262    }
263
264    fn consume(&mut self, amt: usize) {
265        self.as_stream().consume(amt)
266    }
267}
268
269impl<C, T, S> Write for StreamOwned<C, T>
270where
271    C: DerefMut + Deref<Target = ConnectionCommon<S>>,
272    T: Read + Write,
273    S: SideData,
274{
275    fn write(&mut self, buf: &[u8]) -> Result<usize> {
276        self.as_stream().write(buf)
277    }
278
279    fn flush(&mut self) -> Result<()> {
280        self.as_stream().flush()
281    }
282}
283
284#[cfg(test)]
285mod tests {
286    use std::net::TcpStream;
287
288    use super::{Stream, StreamOwned};
289    use crate::client::ClientConnection;
290    use crate::server::ServerConnection;
291
292    #[test]
293    fn stream_can_be_created_for_connection_and_tcpstream() {
294        type _Test<'a> = Stream<'a, ClientConnection, TcpStream>;
295    }
296
297    #[test]
298    fn streamowned_can_be_created_for_client_and_tcpstream() {
299        type _Test = StreamOwned<ClientConnection, TcpStream>;
300    }
301
302    #[test]
303    fn streamowned_can_be_created_for_server_and_tcpstream() {
304        type _Test = StreamOwned<ServerConnection, TcpStream>;
305    }
306}