diff options
Diffstat (limited to 'src/bin/client/tls.rs')
| -rw-r--r-- | src/bin/client/tls.rs | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/src/bin/client/tls.rs b/src/bin/client/tls.rs index ca99838..b118f63 100644 --- a/src/bin/client/tls.rs +++ b/src/bin/client/tls.rs | |||
| @@ -19,6 +19,7 @@ use std::sync::Arc; | |||
| 19 | use parking_lot::Mutex; | 19 | use parking_lot::Mutex; |
| 20 | use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; | 20 | use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; |
| 21 | use rustls::DigitallySignedStruct; | 21 | use rustls::DigitallySignedStruct; |
| 22 | use zagan_bet::protocol::LineBuffer; | ||
| 22 | use zagan_bet::tofu::{decide, spki_fingerprint, TrustDecision}; | 23 | use zagan_bet::tofu::{decide, spki_fingerprint, TrustDecision}; |
| 23 | 24 | ||
| 24 | pub struct TlsConnector { | 25 | pub struct TlsConnector { |
| @@ -59,7 +60,11 @@ impl TlsConnector { | |||
| 59 | conn.complete_io(&mut sock)?; | 60 | conn.complete_io(&mut sock)?; |
| 60 | 61 | ||
| 61 | Ok(TlsStream { | 62 | Ok(TlsStream { |
| 62 | session: Arc::new(Mutex::new(Session { sock, tls: conn })), | 63 | session: Arc::new(Mutex::new(Session { |
| 64 | sock, | ||
| 65 | tls: conn, | ||
| 66 | lines: LineBuffer::new(), | ||
| 67 | })), | ||
| 63 | }) | 68 | }) |
| 64 | } | 69 | } |
| 65 | 70 | ||
| @@ -144,6 +149,7 @@ impl ServerCertVerifier for TofuVerifier { | |||
| 144 | struct Session { | 149 | struct Session { |
| 145 | sock: TcpStream, | 150 | sock: TcpStream, |
| 146 | tls: rustls::ClientConnection, | 151 | tls: rustls::ClientConnection, |
| 152 | lines: LineBuffer, | ||
| 147 | } | 153 | } |
| 148 | 154 | ||
| 149 | impl Session { | 155 | impl Session { |
| @@ -159,17 +165,25 @@ pub struct TlsStream { | |||
| 159 | 165 | ||
| 160 | impl TlsStream { | 166 | impl TlsStream { |
| 161 | pub fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> { | 167 | pub fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> { |
| 162 | let mut byte_buf = [0u8; 1024]; | ||
| 163 | let mut s = self.session.lock(); | 168 | let mut s = self.session.lock(); |
| 164 | loop { | 169 | loop { |
| 170 | if let Some(line) = s.lines.next_line() { | ||
| 171 | buf.push_str(&line); | ||
| 172 | buf.push('\n'); | ||
| 173 | return Ok(line.len() + 1); | ||
| 174 | } | ||
| 175 | |||
| 176 | let mut byte_buf = [0u8; 4096]; | ||
| 165 | match s.tls.reader().read(&mut byte_buf) { | 177 | match s.tls.reader().read(&mut byte_buf) { |
| 166 | Ok(0) => return Ok(0), | 178 | Ok(0) => { |
| 167 | Ok(n) => { | 179 | if let Some(rest) = s.lines.take_rest() { |
| 168 | buf.push_str(std::str::from_utf8(&byte_buf[..n]).unwrap_or("")); | 180 | let read = rest.len(); |
| 169 | if buf.contains('\n') { | 181 | buf.push_str(&rest); |
| 170 | return Ok(n); | 182 | return Ok(read); |
| 171 | } | 183 | } |
| 184 | return Ok(0); | ||
| 172 | } | 185 | } |
| 186 | Ok(n) => s.lines.push(&byte_buf[..n]), | ||
| 173 | Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => s.drive()?, | 187 | Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => s.drive()?, |
| 174 | Err(e) => return Err(e), | 188 | Err(e) => return Err(e), |
| 175 | } | 189 | } |
| @@ -183,6 +197,14 @@ impl TlsStream { | |||
| 183 | s.drive() | 197 | s.drive() |
| 184 | } | 198 | } |
| 185 | 199 | ||
| 200 | /// Apply a read timeout to the underlying TCP socket. | ||
| 201 | pub fn set_read_timeout( | ||
| 202 | &self, | ||
| 203 | duration: Option<std::time::Duration>, | ||
| 204 | ) -> std::io::Result<()> { | ||
| 205 | self.session.lock().sock.set_read_timeout(duration) | ||
| 206 | } | ||
| 207 | |||
| 186 | /// Clones share the same underlying TLS session. | 208 | /// Clones share the same underlying TLS session. |
| 187 | pub fn try_clone(&self) -> std::io::Result<TlsStream> { | 209 | pub fn try_clone(&self) -> std::io::Result<TlsStream> { |
| 188 | Ok(self.clone()) | 210 | Ok(self.clone()) |
