From 5d6b5049c2a34a3f8abe725d4a871ba84a0dd714 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 24 Aug 2026 14:48:12 +0200 Subject: TLS transport and games framework on client and server --- src/bin/server/tls.rs | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/bin/server/tls.rs (limited to 'src/bin/server/tls.rs') diff --git a/src/bin/server/tls.rs b/src/bin/server/tls.rs new file mode 100644 index 0000000..acf3315 --- /dev/null +++ b/src/bin/server/tls.rs @@ -0,0 +1,96 @@ +use std::io::{Read, Write}; +use std::net::TcpStream; + +#[derive(Clone)] +pub struct TlsServer { + acceptor: native_tls::TlsAcceptor, +} + +impl TlsServer { + pub fn new( + cert_path: &str, + _key_path: &str, + unsafe_mode: bool, + ) -> Result> { + let cert_data = if unsafe_mode { + if std::path::Path::new(cert_path).exists() { + std::fs::read(cert_path)? + } else { + return Err(format!( + "Certificate file '{}' not found. In --unsafe mode, you must provide a valid PKCS12 certificate file.\n\ + You can generate one with:\n\ + openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes\n\ + openssl pkcs12 -export -out identity.p12 -inkey key.pem -in cert.pem", + cert_path + ).into()); + } + } else { + std::fs::read(cert_path)? + }; + + let identity = native_tls::Identity::from_pkcs12(&cert_data, "")?; + let acceptor = native_tls::TlsAcceptor::new(identity)?; + + Ok(Self { acceptor }) + } + + pub fn accept(&self, stream: TcpStream) -> Result> { + let stream = self.acceptor.accept(stream)?; + Ok(TlsStream::new(stream)) + } +} + +pub struct TlsStream { + stream: native_tls::TlsStream, +} + +impl TlsStream { + pub fn new(stream: native_tls::TlsStream) -> Self { + Self { stream } + } + + pub fn read_line(&mut self, s: &mut String) -> std::io::Result { + let mut buf = [0u8; 1024]; + loop { + match self.stream.read(&mut buf) { + Ok(0) => return Ok(0), + Ok(n) => { + let chunk = std::str::from_utf8(&buf[..n]).unwrap_or(""); + s.push_str(chunk); + if s.contains('\n') { + return Ok(n); + } + } + Err(e) => return Err(e), + } + } + } + + pub fn write_line(&mut self, msg: &str) -> std::io::Result<()> { + use std::io::Write; + self.stream.write_all(msg.as_bytes())?; + self.stream.write_all(b"\n")?; + self.stream.flush()?; + Ok(()) + } + + pub fn peer_addr(&self) -> std::io::Result { + self.stream.get_ref().peer_addr() + } +} + +impl Read for TlsStream { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.stream.read(buf) + } +} + +impl Write for TlsStream { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.stream.write(buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.stream.flush() + } +} -- cgit v1.2.3