Added nodelay socket option

This commit is contained in:
Mauro D 2023-08-16 19:06:57 +02:00
parent 0c95388a70
commit c8c32f3198
7 changed files with 77 additions and 32 deletions

2
Cargo.lock generated
View file

@ -5748,7 +5748,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "utils"
version = "0.1.0"
version = "0.3.4"
dependencies = [
"ahash 0.8.3",
"dashmap",

View file

@ -1,6 +1,6 @@
[package]
name = "utils"
version = "0.1.0"
version = "0.3.4"
edition = "2021"
resolver = "2"

View file

@ -21,7 +21,7 @@
* for more details.
*/
use std::{net::SocketAddr, sync::Arc, time::Duration};
use std::{net::SocketAddr, sync::Arc};
use rustls::{
cipher_suite::{
@ -209,8 +209,6 @@ impl Config {
TcpSocket::new_v6()
}
.map_err(|err| format!("Failed to create socket: {err}"))?;
let mut backlog = None;
let mut ttl = None;
// Set socket options
for option in [
@ -218,10 +216,7 @@ impl Config {
"reuse-port",
"send-buffer-size",
"recv-buffer-size",
"linger",
"tos",
"backlog",
"ttl",
] {
if let Some(value) = self.value_or_default(
("server.listener", id, "socket", option),
@ -234,18 +229,7 @@ impl Config {
"reuse-port" => socket.set_reuseport(value.parse_key(key)?),
"send-buffer-size" => socket.set_send_buffer_size(value.parse_key(key)?),
"recv-buffer-size" => socket.set_recv_buffer_size(value.parse_key(key)?),
"linger" => {
socket.set_linger(Duration::from_millis(value.parse_key(key)?).into())
}
"tos" => socket.set_tos(value.parse_key(key)?),
"backlog" => {
backlog = Some(value.parse_key(key)?);
continue;
}
"ttl" => {
ttl = Some(value.parse_key(key)?);
continue;
}
_ => unreachable!(),
}
.map_err(|err| {
@ -257,8 +241,24 @@ impl Config {
listeners.push(Listener {
socket,
addr,
ttl,
backlog,
ttl: self.property_or_default(
("server.listener", id, "socket.ttl"),
"server.socket.ttl",
)?,
backlog: self.property_or_default(
("server.listener", id, "socket.backlog"),
"server.socket.backlog",
)?,
linger: self.property_or_default(
("server.listener", id, "socket.linger"),
"server.socket.linger",
)?,
nodelay: self
.property_or_default(
("server.listener", id, "socket.nodelay"),
"server.socket.nodelay",
)?
.unwrap_or(true),
});
}
@ -278,7 +278,11 @@ impl Config {
data: match protocol {
ServerProtocol::Smtp | ServerProtocol::Lmtp => self
.value_or_default(("server.listener", id, "greeting"), "server.greeting")
.unwrap_or("Stalwart SMTP at your service")
.unwrap_or(concat!(
"Stalwart SMTP v",
env!("CARGO_PKG_VERSION"),
" at your service."
))
.to_string(),
ServerProtocol::Jmap => self

View file

@ -68,8 +68,12 @@ pub struct Servers {
pub struct Listener {
pub socket: TcpSocket,
pub addr: SocketAddr,
pub ttl: Option<u32>,
pub backlog: Option<u32>,
// TCP options
pub ttl: Option<u32>,
pub linger: Option<Duration>,
pub nodelay: bool,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]

View file

@ -70,6 +70,11 @@ impl Server {
);
let local_ip = listener.addr.ip();
// Obtain TCP options
let nodelay = listener.nodelay;
let ttl = listener.ttl;
let linger = listener.linger;
// Bind socket
let listener = listener.listen();
@ -93,6 +98,36 @@ impl Server {
remote.port = remote_addr.port(),
);
// Set TCP options
if let Err(err) = stream.set_nodelay(nodelay) {
tracing::warn!(
context = "tcp",
event = "error",
instance = instance.id,
protocol = ?instance.protocol,
"Failed to set no-delay: {}", err);
}
if let Some(ttl) = ttl {
if let Err(err) = stream.set_ttl(ttl) {
tracing::warn!(
context = "tcp",
event = "error",
instance = instance.id,
protocol = ?instance.protocol,
"Failed to set TTL: {}", err);
}
}
if linger.is_some() {
if let Err(err) = stream.set_linger(linger) {
tracing::warn!(
context = "tcp",
event = "error",
instance = instance.id,
protocol = ?instance.protocol,
"Failed to set linger: {}", err);
}
}
// Spawn connection
manager.spawn(SessionData {
stream,
@ -179,16 +214,9 @@ impl Servers {
impl Listener {
pub fn listen(self) -> TcpListener {
let listener = self
.socket
self.socket
.listen(self.backlog.unwrap_or(1024))
.unwrap_or_else(|err| failed(&format!("Failed to listen on {}: {}", self.addr, err)));
if let Some(ttl) = self.ttl {
listener.set_ttl(ttl).unwrap_or_else(|err| {
failed(&format!("Failed to set TTL on {}: {}", self.addr, err))
});
}
listener
.unwrap_or_else(|err| failed(&format!("Failed to listen on {}: {}", self.addr, err)))
}
}

View file

@ -21,6 +21,7 @@ certificate = "default"
ignore-client-order = true
[server.socket]
nodelay = true
reuse-addr = true
#reuse-port = true
backlog = 1024

View file

@ -438,6 +438,8 @@ fn parse_servers() {
addr: "127.0.0.1:9925".parse().unwrap(),
ttl: 3600.into(),
backlog: 1024.into(),
linger: None,
nodelay: true,
}],
tls: None,
tls_implicit: false,
@ -455,12 +457,16 @@ fn parse_servers() {
addr: "127.0.0.1:9465".parse().unwrap(),
ttl: 4096.into(),
backlog: 1024.into(),
linger: None,
nodelay: true,
},
Listener {
socket: TcpSocket::new_v4().unwrap(),
addr: "127.0.0.1:9466".parse().unwrap(),
ttl: 4096.into(),
backlog: 1024.into(),
linger: None,
nodelay: true,
},
],
tls: None,
@ -478,6 +484,8 @@ fn parse_servers() {
addr: "127.0.0.1:9991".parse().unwrap(),
ttl: 3600.into(),
backlog: 2048.into(),
linger: None,
nodelay: true,
}],
tls: None,
tls_implicit: true,