]> git.r.bdr.sh - rbdr/olden-mail/blobdiff - src/proxy.rs
Don't use a prefix
[rbdr/olden-mail] / src / proxy.rs
index c6954a06c11e5867aab8f831c6e8f7868135a7ba..33de44039615959fdc360b56767d601bbbba58d7 100644 (file)
@@ -1,7 +1,7 @@
 //! # Proxy Module
 //!
 //! This module has the actual proxy functionality, exposed through
 //! # Proxy Module
 //!
 //! This module has the actual proxy functionality, exposed through
-//! `ProxyServer`. The proxy consists of a local unencrypted TCP stream
+//! `Server`. The proxy consists of a local unencrypted TCP stream
 //! and a remote TLS stream. Messages are passed between them via two
 //! threads.
 //!
 //! and a remote TLS stream. Messages are passed between them via two
 //! threads.
 //!
@@ -9,24 +9,24 @@
 //! - **Client to Server Thread**: Forwards data from client -> TLS server
 //! - **Serveer to Client Thread**: Forwards data from TLS server -> client
 //!
 //! - **Client to Server Thread**: Forwards data from client -> TLS server
 //! - **Serveer to Client Thread**: Forwards data from TLS server -> client
 //!
-//! Finally, the ProxyServer may be shutdown by calling `.shutdown()`,
+//! Finally, the `Server` may be shutdown by calling `.shutdown()`,
 //! this will stop new connections and wait for it to finish.
 //!
 //! # Example
 //!
 //! ```
 //! use std::sync::Arc;
 //! this will stop new connections and wait for it to finish.
 //!
 //! # Example
 //!
 //! ```
 //! use std::sync::Arc;
-//! use crate::configuration::ProxyConfiguration;
-//! use crate::proxy::ProxyServer;
+//! use crate::configuration::Proxy;
+//! use crate::proxy::Server;
 //!
 //!
-//! let config = Arc::new(ProxyConfiguration {
+//! let config = Arc::new(Proxy {
 //!     protocol: "IMAP".to_string(),
 //!     local_port: 143,
 //!     remote_domain: "imap.example.com".to_string(),
 //!     remote_port: 993,
 //! });
 //!
 //!     protocol: "IMAP".to_string(),
 //!     local_port: 143,
 //!     remote_domain: "imap.example.com".to_string(),
 //!     remote_port: 993,
 //! });
 //!
-//! let mut server = ProxyServer::new(config);
+//! let mut server = Server::new(config);
 //! // The server runs in a background thread. To shut down gracefully:
 //! server.shutdown();
 //! ```
 //! // The server runs in a background thread. To shut down gracefully:
 //! server.shutdown();
 //! ```
