summaryrefslogtreecommitdiffstats
path: root/src/bin/client/tls.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-28 22:38:54 +0100
committersalmonik <salmonik@tuta.io>2026-10-28 22:38:54 +0100
commitef2e13df274aaf0f2e50c03c63db33d65d9a0275 (patch)
tree991fa12e70ec11e84e8f6c6e7bc0a60b0a150759 /src/bin/client/tls.rs
parentv0.2.5: fix terminal width, ping timing and output formatting (diff)
downloadzagan-bet-ef2e13df274aaf0f2e50c03c63db33d65d9a0275.tar.gz
zagan-bet-ef2e13df274aaf0f2e50c03c63db33d65d9a0275.zip
v0.2.6: preserve buffered lines and add request read timeouts
Diffstat (limited to 'src/bin/client/tls.rs')
-rw-r--r--src/bin/client/tls.rs36
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;
19use parking_lot::Mutex; 19use parking_lot::Mutex;
20use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; 20use rustls::client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
21use rustls::DigitallySignedStruct; 21use rustls::DigitallySignedStruct;
22use zagan_bet::protocol::LineBuffer;
22use zagan_bet::tofu::{decide, spki_fingerprint, TrustDecision}; 23use zagan_bet::tofu::{decide, spki_fingerprint, TrustDecision};
23 24
24pub struct TlsConnector { 25pub 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 {
144struct Session { 149struct Session {
145 sock: TcpStream, 150 sock: TcpStream,
146 tls: rustls::ClientConnection, 151 tls: rustls::ClientConnection,
152 lines: LineBuffer,
147} 153}
148 154
149impl Session { 155impl Session {
@@ -159,17 +165,25 @@ pub struct TlsStream {
159 165
160impl TlsStream { 166impl 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())