feat: Add incoming unix domain socket support
This commit is contained in:
parent
d42508b15e
commit
3331e431dd
5 changed files with 749 additions and 21 deletions
|
|
@ -1,9 +1,13 @@
|
|||
use anyhow::bail;
|
||||
use serde::Deserialize;
|
||||
use tokio_listener::{Listener, ListenerAddress, SystemOptions, UserOptions};
|
||||
|
||||
use std::net::{Ipv6Addr, SocketAddrV6};
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct Config {
|
||||
pub listen: Option<ListenerAddress>,
|
||||
pub mapping: Vec<Mapping>,
|
||||
}
|
||||
|
||||
|
|
@ -12,6 +16,47 @@ impl Config {
|
|||
let content = tokio::fs::read(path).await?;
|
||||
Ok(toml::from_slice(&content)?)
|
||||
}
|
||||
|
||||
pub async fn listener(&self) -> anyhow::Result<Listener> {
|
||||
let listener_addr = if let Some(listen) = &self.listen {
|
||||
// For now we only support ADDR:PORT and Unix domain sockets
|
||||
match listen {
|
||||
ListenerAddress::Tcp(_) => listen,
|
||||
ListenerAddress::Path(p) => {
|
||||
if tokio::fs::try_exists(p).await? {
|
||||
warn!(
|
||||
"Socket {} already exists, probably because multildap was not shut down correctly.",
|
||||
p.display()
|
||||
);
|
||||
warn!(
|
||||
"If another multildap instance is still listening on there, it will no longer receive new connections."
|
||||
);
|
||||
}
|
||||
listen
|
||||
}
|
||||
_ => {
|
||||
error!(
|
||||
"To use unix domain sockets, use relative or absolute paths, eg. `./ldap.sock` or `/var/run/ldap.sock`"
|
||||
);
|
||||
bail!("Invalid listen option, currently parsed to: {:?}", listen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// By default, listen on localhost:389 where a LDAP server usually listens.
|
||||
// Don't listen on all interfaces by default for security reasons.
|
||||
&ListenerAddress::Tcp(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 389, 0, 0).into())
|
||||
};
|
||||
|
||||
let system_options: SystemOptions = Default::default();
|
||||
let mut user_options: UserOptions = Default::default();
|
||||
// If there's a left over socket, delete it instead of erroring.
|
||||
// If another daemon is still listening over there, it will no longer
|
||||
// receive connections.
|
||||
// TODO: Unix Domain Socket garbage collection (graceful shutdown).
|
||||
user_options.unix_listen_unlink = true;
|
||||
|
||||
Ok(Listener::bind(listener_addr, &system_options, &user_options).await?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
|
|
|
|||
25
src/main.rs
25
src/main.rs
|
|
@ -6,7 +6,7 @@ use futures_util::StreamExt;
|
|||
use ldap3_proto::LdapCodec;
|
||||
use ldap3_proto::proto::*;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadHalf, WriteHalf};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::timeout;
|
||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||
|
||||
|
|
@ -190,8 +190,10 @@ pub async fn client_process<W: AsyncWrite + Unpin, R: AsyncRead + Unpin>(
|
|||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
if let Err(_) = std::env::var("RUST_LOG") {
|
||||
unsafe { std::env::set_var("RUST_LOG", "info"); }
|
||||
if std::env::var("RUST_LOG").is_err() {
|
||||
unsafe {
|
||||
std::env::set_var("RUST_LOG", "info");
|
||||
}
|
||||
}
|
||||
|
||||
pretty_env_logger::formatted_timed_builder()
|
||||
|
|
@ -211,12 +213,18 @@ async fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
let state = Arc::new(config);
|
||||
|
||||
// Let the listening port ready.
|
||||
let listener = TcpListener::bind("127.0.0.1:3389").await.unwrap();
|
||||
let mut listener = match config.listener().await {
|
||||
Ok(listener) => listener,
|
||||
Err(e) => {
|
||||
error!("Listening on port/socket failed: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
info!("Listening on {:?}", listener);
|
||||
|
||||
let state = Arc::new(config);
|
||||
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((tcpstream, client_socket_addr)) => {
|
||||
|
|
@ -226,7 +234,10 @@ async fn main() {
|
|||
let w = FramedWrite::new(w, LdapCodec::new(None, None));
|
||||
tokio::spawn(client_process(r, w, state.clone()));
|
||||
}
|
||||
Err(_e) => continue,
|
||||
Err(e) => {
|
||||
warn!("{}", e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue