aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-02-26 23:59:29 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-02-26 23:59:29 +0100
commit3d3fd80629c804b0593692318a94dc9f344936fd (patch)
tree33514ab96c0237ad40227e276a29750d2a05a92b /src
parent0dcf69f180f5a7b71b6ad2ac67e4cdd81e5154f1 (diff)
downloadaerogramme-3d3fd80629c804b0593692318a94dc9f344936fd.tar.gz
aerogramme-3d3fd80629c804b0593692318a94dc9f344936fd.zip
Add basic DAV server
Diffstat (limited to 'src')
-rw-r--r--src/config.rs7
-rw-r--r--src/dav/mod.rs75
-rw-r--r--src/main.rs4
-rw-r--r--src/server.rs13
4 files changed, 99 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs
index faaa1ba..7de2eac 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
pub struct CompanionConfig {
pub pid: Option<PathBuf>,
pub imap: ImapUnsecureConfig,
+ // @FIXME Add DAV
#[serde(flatten)]
pub users: LoginStaticConfig,
@@ -22,6 +23,7 @@ pub struct ProviderConfig {
pub imap_unsecure: Option<ImapUnsecureConfig>,
pub lmtp: Option<LmtpConfig>,
pub auth: Option<AuthConfig>,
+ pub dav_unsecure: Option<DavUnsecureConfig>,
pub users: UserManagement,
}
@@ -52,6 +54,11 @@ pub struct ImapConfig {
}
#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct DavUnsecureConfig {
+ pub bind_addr: SocketAddr,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ImapUnsecureConfig {
pub bind_addr: SocketAddr,
}
diff --git a/src/dav/mod.rs b/src/dav/mod.rs
new file mode 100644
index 0000000..36d154a
--- /dev/null
+++ b/src/dav/mod.rs
@@ -0,0 +1,75 @@
+use std::net::SocketAddr;
+
+use anyhow::Result;
+use hyper::service::service_fn;
+use hyper::{Request, Response, body::Bytes};
+use hyper::server::conn::http1 as http;
+use hyper_util::rt::TokioIo;
+use http_body_util::Full;
+use futures::stream::{FuturesUnordered, StreamExt};
+use tokio::net::TcpListener;
+use tokio::sync::watch;
+
+use crate::config::DavUnsecureConfig;
+use crate::login::ArcLoginProvider;
+
+pub struct Server {
+ bind_addr: SocketAddr,
+ login_provider: ArcLoginProvider,
+}
+
+pub fn new_unsecure(config: DavUnsecureConfig, login: ArcLoginProvider) -> Server {
+ Server {
+ bind_addr: config.bind_addr,
+ login_provider: login,
+ }
+}
+
+impl Server {
+ pub async fn run(self: Self, mut must_exit: watch::Receiver<bool>) -> Result<()> {
+ let tcp = TcpListener::bind(self.bind_addr).await?;
+ tracing::info!("DAV server listening on {:#}", self.bind_addr);
+
+ let mut connections = FuturesUnordered::new();
+ while !*must_exit.borrow() {
+ let wait_conn_finished = async {
+ if connections.is_empty() {
+ futures::future::pending().await
+ } else {
+ connections.next().await
+ }
+ };
+ let (socket, remote_addr) = tokio::select! {
+ a = tcp.accept() => a?,
+ _ = wait_conn_finished => continue,
+ _ = must_exit.changed() => continue,
+ };
+ tracing::info!("DAV: accepted connection from {}", remote_addr);
+ let stream = TokioIo::new(socket);
+ let conn = tokio::spawn(async {
+ //@FIXME should create a generic "public web" server on which "routers" could be
+ //abitrarily bound
+ //@FIXME replace with a handler supporting http2 and TLS
+ match http::Builder::new().serve_connection(stream, service_fn(router)).await {
+ Err(e) => tracing::warn!(err=?e, "connection failed"),
+ Ok(()) => tracing::trace!("connection terminated with success"),
+ }
+ });
+ connections.push(conn);
+ }
+ drop(tcp);
+
+ tracing::info!("DAV server shutting down, draining remaining connections...");
+ while connections.next().await.is_some() {}
+
+ Ok(())
+ }
+}
+
+async fn router(req: Request<impl hyper::body::Body>) -> Result<Response<Full<Bytes>>> {
+ let url_exploded: Vec<_> = req.uri().path().split(",").collect();
+ match url_exploded {
+ _ => unimplemented!(),
+ }
+ Ok(Response::new(Full::new(Bytes::from("Hello World!"))))
+}
diff --git a/src/main.rs b/src/main.rs
index 12a5895..6e3057a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ mod auth;
mod bayou;
mod config;
mod cryptoblob;
+mod dav;
mod imap;
mod k2v_util;
mod lmtp;
@@ -187,6 +188,9 @@ async fn main() -> Result<()> {
imap_unsecure: Some(ImapUnsecureConfig {
bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 1143),
}),
+ dav_unsecure: Some(DavUnsecureConfig {
+ bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8087),
+ }),
lmtp: Some(LmtpConfig {
bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 1025),
hostname: "example.tld".to_string(),
diff --git a/src/server.rs b/src/server.rs
index 9899981..09e91ad 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -9,6 +9,7 @@ use tokio::sync::watch;
use crate::auth;
use crate::config::*;
+use crate::dav;
use crate::imap;
use crate::lmtp::*;
use crate::login::ArcLoginProvider;
@@ -19,6 +20,7 @@ pub struct Server {
imap_unsecure_server: Option<imap::Server>,
imap_server: Option<imap::Server>,
auth_server: Option<auth::AuthServer>,
+ dav_unsecure_server: Option<dav::Server>,
pid_file: Option<PathBuf>,
}
@@ -34,6 +36,7 @@ impl Server {
imap_unsecure_server,
imap_server: None,
auth_server: None,
+ dav_unsecure_server: None,
pid_file: config.pid,
})
}
@@ -57,11 +60,15 @@ impl Server {
let auth_server = config
.auth
.map(|auth| auth::AuthServer::new(auth, login.clone()));
+ let dav_unsecure_server = config
+ .dav_unsecure
+ .map(|dav_config| dav::new_unsecure(dav_config, login.clone()));
Ok(Self {
lmtp_server,
imap_unsecure_server,
imap_server,
+ dav_unsecure_server,
auth_server,
pid_file: config.pid,
})
@@ -112,6 +119,12 @@ impl Server {
None => Ok(()),
Some(a) => a.run(exit_signal.clone()).await,
}
+ },
+ async {
+ match self.dav_unsecure_server {
+ None => Ok(()),
+ Some(s) => s.run(exit_signal.clone()).await,
+ }
}
)?;