From 62db7d7f3221d9fd7584a9e18318e58a0eaaf84f Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 5 Jan 2021 17:05:56 +0200 Subject: [PATCH] melib/jmap: put JmapSession behind mutex And deserialize API urls to Arc. --- melib/src/backends/jmap.rs | 17 +++++++---- melib/src/backends/jmap/connection.rs | 14 ++++----- melib/src/backends/jmap/operations.rs | 5 ++-- melib/src/backends/jmap/protocol.rs | 9 ++++-- melib/src/backends/jmap/rfc8620.rs | 41 ++++++++++++++------------- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs index ed8d7c73a..1a5a23ab6 100644 --- a/melib/src/backends/jmap.rs +++ b/melib/src/backends/jmap.rs @@ -391,10 +391,14 @@ impl MailBackend for JmapType { * 1. upload binary blob, get blobId * 2. Email/import */ + let (api_url, upload_url) = { + let lck = conn.session.lock().unwrap(); + (lck.api_url.clone(), lck.upload_url.clone()) + }; let mut res = conn .client .post_async( - &upload_request_format(&conn.session, conn.mail_account_id()), + &upload_request_format(upload_url.as_str(), &conn.mail_account_id()), bytes, ) .await?; @@ -432,7 +436,7 @@ impl MailBackend for JmapType { req.add_call(&import_call); let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; @@ -502,10 +506,11 @@ impl MailBackend for JmapType { let mut req = Request::new(conn.request_no.clone()); req.add_call(&email_call); + let api_url = conn.session.lock().unwrap().api_url.clone(); let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; @@ -587,6 +592,7 @@ impl MailBackend for JmapType { } } let conn = connection.lock().await; + let api_url = conn.session.lock().unwrap().api_url.clone(); let email_set_call: EmailSet = EmailSet::new( Set::::new() @@ -599,7 +605,7 @@ impl MailBackend for JmapType { let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; @@ -697,10 +703,11 @@ impl MailBackend for JmapType { ); req.add_call(&email_call); + let api_url = conn.session.lock().unwrap().api_url.clone(); //debug!(serde_json::to_string(&req)?); let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; diff --git a/melib/src/backends/jmap/connection.rs b/melib/src/backends/jmap/connection.rs index 5447b9147..8f5e506fe 100644 --- a/melib/src/backends/jmap/connection.rs +++ b/melib/src/backends/jmap/connection.rs @@ -24,7 +24,7 @@ use isahc::config::Configurable; #[derive(Debug)] pub struct JmapConnection { - pub session: JmapSession, + pub session: Arc>, pub request_no: Arc>, pub client: Arc, pub server_conf: JmapServerConf, @@ -44,7 +44,7 @@ impl JmapConnection { .build()?; let server_conf = server_conf.clone(); Ok(JmapConnection { - session: Default::default(), + session: Arc::new(Mutex::new(Default::default())), request_no: Arc::new(Mutex::new(0)), client: Arc::new(client), server_conf, @@ -97,12 +97,12 @@ impl JmapConnection { } *self.store.online_status.lock().await = (Instant::now(), Ok(())); - self.session = session; + *self.session.lock().unwrap() = session; Ok(()) } - pub fn mail_account_id(&self) -> &Id { - &self.session.primary_accounts["urn:ietf:params:jmap:mail"] + pub fn mail_account_id(&self) -> Id { + self.session.lock().unwrap().primary_accounts["urn:ietf:params:jmap:mail"].clone() } pub fn add_refresh_event(&self, event: RefreshEvent) { @@ -123,7 +123,6 @@ impl JmapConnection { return Ok(()); }; loop { - let email_changes_call: EmailChanges = EmailChanges::new( Changes::::new() .account_id(self.mail_account_id().clone()) @@ -172,9 +171,10 @@ impl JmapConnection { } else { return Ok(()); } + let api_url = self.session.lock().unwrap().api_url.clone(); let mut res = self .client - .post_async(&self.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; diff --git a/melib/src/backends/jmap/operations.rs b/melib/src/backends/jmap/operations.rs index 6358c71e9..e5ae2abb7 100644 --- a/melib/src/backends/jmap/operations.rs +++ b/melib/src/backends/jmap/operations.rs @@ -60,11 +60,12 @@ impl BackendOp for JmapOp { let blob_id = store.blob_id_store.lock().unwrap()[&hash].clone(); let mut conn = connection.lock().await; conn.connect().await?; + let download_url = conn.session.lock().unwrap().download_url.clone(); let mut res = conn .client .get_async(&download_request_format( - &conn.session, - conn.mail_account_id(), + download_url.as_str(), + &conn.mail_account_id(), &blob_id, None, )) diff --git a/melib/src/backends/jmap/protocol.rs b/melib/src/backends/jmap/protocol.rs index 93a2c4f67..f15bc2bf4 100644 --- a/melib/src/backends/jmap/protocol.rs +++ b/melib/src/backends/jmap/protocol.rs @@ -86,10 +86,11 @@ pub struct JsonResponse<'a> { pub async fn get_mailboxes(conn: &JmapConnection) -> Result> { let seq = get_request_no!(conn.request_no); + let api_url = conn.session.lock().unwrap().api_url.clone(); let mut res = conn .client .post_async( - &conn.session.api_url, + api_url.as_str(), serde_json::to_string(&json!({ "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], "methodCalls": [["Mailbox/get", { @@ -178,9 +179,10 @@ pub async fn get_message_list( let mut req = Request::new(conn.request_no.clone()); req.add_call(&email_call); + let api_url = conn.session.lock().unwrap().api_url.clone(); let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; @@ -249,9 +251,10 @@ pub async fn fetch( req.add_call(&email_call); + let api_url = conn.session.lock().unwrap().api_url.clone(); let mut res = conn .client - .post_async(&conn.session.api_url, serde_json::to_string(&req)?) + .post_async(api_url.as_str(), serde_json::to_string(&req)?) .await?; let res_text = res.text_async().await?; diff --git a/melib/src/backends/jmap/rfc8620.rs b/melib/src/backends/jmap/rfc8620.rs index 91b879195..bf6d57243 100644 --- a/melib/src/backends/jmap/rfc8620.rs +++ b/melib/src/backends/jmap/rfc8620.rs @@ -25,6 +25,7 @@ use serde::de::DeserializeOwned; use serde::ser::{Serialize, SerializeStruct, Serializer}; use serde_json::{value::RawValue, Value}; use std::hash::{Hash, Hasher}; +use std::sync::Arc; mod filters; pub use filters::*; @@ -208,11 +209,11 @@ pub struct JmapSession { pub accounts: HashMap, Account>, pub primary_accounts: HashMap>, pub username: String, - pub api_url: String, - pub download_url: String, + pub api_url: Arc, + pub download_url: Arc, - pub upload_url: String, - pub event_source_url: String, + pub upload_url: Arc, + pub event_source_url: Arc, pub state: State, #[serde(flatten)] pub extra_properties: HashMap, @@ -930,49 +931,49 @@ impl core::fmt::Display for SetError { } pub fn download_request_format( - session: &JmapSession, + download_url: &str, account_id: &Id, blob_id: &Id, name: Option, ) -> String { // https://jmap.fastmail.com/download/{accountId}/{blobId}/{name} let mut ret = String::with_capacity( - session.download_url.len() + download_url.len() + blob_id.len() + name.as_ref().map(|n| n.len()).unwrap_or(0) + account_id.len(), ); let mut prev_pos = 0; - while let Some(pos) = session.download_url.as_bytes()[prev_pos..].find(b"{") { - ret.push_str(&session.download_url[prev_pos..prev_pos + pos]); + while let Some(pos) = download_url.as_bytes()[prev_pos..].find(b"{") { + ret.push_str(&download_url[prev_pos..prev_pos + pos]); prev_pos += pos; - if session.download_url[prev_pos..].starts_with("{accountId}") { + if download_url[prev_pos..].starts_with("{accountId}") { ret.push_str(account_id.as_str()); prev_pos += "{accountId}".len(); - } else if session.download_url[prev_pos..].starts_with("{blobId}") { + } else if download_url[prev_pos..].starts_with("{blobId}") { ret.push_str(blob_id.as_str()); prev_pos += "{blobId}".len(); - } else if session.download_url[prev_pos..].starts_with("{name}") { + } else if download_url[prev_pos..].starts_with("{name}") { ret.push_str(name.as_ref().map(String::as_str).unwrap_or("")); prev_pos += "{name}".len(); } } - if prev_pos != session.download_url.len() { - ret.push_str(&session.download_url[prev_pos..]); + if prev_pos != download_url.len() { + ret.push_str(&download_url[prev_pos..]); } ret } -pub fn upload_request_format(session: &JmapSession, account_id: &Id) -> String { +pub fn upload_request_format(upload_url: &str, account_id: &Id) -> String { //"uploadUrl": "https://jmap.fastmail.com/upload/{accountId}/", - let mut ret = String::with_capacity(session.upload_url.len() + account_id.len()); + let mut ret = String::with_capacity(upload_url.len() + account_id.len()); let mut prev_pos = 0; - while let Some(pos) = session.upload_url.as_bytes()[prev_pos..].find(b"{") { - ret.push_str(&session.upload_url[prev_pos..prev_pos + pos]); + while let Some(pos) = upload_url.as_bytes()[prev_pos..].find(b"{") { + ret.push_str(&upload_url[prev_pos..prev_pos + pos]); prev_pos += pos; - if session.upload_url[prev_pos..].starts_with("{accountId}") { + if upload_url[prev_pos..].starts_with("{accountId}") { ret.push_str(account_id.as_str()); prev_pos += "{accountId}".len(); break; @@ -981,8 +982,8 @@ pub fn upload_request_format(session: &JmapSession, account_id: &Id) -> prev_pos += 1; } } - if prev_pos != session.upload_url.len() { - ret.push_str(&session.upload_url[prev_pos..]); + if prev_pos != upload_url.len() { + ret.push_str(&upload_url[prev_pos..]); } ret }