rename to ClientConfig

This commit is contained in:
Michael Zhang 2021-02-21 07:54:46 -06:00
parent 0b6b853662
commit 0b88df1367
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
3 changed files with 32 additions and 29 deletions

View file

@ -15,21 +15,23 @@ use tokio::{
sync::{mpsc, oneshot}, sync::{mpsc, oneshot},
task::JoinHandle, task::JoinHandle,
}; };
use tokio_rustls::{client::TlsStream, rustls::ClientConfig, webpki::DNSNameRef, TlsConnector}; use tokio_rustls::{
client::TlsStream, rustls::ClientConfig as RustlsConfig, webpki::DNSNameRef, TlsConnector,
};
use crate::command::Command; use crate::command::Command;
use crate::types::Response; use crate::types::Response;
use super::ClientNotConnected; use super::ClientConfig;
pub type BoxedFunc = Box<dyn Fn()>; pub type BoxedFunc = Box<dyn Fn()>;
pub type ResultMap = Arc<RwLock<HashMap<usize, (Option<String>, Option<Waker>)>>>; pub type ResultMap = Arc<RwLock<HashMap<usize, (Option<String>, Option<Waker>)>>>;
pub type GreetingRx = Arc<RwLock<(bool, Option<Waker>)>>; pub type GreetingState = Arc<RwLock<(bool, Option<Waker>)>>;
pub const TAG_PREFIX: &str = "panorama"; pub const TAG_PREFIX: &str = "panorama";
/// The lower-level Client struct, that is shared by all of the exported structs in the state machine. /// The lower-level Client struct, that is shared by all of the exported structs in the state machine.
pub struct Client<C> { pub struct Client<C> {
config: ClientNotConnected, config: ClientConfig,
conn: WriteHalf<C>, conn: WriteHalf<C>,
symbols: StringStore, symbols: StringStore,
@ -46,7 +48,7 @@ pub struct Client<C> {
exit_tx: mpsc::Sender<()>, exit_tx: mpsc::Sender<()>,
/// used for receiving the greeting /// used for receiving the greeting
greeting: GreetingRx, greeting: GreetingState,
} }
impl<C> Client<C> impl<C> Client<C>
@ -54,7 +56,7 @@ where
C: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{ {
/// Creates a new client that wraps a connection /// Creates a new client that wraps a connection
pub fn new(conn: C, config: ClientNotConnected) -> Self { pub fn new(conn: C, config: ClientConfig) -> Self {
let (read_half, write_half) = io::split(conn); let (read_half, write_half) = io::split(conn);
let results = Arc::new(RwLock::new(HashMap::new())); let results = Arc::new(RwLock::new(HashMap::new()));
let (exit_tx, exit_rx) = mpsc::channel(1); let (exit_tx, exit_rx) = mpsc::channel(1);
@ -79,9 +81,10 @@ where
} }
} }
pub fn wait_for_greeting(&self) -> GreetingHandler { /// Returns a future that doesn't resolve until we receive a greeting from the server.
pub fn wait_for_greeting(&self) -> GreetingWaiter {
debug!("waiting for greeting"); debug!("waiting for greeting");
GreetingHandler(self.greeting.clone()) GreetingWaiter(self.greeting.clone())
} }
/// Sends a command to the server and returns a handle to retrieve the result /// Sends a command to the server and returns a handle to retrieve the result
@ -100,7 +103,7 @@ where
self.conn.flush().await?; self.conn.flush().await?;
debug!("[{}] written.", id); debug!("[{}] written.", id);
ExecHandle(self, id).await; ExecWaiter(self, id).await;
let resp = { let resp = {
let mut handlers = self.results.write(); let mut handlers = self.results.write();
handlers.remove(&id).unwrap().0.unwrap() handlers.remove(&id).unwrap().0.unwrap()
@ -142,7 +145,7 @@ where
let server_name = &self.config.hostname; let server_name = &self.config.hostname;
let mut tls_config = ClientConfig::new(); let mut tls_config = RustlsConfig::new();
tls_config tls_config
.root_store .root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
@ -154,9 +157,9 @@ where
} }
} }
pub struct GreetingHandler(GreetingRx); pub struct GreetingWaiter(GreetingState);
impl Future for GreetingHandler { impl Future for GreetingWaiter {
type Output = (); type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let (state, waker) = &mut *self.0.write(); let (state, waker) = &mut *self.0.write();
@ -171,9 +174,9 @@ impl Future for GreetingHandler {
} }
} }
pub struct ExecHandle<'a, C>(&'a Client<C>, usize); pub struct ExecWaiter<'a, C>(&'a Client<C>, usize);
impl<'a, C> Future for ExecHandle<'a, C> { impl<'a, C> Future for ExecWaiter<'a, C> {
type Output = (); type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut handlers = self.0.results.write(); let mut handlers = self.0.results.write();
@ -198,7 +201,7 @@ async fn listen<C>(
conn: C, conn: C,
results: ResultMap, results: ResultMap,
mut exit: mpsc::Receiver<()>, mut exit: mpsc::Receiver<()>,
greeting: GreetingRx, greeting: GreetingState,
) -> Result<C> ) -> Result<C>
where where
C: AsyncRead + Unpin, C: AsyncRead + Unpin,
@ -225,7 +228,7 @@ where
if tag == "*" { if tag == "*" {
debug!("UNTAGGED {:?}", rest); debug!("UNTAGGED {:?}", rest);
// TODO: verify that the greeting is actually an OK // TODO: verify that the greeting is actually an OK
if let Some(greeting) = greeting.take() { if let Some(greeting) = greeting.take() {
let (greeting, waker) = &mut *greeting.write(); let (greeting, waker) = &mut *greeting.write();

View file

@ -15,11 +15,10 @@ mod inner;
use std::sync::Arc; use std::sync::Arc;
use anyhow::Result; use anyhow::Result;
use tokio::{ use tokio::net::TcpStream;
io::{self, AsyncRead, AsyncWrite, ReadHalf, WriteHalf}, use tokio_rustls::{
net::TcpStream, client::TlsStream, rustls::ClientConfig as RustlsConfig, webpki::DNSNameRef, TlsConnector,
}; };
use tokio_rustls::{client::TlsStream, rustls::ClientConfig, webpki::DNSNameRef, TlsConnector};
pub use self::inner::Client; pub use self::inner::Client;
@ -28,13 +27,13 @@ pub use self::inner::Client;
/// Call [`.build`][1] to _build_ the config, then run [`.connect`][2] to actually start opening /// Call [`.build`][1] to _build_ the config, then run [`.connect`][2] to actually start opening
/// the connection to the server. /// the connection to the server.
/// ///
/// [1]: self::ClientNotConnectedBuilder::build /// [1]: self::ClientConfigBuilder::build
/// [2]: self::ClientNotConnected::connect /// [2]: self::ClientConfig::connect
pub type ClientBuilder = ClientNotConnectedBuilder; pub type ClientBuilder = ClientConfigBuilder;
/// An IMAP client that hasn't been connected yet. /// An IMAP client that hasn't been connected yet.
#[derive(Builder, Clone, Debug)] #[derive(Builder, Clone, Debug)]
pub struct ClientNotConnected { pub struct ClientConfig {
/// The hostname of the IMAP server. If using TLS, must be an address /// The hostname of the IMAP server. If using TLS, must be an address
hostname: String, hostname: String,
@ -47,14 +46,14 @@ pub struct ClientNotConnected {
tls: bool, tls: bool,
} }
impl ClientNotConnected { impl ClientConfig {
pub async fn open(self) -> Result<ClientUnauthenticated> { pub async fn open(self) -> Result<ClientUnauthenticated> {
let hostname = self.hostname.as_ref(); let hostname = self.hostname.as_ref();
let port = self.port; let port = self.port;
let conn = TcpStream::connect((hostname, port)).await?; let conn = TcpStream::connect((hostname, port)).await?;
if self.tls { if self.tls {
let mut tls_config = ClientConfig::new(); let mut tls_config = RustlsConfig::new();
tls_config tls_config
.root_store .root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);

View file

@ -6,7 +6,7 @@ mod imap2;
use anyhow::Result; use anyhow::Result;
use futures::stream::StreamExt; use futures::stream::StreamExt;
use panorama_imap::{ use panorama_imap::{
client::{ClientBuilder, ClientNotConnected}, client::{ClientBuilder, ClientConfig},
command::Command as ImapCommand, command::Command as ImapCommand,
}; };
use tokio::{sync::mpsc::UnboundedReceiver, task::JoinHandle}; use tokio::{sync::mpsc::UnboundedReceiver, task::JoinHandle};
@ -69,7 +69,7 @@ pub async fn run_mail(
/// The main sequence of steps for the IMAP thread to follow /// The main sequence of steps for the IMAP thread to follow
async fn imap_main(acct: MailAccountConfig) -> Result<()> { async fn imap_main(acct: MailAccountConfig) -> Result<()> {
let builder: ClientNotConnected = ClientBuilder::default() let builder: ClientConfig = ClientBuilder::default()
.hostname(acct.imap.server.clone()) .hostname(acct.imap.server.clone())
.port(acct.imap.port) .port(acct.imap.port)
.tls(matches!(acct.imap.tls, TlsMethod::On)) .tls(matches!(acct.imap.tls, TlsMethod::On))
@ -79,7 +79,7 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
debug!("connecting to {}:{}", &acct.imap.server, acct.imap.port); debug!("connecting to {}:{}", &acct.imap.server, acct.imap.port);
let unauth = builder.open().await?; let unauth = builder.open().await?;
let unauth = if matches!(acct.imap.tls, TlsMethod::Starttls) { let mut unauth = if matches!(acct.imap.tls, TlsMethod::Starttls) {
debug!("attempting to upgrade"); debug!("attempting to upgrade");
let client = unauth.upgrade().await?; let client = unauth.upgrade().await?;
debug!("upgrade successful"); debug!("upgrade successful");
@ -90,6 +90,7 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
debug!("preparing to auth"); debug!("preparing to auth");
// check if the authentication method is supported // check if the authentication method is supported
unauth.capabilities().await?;
// debug!("sending CAPABILITY"); // debug!("sending CAPABILITY");
// let result = unauth.capabilities().await?; // let result = unauth.capabilities().await?;