@@ -41,41 +41,42 @@ use std::sync::{
 use std::thread::{sleep, spawn, JoinHandle};
 use std::time::Duration;
 
 use std::thread::{sleep, spawn, JoinHandle};
 use std::time::Duration;
 
-use crate::configuration::ProxyConfiguration;
+use crate::configuration::Proxy;
+use crate::middleware::{CLIENT_MIDDLEWARE, SERVER_MIDDLEWARE};
 
 /// A proxy server that listens for plaintext connections and forwards them
 /// via TLS.
 ///
 
 /// A proxy server that listens for plaintext connections and forwards them
 /// via TLS.
 ///
-/// Creating a new `ProxyServer` spawns a dedicated thread that:
+/// Creating a new `Server` spawns a dedicated thread that:
 /// - Binds to a local port (non-blocking mode).
 /// - Spawns additional threads for each incoming client connection.
 /// - Manages connection-lifetime until it receives a shutdown signal.
 /// - Binds to a local port (non-blocking mode).
 /// - Spawns additional threads for each incoming client connection.
 /// - Manages connection-lifetime until it receives a shutdown signal.
-pub struct ProxyServer {
+pub struct Server {
     running: Arc<AtomicBool>,
     thread_handle: Option<JoinHandle<()>>,
 }
 
     running: Arc<AtomicBool>,
     thread_handle: Option<JoinHandle<()>>,
 }
 
-impl ProxyServer {
-    /// Creates a new `ProxyServer` for the given `ProxyConfiguration` and
+impl Server {
+    /// Creates a new `Server` for the given `Proxy` configuration and
     /// immediately starts it.
     ///
     /// # Arguments
     ///
     /// immediately starts it.
     ///
     /// # Arguments
     ///
-    /// * `configuration` - Shared (Arc) `ProxyConfiguration`
+    /// * `configuration` - Shared (Arc) `Proxy`
     ///
     /// # Returns
     ///
     ///
     /// # Returns
     ///
-    /// A `ProxyServer` instance that will keep running until its `.shutdown()`
+    /// A `Server` instance that will keep running until its `.shutdown()`
     /// method is called, or an error occurs.
     /// method is called, or an error occurs.
-    pub fn new(configuration: Arc<ProxyConfiguration>) -> Self {
+    pub fn new(configuration: Arc<Proxy>) -> Self {
         let running = Arc::new(AtomicBool::new(true));
         let running_clone = Arc::clone(&running);
 
         let thread_handle = spawn(move || {
         let running = Arc::new(AtomicBool::new(true));
         let running_clone = Arc::clone(&running);
 
         let thread_handle = spawn(move || {
-            run_proxy(configuration, running_clone);
+            run_proxy(&configuration, &running_clone);
         });
 
         });
 
-        ProxyServer {
+        Server {
             running,
             thread_handle: Some(thread_handle),
         }
             running,
             thread_handle: Some(thread_handle),
         }
@@ -93,7 +94,7 @@ impl ProxyServer {
 
 /// The main loop that listens for incoming (plaintext) connections on
 /// `configuration.bind_address:configuration.local_port`.
 
 /// The main loop that listens for incoming (plaintext) connections on
 /// `configuration.bind_address:configuration.local_port`.
-fn run_proxy(configuration: Arc<ProxyConfiguration>, running: Arc<AtomicBool>) {
+fn run_proxy(configuration: &Arc<Proxy>, running: &Arc<AtomicBool>) {
     let listener = match TcpListener::bind(format!(
         "{}:{}",
         configuration.bind_address, configuration.local_port
     let listener = match TcpListener::bind(format!(
         "{}:{}",
         configuration.bind_address, configuration.local_port
@@ -119,9 +120,9 @@ fn run_proxy(configuration: Arc<ProxyConfiguration>, running: Arc<AtomicBool>) {
             Ok((stream, addr)) => {
                 info!("New {} connection from {}", configuration.protocol, addr);
 
             Ok((stream, addr)) => {
                 info!("New {} connection from {}", configuration.protocol, addr);
 
-                let configuration_clone = Arc::clone(&configuration);
+                let configuration_clone = Arc::clone(configuration);
                 let handle = spawn(move || {
                 let handle = spawn(move || {
-                    handle_client(stream, configuration_clone);
+                    handle_client(stream, &configuration_clone);
                 });
                 active_threads.push(handle);
             }
                 });
                 active_threads.push(handle);
             }
@@ -152,7 +153,7 @@ fn run_proxy(configuration: Arc<ProxyConfiguration>, running: Arc<AtomicBool>) {
 }
 
 /// Handles a single client connection by bridging it (plaintext) to a TLS connection.
 }
 
 /// Handles a single client connection by bridging it (plaintext) to a TLS connection.
-fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration>) {
+fn handle_client(client_stream: TcpStream, configuration: &Arc<Proxy>) {
     if let Err(e) = client_stream.set_nonblocking(true) {
         error!("Failed to set client stream to nonblocking: {}", e);
         return;
     if let Err(e) = client_stream.set_nonblocking(true) {
         error!("Failed to set client stream to nonblocking: {}", e);
         return;
@@ -213,7 +214,6 @@ fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration
         let mut buffer = [0u8; 8192];
         let mut client_reader = client_stream;
         loop {
         let mut buffer = [0u8; 8192];
         let mut client_reader = client_stream;
         loop {
-            debug!(">");
             let bytes_read = match client_reader.read(&mut buffer) {
                 Ok(0) => break,
                 Ok(n) => n,
             let bytes_read = match client_reader.read(&mut buffer) {
                 Ok(0) => break,
                 Ok(n) => n,
@@ -227,7 +227,13 @@ fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration
                 }
             };
 
                 }
             };
 
-            let debug_str = String::from_utf8_lossy(&buffer[..bytes_read])
+            let mut command = buffer[..bytes_read].to_vec();
+
+            for middleware in CLIENT_MIDDLEWARE {
+                command = middleware(&command);
+            }
+
+            let debug_str = String::from_utf8_lossy(&command)
                 .replace('\n', "\\n")
                 .replace('\r', "\\r")
                 .replace('\t', "\\t");
                 .replace('\n', "\\n")
                 .replace('\r', "\\r")
                 .replace('\t', "\\t");
@@ -236,7 +242,7 @@ fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration
             // Lock the TLS stream and write the data to server
             match tls_stream_clone.lock() {
                 Ok(mut tls_guard) => {
             // Lock the TLS stream and write the data to server
             match tls_stream_clone.lock() {
                 Ok(mut tls_guard) => {
-                    if let Err(error) = tls_guard.write_all(&buffer[..bytes_read]) {
+                    if let Err(error) = tls_guard.write_all(&command) {
                         debug!(">>> Error writing to server: {error}");
                         break;
                     }
                         debug!(">>> Error writing to server: {error}");
                         break;
                     }
@@ -260,7 +266,6 @@ fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration
         let mut buffer = [0u8; 8192];
         let mut client_writer = client_stream_clone;
         loop {
         let mut buffer = [0u8; 8192];
         let mut client_writer = client_stream_clone;
         loop {
-            debug!("<");
             // Lock the TLS stream and read from the server
             let bytes_read = match tls_stream_clone.lock() {
                 Ok(mut tls_guard) => match tls_guard.read(&mut buffer) {
             // Lock the TLS stream and read from the server
             let bytes_read = match tls_stream_clone.lock() {
                 Ok(mut tls_guard) => match tls_guard.read(&mut buffer) {
@@ -281,14 +286,20 @@ fn handle_client(client_stream: TcpStream, configuration: Arc<ProxyConfiguration
                 }
             };
 
                 }
             };
 
-            let debug_str = String::from_utf8_lossy(&buffer[..bytes_read])
+            let mut command = buffer[..bytes_read].to_vec();
+
+            for middleware in SERVER_MIDDLEWARE {
+                command = middleware(&command);
+            }
+
+            let debug_str = String::from_utf8_lossy(&command)
                 .replace('\n', "\\n")
                 .replace('\r', "\\r")
                 .replace('\t', "\\t");
             debug!("<<< {}", debug_str);
 
             // Write decrypted data to client
                 .replace('\n', "\\n")
                 .replace('\r', "\\r")
                 .replace('\t', "\\t");
             debug!("<<< {}", debug_str);
 
             // Write decrypted data to client
-            if client_writer.write_all(&buffer[..bytes_read]).is_err() {
+            if client_writer.write_all(&command).is_err() {
                 debug!("<<< ERR");
                 break;
             }
                 debug!("<<< ERR");
                 break;
             }