Skip to main content

confium_coordinator/coordinator/
transport.rs

1//! Transport abstraction for authenticated encryption.
2//!
3//! OCP: new transport types (Noise, TLS, QUIC) implement [`Transport`]
4//! without modifying the coordinator or signer daemon.
5
6use std::io::{Read, Write};
7
8/// Transport mode — client or server.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum TransportMode {
11    Client,
12    Server,
13}
14
15/// A secure transport for coordinator↔signer communication.
16pub trait Transport: Read + Write + Send {
17    /// Transport name (e.g., "plaintext", "noise", "tls").
18    fn name(&self) -> &str;
19    /// Whether the connection is encrypted.
20    fn is_encrypted(&self) -> bool;
21    /// Peer identity (authenticated ID or None).
22    fn peer_identity(&self) -> Option<String>;
23}
24
25/// Plaintext transport (no encryption — development only).
26pub struct PlaintextTransport {
27    inner: std::net::TcpStream,
28    peer: Option<String>,
29}
30
31impl PlaintextTransport {
32    pub fn new(stream: std::net::TcpStream) -> Self {
33        let peer = stream.peer_addr().ok().map(|a| a.to_string());
34        Self {
35            inner: stream,
36            peer,
37        }
38    }
39}
40
41impl Read for PlaintextTransport {
42    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
43        self.inner.read(buf)
44    }
45}
46
47impl Write for PlaintextTransport {
48    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
49        self.inner.write(buf)
50    }
51    fn flush(&mut self) -> std::io::Result<()> {
52        self.inner.flush()
53    }
54}
55
56impl Transport for PlaintextTransport {
57    fn name(&self) -> &str {
58        "plaintext"
59    }
60    fn is_encrypted(&self) -> bool {
61        false
62    }
63    fn peer_identity(&self) -> Option<String> {
64        self.peer.clone()
65    }
66}
67
68/// Transport factory trait — produces transports for connections.
69pub trait TransportFactory: Send + Sync {
70    /// Wrap a raw TCP stream into a transport.
71    fn wrap(&self, stream: std::net::TcpStream, mode: TransportMode) -> Box<dyn Transport>;
72    /// Factory name.
73    fn name(&self) -> &str;
74}
75
76/// Plaintext factory (development).
77pub struct PlaintextTransportFactory;
78
79impl TransportFactory for PlaintextTransportFactory {
80    fn wrap(&self, stream: std::net::TcpStream, _mode: TransportMode) -> Box<dyn Transport> {
81        Box::new(PlaintextTransport::new(stream))
82    }
83    fn name(&self) -> &str {
84        "plaintext"
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn plaintext_not_encrypted() {
94        let factory = PlaintextTransportFactory;
95        // Can't actually connect, but can verify the factory name
96        assert_eq!(factory.name(), "plaintext");
97    }
98
99    #[test]
100    fn transport_mode_eq() {
101        assert_eq!(TransportMode::Client, TransportMode::Client);
102        assert_ne!(TransportMode::Client, TransportMode::Server);
103    }
104
105    #[test]
106    fn factory_implements_trait() {
107        let factory: Box<dyn TransportFactory> = Box::new(PlaintextTransportFactory);
108        assert_eq!(factory.name(), "plaintext");
109    }
110}