mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-10-12 05:25:52 +08:00
Added nodelay socket option
This commit is contained in:
parent
0c95388a70
commit
c8c32f3198
7 changed files with 77 additions and 32 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -5748,7 +5748,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utils"
|
name = "utils"
|
||||||
version = "0.1.0"
|
version = "0.3.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.3",
|
"ahash 0.8.3",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "utils"
|
name = "utils"
|
||||||
version = "0.1.0"
|
version = "0.3.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
use std::{net::SocketAddr, sync::Arc};
|
||||||
|
|
||||||
use rustls::{
|
use rustls::{
|
||||||
cipher_suite::{
|
cipher_suite::{
|
||||||
|
@ -209,8 +209,6 @@ impl Config {
|
||||||
TcpSocket::new_v6()
|
TcpSocket::new_v6()
|
||||||
}
|
}
|
||||||
.map_err(|err| format!("Failed to create socket: {err}"))?;
|
.map_err(|err| format!("Failed to create socket: {err}"))?;
|
||||||
let mut backlog = None;
|
|
||||||
let mut ttl = None;
|
|
||||||
|
|
||||||
// Set socket options
|
// Set socket options
|
||||||
for option in [
|
for option in [
|
||||||
|
@ -218,10 +216,7 @@ impl Config {
|
||||||
"reuse-port",
|
"reuse-port",
|
||||||
"send-buffer-size",
|
"send-buffer-size",
|
||||||
"recv-buffer-size",
|
"recv-buffer-size",
|
||||||
"linger",
|
|
||||||
"tos",
|
"tos",
|
||||||
"backlog",
|
|
||||||
"ttl",
|
|
||||||
] {
|
] {
|
||||||
if let Some(value) = self.value_or_default(
|
if let Some(value) = self.value_or_default(
|
||||||
("server.listener", id, "socket", option),
|
("server.listener", id, "socket", option),
|
||||||
|
@ -234,18 +229,7 @@ impl Config {
|
||||||
"reuse-port" => socket.set_reuseport(value.parse_key(key)?),
|
"reuse-port" => socket.set_reuseport(value.parse_key(key)?),
|
||||||
"send-buffer-size" => socket.set_send_buffer_size(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)?),
|
"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)?),
|
"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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
@ -257,8 +241,24 @@ impl Config {
|
||||||
listeners.push(Listener {
|
listeners.push(Listener {
|
||||||
socket,
|
socket,
|
||||||
addr,
|
addr,
|
||||||
ttl,
|
ttl: self.property_or_default(
|
||||||
backlog,
|
("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 {
|
data: match protocol {
|
||||||
ServerProtocol::Smtp | ServerProtocol::Lmtp => self
|
ServerProtocol::Smtp | ServerProtocol::Lmtp => self
|
||||||
.value_or_default(("server.listener", id, "greeting"), "server.greeting")
|
.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(),
|
.to_string(),
|
||||||
|
|
||||||
ServerProtocol::Jmap => self
|
ServerProtocol::Jmap => self
|
||||||
|
|
|
@ -68,8 +68,12 @@ pub struct Servers {
|
||||||
pub struct Listener {
|
pub struct Listener {
|
||||||
pub socket: TcpSocket,
|
pub socket: TcpSocket,
|
||||||
pub addr: SocketAddr,
|
pub addr: SocketAddr,
|
||||||
pub ttl: Option<u32>,
|
|
||||||
pub backlog: 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)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
|
||||||
|
|
|
@ -70,6 +70,11 @@ impl Server {
|
||||||
);
|
);
|
||||||
let local_ip = listener.addr.ip();
|
let local_ip = listener.addr.ip();
|
||||||
|
|
||||||
|
// Obtain TCP options
|
||||||
|
let nodelay = listener.nodelay;
|
||||||
|
let ttl = listener.ttl;
|
||||||
|
let linger = listener.linger;
|
||||||
|
|
||||||
// Bind socket
|
// Bind socket
|
||||||
let listener = listener.listen();
|
let listener = listener.listen();
|
||||||
|
|
||||||
|
@ -93,6 +98,36 @@ impl Server {
|
||||||
remote.port = remote_addr.port(),
|
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
|
// Spawn connection
|
||||||
manager.spawn(SessionData {
|
manager.spawn(SessionData {
|
||||||
stream,
|
stream,
|
||||||
|
@ -179,16 +214,9 @@ impl Servers {
|
||||||
|
|
||||||
impl Listener {
|
impl Listener {
|
||||||
pub fn listen(self) -> TcpListener {
|
pub fn listen(self) -> TcpListener {
|
||||||
let listener = self
|
self.socket
|
||||||
.socket
|
|
||||||
.listen(self.backlog.unwrap_or(1024))
|
.listen(self.backlog.unwrap_or(1024))
|
||||||
.unwrap_or_else(|err| failed(&format!("Failed to listen on {}: {}", self.addr, err)));
|
.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ certificate = "default"
|
||||||
ignore-client-order = true
|
ignore-client-order = true
|
||||||
|
|
||||||
[server.socket]
|
[server.socket]
|
||||||
|
nodelay = true
|
||||||
reuse-addr = true
|
reuse-addr = true
|
||||||
#reuse-port = true
|
#reuse-port = true
|
||||||
backlog = 1024
|
backlog = 1024
|
||||||
|
|
|
@ -438,6 +438,8 @@ fn parse_servers() {
|
||||||
addr: "127.0.0.1:9925".parse().unwrap(),
|
addr: "127.0.0.1:9925".parse().unwrap(),
|
||||||
ttl: 3600.into(),
|
ttl: 3600.into(),
|
||||||
backlog: 1024.into(),
|
backlog: 1024.into(),
|
||||||
|
linger: None,
|
||||||
|
nodelay: true,
|
||||||
}],
|
}],
|
||||||
tls: None,
|
tls: None,
|
||||||
tls_implicit: false,
|
tls_implicit: false,
|
||||||
|
@ -455,12 +457,16 @@ fn parse_servers() {
|
||||||
addr: "127.0.0.1:9465".parse().unwrap(),
|
addr: "127.0.0.1:9465".parse().unwrap(),
|
||||||
ttl: 4096.into(),
|
ttl: 4096.into(),
|
||||||
backlog: 1024.into(),
|
backlog: 1024.into(),
|
||||||
|
linger: None,
|
||||||
|
nodelay: true,
|
||||||
},
|
},
|
||||||
Listener {
|
Listener {
|
||||||
socket: TcpSocket::new_v4().unwrap(),
|
socket: TcpSocket::new_v4().unwrap(),
|
||||||
addr: "127.0.0.1:9466".parse().unwrap(),
|
addr: "127.0.0.1:9466".parse().unwrap(),
|
||||||
ttl: 4096.into(),
|
ttl: 4096.into(),
|
||||||
backlog: 1024.into(),
|
backlog: 1024.into(),
|
||||||
|
linger: None,
|
||||||
|
nodelay: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
tls: None,
|
tls: None,
|
||||||
|
@ -478,6 +484,8 @@ fn parse_servers() {
|
||||||
addr: "127.0.0.1:9991".parse().unwrap(),
|
addr: "127.0.0.1:9991".parse().unwrap(),
|
||||||
ttl: 3600.into(),
|
ttl: 3600.into(),
|
||||||
backlog: 2048.into(),
|
backlog: 2048.into(),
|
||||||
|
linger: None,
|
||||||
|
nodelay: true,
|
||||||
}],
|
}],
|
||||||
tls: None,
|
tls: None,
|
||||||
tls_implicit: true,
|
tls_implicit: true,
|
||||||
|
|
Loading…
Add table
Reference in a new issue