IMAP IDLE support for command pipelining (fixes #765)
This commit is contained in:
@@ -52,11 +52,7 @@ pub struct ImapInstance {
|
||||
}
|
||||
|
||||
pub struct Inner {
|
||||
pub greeting_plain: Vec<u8>,
|
||||
pub greeting_tls: Vec<u8>,
|
||||
|
||||
pub rate_limiter: DashMap<u32, Arc<ConcurrencyLimiters>>,
|
||||
|
||||
pub cache_account: LruCache<AccountId, Arc<Account>>,
|
||||
pub cache_mailbox: LruCache<MailboxId, Arc<MailboxState>>,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ use jmap::JMAP;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio_rustls::server::TlsStream;
|
||||
|
||||
use crate::{GREETING_WITHOUT_TLS, GREETING_WITH_TLS};
|
||||
|
||||
use super::{ImapSessionManager, Session, State};
|
||||
|
||||
impl SessionManager for ImapSessionManager {
|
||||
@@ -116,11 +118,13 @@ impl<T: SessionStream> Session<T> {
|
||||
manager: ImapSessionManager,
|
||||
) -> Result<Session<T>, ()> {
|
||||
// Write greeting
|
||||
let (is_tls, greeting) = if session.stream.is_tls() {
|
||||
(true, &manager.imap.imap_inner.greeting_tls)
|
||||
let is_tls = session.stream.is_tls();
|
||||
let greeting = if !is_tls && session.instance.acceptor.is_tls() {
|
||||
&GREETING_WITH_TLS
|
||||
} else {
|
||||
(false, &manager.imap.imap_inner.greeting_plain)
|
||||
&GREETING_WITHOUT_TLS
|
||||
};
|
||||
|
||||
if let Err(err) = session.stream.write_all(greeting).await {
|
||||
trc::event!(
|
||||
Network(trc::NetworkEvent::WriteError),
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
*/
|
||||
|
||||
use core::{ImapInstance, Inner, IMAP};
|
||||
use std::{collections::hash_map::RandomState, sync::Arc};
|
||||
use std::{
|
||||
collections::hash_map::RandomState,
|
||||
sync::{Arc, LazyLock},
|
||||
};
|
||||
|
||||
use dashmap::DashMap;
|
||||
use imap_proto::{protocol::capability::Capability, ResponseCode, StatusResponse};
|
||||
@@ -20,6 +23,22 @@ pub mod op;
|
||||
|
||||
static SERVER_GREETING: &str = "Stalwart IMAP4rev2 at your service.";
|
||||
|
||||
pub(crate) static GREETING_WITH_TLS: LazyLock<Vec<u8>> = LazyLock::new(|| {
|
||||
StatusResponse::ok(SERVER_GREETING)
|
||||
.with_code(ResponseCode::Capability {
|
||||
capabilities: Capability::all_capabilities(false, true),
|
||||
})
|
||||
.into_bytes()
|
||||
});
|
||||
|
||||
pub(crate) static GREETING_WITHOUT_TLS: LazyLock<Vec<u8>> = LazyLock::new(|| {
|
||||
StatusResponse::ok(SERVER_GREETING)
|
||||
.with_code(ResponseCode::Capability {
|
||||
capabilities: Capability::all_capabilities(false, false),
|
||||
})
|
||||
.into_bytes()
|
||||
});
|
||||
|
||||
impl IMAP {
|
||||
pub async fn init(config: &mut Config, jmap_instance: JmapInstance) -> ImapInstance {
|
||||
let shard_amount = config
|
||||
@@ -29,16 +48,6 @@ impl IMAP {
|
||||
let capacity = config.property("cache.capacity").unwrap_or(100);
|
||||
|
||||
let inner = Inner {
|
||||
greeting_plain: StatusResponse::ok(SERVER_GREETING)
|
||||
.with_code(ResponseCode::Capability {
|
||||
capabilities: Capability::all_capabilities(false, false),
|
||||
})
|
||||
.into_bytes(),
|
||||
greeting_tls: StatusResponse::ok(SERVER_GREETING)
|
||||
.with_code(ResponseCode::Capability {
|
||||
capabilities: Capability::all_capabilities(false, true),
|
||||
})
|
||||
.into_bytes(),
|
||||
rate_limiter: DashMap::with_capacity_and_hasher_and_shard_amount(
|
||||
capacity,
|
||||
RandomState::default(),
|
||||
|
||||
@@ -140,7 +140,10 @@ impl<T: SessionStream> Session<T> {
|
||||
self.write_bytes(
|
||||
StatusResponse::ok("Authentication successful")
|
||||
.with_code(ResponseCode::Capability {
|
||||
capabilities: Capability::all_capabilities(true, self.is_tls),
|
||||
capabilities: Capability::all_capabilities(
|
||||
true,
|
||||
!self.is_tls && self.instance.acceptor.is_tls(),
|
||||
),
|
||||
})
|
||||
.with_tag(tag)
|
||||
.into_bytes(),
|
||||
|
||||
@@ -39,7 +39,7 @@ impl<T: SessionStream> Session<T> {
|
||||
Response {
|
||||
capabilities: Capability::all_capabilities(
|
||||
self.state.is_authenticated(),
|
||||
self.is_tls,
|
||||
!self.is_tls && self.instance.acceptor.is_tls(),
|
||||
),
|
||||
}
|
||||
.serialize(),
|
||||
|
||||
@@ -69,10 +69,10 @@ impl<T: SessionStream> Session<T> {
|
||||
);
|
||||
|
||||
let op_start = Instant::now();
|
||||
let mut buf = vec![0; 1024];
|
||||
let mut buf = vec![0; 4];
|
||||
loop {
|
||||
tokio::select! {
|
||||
result = tokio::time::timeout(self.jmap.core.imap.timeout_idle, self.stream_rx.read(&mut buf)) => {
|
||||
result = tokio::time::timeout(self.jmap.core.imap.timeout_idle, self.stream_rx.read_exact(&mut buf)) => {
|
||||
match result {
|
||||
Ok(Ok(bytes_read)) => {
|
||||
if bytes_read > 0 {
|
||||
|
||||
Reference in New Issue
Block a user