aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMroik <mroik@delayed.space>2026-04-11 05:14:41 +0200
committerMroik <mroik@delayed.space>2026-04-13 06:56:11 +0200
commit203f02b88e75a9b604b27922aecaceb31c44d20a (patch)
tree99dc845bc8d6a5fd3a4ede70fa70b0d58390a60e
parentffc0ad7c86408193b213c46cbca5c0d8b60f8632 (diff)
Replace std socket IO with tokio socket IO
Since the TcpListener (and related) operations are blocking, they would prevent other tasks from running by monopolizing CPU time. This should've been done from the start but I'm not used to directly using low level primitives in an async environment as I would normally use a high level library for this, so I forgot. Signed-off-by: Mroik <mroik@delayed.space>
-rw-r--r--Cargo.lock66
-rw-r--r--Cargo.toml2
-rw-r--r--src/smtp_server.rs44
3 files changed, 78 insertions, 34 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bb34612..81bf80e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -80,10 +80,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
+name = "bytes"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+
+[[package]]
name = "cc"
-version = "1.2.58"
+version = "1.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
+checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -198,9 +204,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.93"
+version = "0.3.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "797146bb2677299a1eb6b7b50a890f4c361b29ef967addf5b2fa45dae1bb6d7d"
+checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -235,6 +241,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
+name = "mio"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -396,6 +413,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
+name = "socket2"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
name = "sqlite-wasm-rs"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -440,12 +467,17 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.51.0"
+version = "1.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd"
+checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
dependencies = [
+ "bytes",
+ "libc",
+ "mio",
"pin-project-lite",
+ "socket2",
"tokio-macros",
+ "windows-sys",
]
[[package]]
@@ -478,10 +510,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
name = "wasm-bindgen"
-version = "0.2.116"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dc0882f7b5bb01ae8c5215a1230832694481c1a4be062fd410e12ea3da5b631"
+checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
dependencies = [
"cfg-if",
"once_cell",
@@ -492,9 +530,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.116"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75973d3066e01d035dbedaad2864c398df42f8dd7b1ea057c35b8407c015b537"
+checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -502,9 +540,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.116"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91af5e4be765819e0bcfee7322c14374dc821e35e72fa663a830bbc7dc199eac"
+checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -515,9 +553,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.116"
+version = "0.2.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9bf0406a78f02f336bf1e451799cca198e8acde4ffa278f0fb20487b150a633"
+checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
dependencies = [
"unicode-ident",
]
diff --git a/Cargo.toml b/Cargo.toml
index cbd5e80..d48b275 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,4 +9,4 @@ env_logger = "0.11.10"
libc = "0.2.184"
log = "0.4.29"
rusqlite = "0.39.0"
-tokio = { version = "1.51.0", features = ["macros", "rt-multi-thread", "sync"] }
+tokio = { version = "1.51.0", features = ["io-util", "macros", "net", "rt-multi-thread", "sync"] }
diff --git a/src/smtp_server.rs b/src/smtp_server.rs
index e6c0efc..2805081 100644
--- a/src/smtp_server.rs
+++ b/src/smtp_server.rs
@@ -1,10 +1,12 @@
-use std::{
- io::{BufRead, BufReader, Write},
- net::{IpAddr, SocketAddr, TcpListener, TcpStream},
-};
+use std::net::{IpAddr, SocketAddr};
use anyhow::Result;
-use tokio::{spawn, sync::mpsc::Sender};
+use tokio::{
+ io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
+ net::{TcpListener, TcpStream},
+ spawn,
+ sync::mpsc::Sender,
+};
use crate::model::Mail;
@@ -16,9 +18,9 @@ pub struct SmtpServer {
}
impl SmtpServer {
- pub fn new(ip: [u8; 4], port: u16) -> Result<Self> {
+ pub async fn new(ip: [u8; 4], port: u16) -> Result<Self> {
Ok(Self {
- listener: TcpListener::bind((IpAddr::from(ip), port))?,
+ listener: TcpListener::bind((IpAddr::from(ip), port)).await?,
running: false,
})
}
@@ -27,7 +29,7 @@ impl SmtpServer {
pub async fn run(&mut self, tx_processor: Sender<Mail>) -> Result<()> {
self.running = true;
while self.running {
- let (stream, addr) = match self.listener.accept() {
+ let (stream, addr) = match self.listener.accept().await {
Ok(v) => v,
Err(e) => match e.raw_os_error() {
Some(libc::EMFILE | libc::ENFILE) => return Err(anyhow::Error::from(e)),
@@ -68,20 +70,22 @@ struct SessionHandler {
}
impl SessionHandler {
- async fn run(mut self, stream: TcpStream) -> Result<()> {
- let mut writer = stream.try_clone()?;
- let mut r = BufReader::new(&stream);
+ async fn run(mut self, mut stream: TcpStream) -> Result<()> {
+ let (r, mut writer) = stream.split();
+ let mut reader = BufReader::new(r);
let mut buffer = String::new();
- writer.write_all(
- Reply::Ready(String::from(SERVER_NAME))
- .to_string()
- .as_bytes(),
- )?;
+ writer
+ .write_all(
+ Reply::Ready(String::from(SERVER_NAME))
+ .to_string()
+ .as_bytes(),
+ )
+ .await?;
loop {
buffer.clear();
- if r.read_line(&mut buffer)? == 0 {
+ if reader.read_line(&mut buffer).await? == 0 {
break;
}
log::debug!("Received '{}' from '{}'", buffer.trim(), self.addr);
@@ -100,13 +104,15 @@ impl SessionHandler {
let command = match Command::try_from(buffer.as_str()) {
Err(_) => {
- writer.write_all(Reply::InvalidCommand.to_string().as_bytes())?;
+ writer
+ .write_all(Reply::InvalidCommand.to_string().as_bytes())
+ .await?;
continue;
}
Ok(v) => v,
};
let res = self.apply(command).await?;
- writer.write_all(res.to_string().as_bytes())?;
+ writer.write_all(res.to_string().as_bytes()).await?;
}
log::info!("Connection closed by {}", self.addr);
XMR address: 854DmXNrxULU3ZFJVs4Wc8PFhbq29RhqHhY8W6cdWrtFN3qmooKyyeYPcDzZTNRxphhJ5UzASQfAdEMwSteVqymk28aLhqj