Implement imap-flow #34

Merged
quentin merged 18 commits from refactor/imap-flow into main 2024-01-02 22:44:29 +00:00
7 changed files with 58 additions and 56 deletions
Showing only changes of commit d2c3b641fe - Show all commits

View file

@ -1,8 +1,7 @@
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use boitalettres::proto::{res::body::Data as Body, Request, Response}; use imap_codec::imap_types::command::{Command, CommandBody};
use imap_codec::types::command::CommandBody; use imap_codec::imap_types::core::AString;
use imap_codec::types::core::AString; use imap_codec::imap_types::response::{Capability, Data, Status, CommandContinuationRequest};
use imap_codec::types::response::{Capability, Data, Status};
use crate::imap::flow; use crate::imap::flow;
use crate::login::ArcLoginProvider; use crate::login::ArcLoginProvider;
@ -11,12 +10,12 @@ use crate::mail::user::User;
//--- dispatching //--- dispatching
pub struct AnonymousContext<'a> { pub struct AnonymousContext<'a> {
pub req: &'a Request, pub req: &'a Command<'static>,
pub login_provider: Option<&'a ArcLoginProvider>, pub login_provider: Option<&'a ArcLoginProvider>,
} }
pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response, flow::Transition)> { pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Status, flow::Transition)> {
match &ctx.req.command.body { match &ctx.req.body {
CommandBody::Noop => Ok((Response::ok("Noop completed.")?, flow::Transition::None)), CommandBody::Noop => Ok((Response::ok("Noop completed.")?, flow::Transition::None)),
CommandBody::Capability => ctx.capability().await, CommandBody::Capability => ctx.capability().await,
CommandBody::Logout => ctx.logout().await, CommandBody::Logout => ctx.logout().await,
@ -31,7 +30,7 @@ pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response, flow::Tran
//--- Command controllers, private //--- Command controllers, private
impl<'a> AnonymousContext<'a> { impl<'a> AnonymousContext<'a> {
async fn capability(self) -> Result<(Response, flow::Transition)> { async fn capability(self) -> Result<(Status, flow::Transition)> {
let capabilities = vec![Capability::Imap4Rev1, Capability::Idle]; let capabilities = vec![Capability::Imap4Rev1, Capability::Idle];
let res = Response::ok("Server capabilities")?.with_body(Data::Capability(capabilities)); let res = Response::ok("Server capabilities")?.with_body(Data::Capability(capabilities));
Ok((res, flow::Transition::None)) Ok((res, flow::Transition::None))
@ -41,7 +40,7 @@ impl<'a> AnonymousContext<'a> {
self, self,
username: &AString, username: &AString,
password: &AString, password: &AString,
) -> Result<(Response, flow::Transition)> { ) -> Result<(Status, flow::Transition)> {
let (u, p) = ( let (u, p) = (
String::try_from(username.clone())?, String::try_from(username.clone())?,
String::try_from(password.clone())?, String::try_from(password.clone())?,
@ -81,7 +80,7 @@ impl<'a> AnonymousContext<'a> {
// C: 10 logout // C: 10 logout
// S: * BYE Logging out // S: * BYE Logging out
// S: 10 OK Logout completed. // S: 10 OK Logout completed.
async fn logout(self) -> Result<(Response, flow::Transition)> { async fn logout(self) -> Result<(Status, flow::Transition)> {
// @FIXME we should implement From<Vec<Status>> and From<Vec<ImapStatus>> in // @FIXME we should implement From<Vec<Status>> and From<Vec<ImapStatus>> in
// boitalettres/src/proto/res/body.rs // boitalettres/src/proto/res/body.rs
Ok(( Ok((

View file

@ -4,12 +4,12 @@ use std::sync::Arc;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use boitalettres::proto::res::body::Data as Body; use boitalettres::proto::res::body::Data as Body;
use boitalettres::proto::{Request, Response}; use boitalettres::proto::{Request, Response};
use imap_codec::types::command::{CommandBody, StatusAttribute}; use imap_codec::imap_types::command::{CommandBody, StatusAttribute};
use imap_codec::types::core::NonZeroBytes; use imap_codec::imap_types::core::NonZeroBytes;
use imap_codec::types::datetime::MyDateTime; use imap_codec::imap_types::datetime::MyDateTime;
use imap_codec::types::flag::{Flag, FlagNameAttribute}; use imap_codec::imap_types::flag::{Flag, FlagNameAttribute};
use imap_codec::types::mailbox::{ListMailbox, Mailbox as MailboxCodec}; use imap_codec::imap_types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
use imap_codec::types::response::{Code, Data, StatusAttributeValue}; use imap_codec::imap_types::response::{Code, Data, StatusAttributeValue};
use crate::imap::command::anonymous; use crate::imap::command::anonymous;
use crate::imap::flow; use crate::imap::flow;

View file

@ -3,14 +3,14 @@ use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
use boitalettres::proto::Request; use boitalettres::proto::Request;
use boitalettres::proto::Response; use boitalettres::proto::Response;
use imap_codec::types::command::{CommandBody, SearchKey}; use imap_codec::imap_types::command::{CommandBody, SearchKey};
use imap_codec::types::core::{Charset, NonZeroBytes}; use imap_codec::imap_types::core::{Charset, NonZeroBytes};
use imap_codec::types::datetime::MyDateTime; use imap_codec::imap_types::datetime::MyDateTime;
use imap_codec::types::fetch_attributes::MacroOrFetchAttributes; use imap_codec::imap_types::fetch_attributes::MacroOrFetchAttributes;
use imap_codec::types::flag::Flag; use imap_codec::imap_types::flag::Flag;
use imap_codec::types::mailbox::Mailbox as MailboxCodec; use imap_codec::imap_types::mailbox::Mailbox as MailboxCodec;
use imap_codec::types::response::Code; use imap_codec::imap_types::response::Code;
use imap_codec::types::sequence::SequenceSet; use imap_codec::imap_types::sequence::SequenceSet;
use crate::imap::command::authenticated; use crate::imap::command::authenticated;
use crate::imap::flow; use crate::imap::flow;

View file

@ -3,11 +3,11 @@ use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
use boitalettres::proto::Request; use boitalettres::proto::Request;
use boitalettres::proto::Response; use boitalettres::proto::Response;
use imap_codec::types::command::CommandBody; use imap_codec::imap_types::command::CommandBody;
use imap_codec::types::flag::{Flag, StoreResponse, StoreType}; use imap_codec::imap_types::flag::{Flag, StoreResponse, StoreType};
use imap_codec::types::mailbox::Mailbox as MailboxCodec; use imap_codec::imap_types::mailbox::Mailbox as MailboxCodec;
use imap_codec::types::response::Code; use imap_codec::imap_types::response::Code;
use imap_codec::types::sequence::SequenceSet; use imap_codec::imap_types::sequence::SequenceSet;
use crate::imap::command::examined; use crate::imap::command::examined;
use crate::imap::flow; use crate::imap::flow;

View file

@ -9,17 +9,17 @@ use chrono::{Offset, TimeZone, Utc};
use futures::stream::{FuturesOrdered, StreamExt}; use futures::stream::{FuturesOrdered, StreamExt};
use imap_codec::types::address::Address; use imap_codec::imap_types::address::Address;
use imap_codec::types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields}; use imap_codec::imap_types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields};
use imap_codec::types::core::{AString, Atom, IString, NString}; use imap_codec::imap_types::core::{AString, Atom, IString, NString};
use imap_codec::types::datetime::MyDateTime; use imap_codec::imap_types::datetime::MyDateTime;
use imap_codec::types::envelope::Envelope; use imap_codec::imap_types::envelope::Envelope;
use imap_codec::types::fetch_attributes::{ use imap_codec::imap_types::fetch_attributes::{
FetchAttribute, MacroOrFetchAttributes, Section as FetchSection, FetchAttribute, MacroOrFetchAttributes, Section as FetchSection,
}; };
use imap_codec::types::flag::{Flag, StoreResponse, StoreType}; use imap_codec::imap_types::flag::{Flag, StoreResponse, StoreType};
use imap_codec::types::response::{Code, Data, MessageAttribute, Status}; use imap_codec::imap_types::response::{Code, Data, MessageAttribute, Status};
use imap_codec::types::sequence::{self, SequenceSet}; use imap_codec::imap_types::sequence::{self, SequenceSet};
use eml_codec::{ use eml_codec::{
header, imf, mime, header, imf, mime,
@ -1246,7 +1246,7 @@ mod tests {
use crate::cryptoblob; use crate::cryptoblob;
use crate::mail::unique_ident; use crate::mail::unique_ident;
use imap_codec::codec::Encode; use imap_codec::codec::Encode;
use imap_codec::types::fetch_attributes::Section; use imap_codec::imap_types::fetch_attributes::Section;
use std::fs; use std::fs;
#[test] #[test]

View file

@ -6,45 +6,45 @@ mod session;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use anyhow::Result; use anyhow::Result;
use boitalettres::errors::Error as BalError; //use boitalettres::errors::Error as BalError;
use boitalettres::proto::{Request, Response}; //use boitalettres::proto::{Request, Response};
use boitalettres::server::accept::addr::AddrIncoming; //use boitalettres::server::accept::addr::AddrIncoming;
use boitalettres::server::accept::addr::AddrStream; //use boitalettres::server::accept::addr::AddrStream;
use boitalettres::server::Server as ImapServer; //use boitalettres::server::Server as ImapServer;
use futures::future::BoxFuture; use futures::future::BoxFuture;
use futures::future::FutureExt; use futures::future::FutureExt;
use tokio::sync::watch; use tokio::sync::watch;
use tower::Service;
use crate::config::ImapConfig; use crate::config::ImapConfig;
use crate::login::ArcLoginProvider; use crate::login::ArcLoginProvider;
/// Server is a thin wrapper to register our Services in BàL /// Server is a thin wrapper to register our Services in BàL
pub struct Server(ImapServer<AddrIncoming, Instance>); pub struct Server{}
pub async fn new(config: ImapConfig, login: ArcLoginProvider) -> Result<Server> { pub async fn new(config: ImapConfig, login: ArcLoginProvider) -> Result<Server> {
//@FIXME add a configuration parameter unimplemented!();
let incoming = AddrIncoming::new(config.bind_addr).await?; /* let incoming = AddrIncoming::new(config.bind_addr).await?;
tracing::info!("IMAP activated, will listen on {:#}", incoming.local_addr); tracing::info!("IMAP activated, will listen on {:#}", incoming.local_addr);
let imap = ImapServer::new(incoming).serve(Instance::new(login.clone())); let imap = ImapServer::new(incoming).serve(Instance::new(login.clone()));
Ok(Server(imap)) Ok(Server(imap))*/
} }
impl Server { impl Server {
pub async fn run(self, mut must_exit: watch::Receiver<bool>) -> Result<()> { pub async fn run(self, mut must_exit: watch::Receiver<bool>) -> Result<()> {
tracing::info!("IMAP started!"); tracing::info!("IMAP started!");
tokio::select! { unimplemented!();
/*tokio::select! {
s = self.0 => s?, s = self.0 => s?,
_ = must_exit.changed() => tracing::info!("Stopped IMAP server"), _ = must_exit.changed() => tracing::info!("Stopped IMAP server"),
} }
Ok(()) Ok(())*/
} }
} }
//--- //---
/*
/// Instance is the main Tokio Tower service that we register in BàL. /// Instance is the main Tokio Tower service that we register in BàL.
/// It receives new connection demands and spawn a dedicated service. /// It receives new connection demands and spawn a dedicated service.
struct Instance { struct Instance {
@ -103,3 +103,4 @@ impl Service<Request> for Connection {
self.session.process(req) self.session.process(req)
} }
} }
*/

View file

@ -1,6 +1,6 @@
use anyhow::Error; use anyhow::Error;
use boitalettres::errors::Error as BalError; //use boitalettres::errors::Error as BalError;
use boitalettres::proto::{Request, Response}; //use boitalettres::proto::{Request, Response};
use futures::future::BoxFuture; use futures::future::BoxFuture;
use futures::future::FutureExt; use futures::future::FutureExt;
@ -11,6 +11,7 @@ use crate::imap::command::{anonymous, authenticated, examined, selected};
use crate::imap::flow; use crate::imap::flow;
use crate::login::ArcLoginProvider; use crate::login::ArcLoginProvider;
/*
/* This constant configures backpressure in the system, /* This constant configures backpressure in the system,
* or more specifically, how many pipelined messages are allowed * or more specifically, how many pipelined messages are allowed
* before refusing them * before refusing them
@ -69,9 +70,9 @@ impl Manager {
.boxed() .boxed()
} }
} }
*/
//----- //-----
/*
pub struct Instance { pub struct Instance {
rx: mpsc::Receiver<Message>, rx: mpsc::Receiver<Message>,
@ -178,3 +179,4 @@ impl Instance {
tracing::debug!("exiting runner"); tracing::debug!("exiting runner");
} }
} }
*/