back to stable async-std + use surf instead of reqwest

removes tokio from our dependency tree, now only one async executor
This commit is contained in:
dignifiedquire
2020-05-22 11:10:26 +02:00
parent c43e7cdbdc
commit 70a2dbb4bb
10 changed files with 258 additions and 445 deletions

View File

@@ -94,12 +94,12 @@ fn parse_xml(in_emailaddr: &str, xml_raw: &str) -> Result<LoginParam, Error> {
}
}
pub fn moz_autoconfigure(
pub async fn moz_autoconfigure(
context: &Context,
url: &str,
param_in: &LoginParam,
) -> Result<LoginParam, Error> {
let xml_raw = read_url(context, url)?;
let xml_raw = read_url(context, url).await?;
let res = parse_xml(&param_in.addr, &xml_raw);
if let Err(err) = &res {

View File

@@ -112,7 +112,7 @@ fn parse_xml(xml_raw: &str) -> Result<ParsingResult, Error> {
Ok(res)
}
pub fn outlk_autodiscover(
pub async fn outlk_autodiscover(
context: &Context,
url: &str,
_param_in: &LoginParam,
@@ -120,7 +120,7 @@ pub fn outlk_autodiscover(
let mut url = url.to_string();
/* Follow up to 10 xml-redirects (http-redirects are followed in read_url() */
for _i in 0..10 {
let xml_raw = read_url(context, &url)?;
let xml_raw = read_url(context, &url).await?;
let res = parse_xml(&xml_raw);
if let Err(err) = &res {
warn!(context, "{}", err);

View File

@@ -248,7 +248,7 @@ async fn exec_step(
"https://autoconfig.{}/mail/config-v1.1.xml?emailaddress={}",
param_domain, param_addr_urlencoded
);
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).ok();
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).await.ok();
}
}
6 => {
@@ -259,7 +259,7 @@ async fn exec_step(
"https://{}/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress={}",
param_domain, param_addr_urlencoded
);
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).ok();
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).await.ok();
}
}
/* Outlook section start ------------- */
@@ -268,7 +268,7 @@ async fn exec_step(
progress!(ctx, 310);
if param_autoconfig.is_none() {
let url = format!("https://{}/autodiscover/autodiscover.xml", param_domain);
*param_autoconfig = outlk_autodiscover(ctx, &url, &param).ok();
*param_autoconfig = outlk_autodiscover(ctx, &url, &param).await.ok();
}
}
8 => {
@@ -278,7 +278,7 @@ async fn exec_step(
"https://{}{}/autodiscover/autodiscover.xml",
"autodiscover.", param_domain
);
*param_autoconfig = outlk_autodiscover(ctx, &url, &param).ok();
*param_autoconfig = outlk_autodiscover(ctx, &url, &param).await.ok();
}
}
/* ----------- Outlook section end */
@@ -289,7 +289,7 @@ async fn exec_step(
"http://autoconfig.{}/mail/config-v1.1.xml?emailaddress={}",
param_domain, param_addr_urlencoded
);
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).ok();
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).await.ok();
}
}
10 => {
@@ -300,7 +300,7 @@ async fn exec_step(
"http://{}/.well-known/autoconfig/mail/config-v1.1.xml",
param_domain
);
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).ok();
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).await.ok();
}
}
/* B. If we have no configuration yet, search configuration in Thunderbird's centeral database */
@@ -309,7 +309,7 @@ async fn exec_step(
if param_autoconfig.is_none() {
/* always SSL for Thunderbird's database */
let url = format!("https://autoconfig.thunderbird.net/v1.1/{}", param_domain);
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).ok();
*param_autoconfig = moz_autoconfigure(ctx, &url, &param).await.ok();
}
}
/* C. Do we have any autoconfig result?

View File

@@ -3,17 +3,13 @@ use crate::context::Context;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("URL request error")]
GetError(#[from] reqwest::Error),
GetError(surf::Error),
}
pub fn read_url(context: &Context, url: &str) -> Result<String, Error> {
pub async fn read_url(context: &Context, url: &str) -> Result<String, Error> {
info!(context, "Requesting URL {}", url);
match reqwest::blocking::Client::new()
.get(url)
.send()
.and_then(|res| res.text())
{
match surf::get(url).recv_string().await {
Ok(res) => Ok(res),
Err(err) => {
info!(context, "Can\'t read URL {}", url);

View File

@@ -161,10 +161,7 @@ pub async fn dc_get_oauth2_access_token(
}
// ... and POST
let response = reqwest::blocking::Client::new()
.post(post_url)
.form(&post_param)
.send();
let response = surf::post(post_url).body_form(&post_param);
if response.is_err() {
warn!(
context,
@@ -172,19 +169,8 @@ pub async fn dc_get_oauth2_access_token(
);
return None;
}
let response = response.unwrap();
if !response.status().is_success() {
warn!(
context,
"Unsuccessful response when calling OAuth2 at {}: {:?}",
token_url,
response.status()
);
return None;
}
// generate new token: parse returned json
let parsed: reqwest::Result<Response> = response.json();
let parsed: Result<Response, _> = response.unwrap().recv_json().await;
if parsed.is_err() {
warn!(
context,
@@ -192,7 +178,6 @@ pub async fn dc_get_oauth2_access_token(
);
return None;
}
println!("response: {:?}", &parsed);
// update refresh_token if given, typically on the first round, but we update it later as well.
let response = parsed.unwrap();
@@ -260,12 +245,12 @@ pub async fn dc_get_oauth2_addr(
if let Some(access_token) =
dc_get_oauth2_access_token(context, addr.as_ref(), code.as_ref(), false).await
{
let addr_out = oauth2.get_addr(context, access_token);
let addr_out = oauth2.get_addr(context, access_token).await;
if addr_out.is_none() {
// regenerate
if let Some(access_token) = dc_get_oauth2_access_token(context, addr, code, true).await
{
oauth2.get_addr(context, access_token)
oauth2.get_addr(context, access_token).await
} else {
None
}
@@ -295,7 +280,7 @@ impl Oauth2 {
}
}
fn get_addr(&self, context: &Context, access_token: impl AsRef<str>) -> Option<String> {
async fn get_addr(&self, context: &Context, access_token: impl AsRef<str>) -> Option<String> {
let userinfo_url = self.get_userinfo.unwrap_or_else(|| "");
let userinfo_url = replace_in_uri(&userinfo_url, "$ACCESS_TOKEN", access_token);
@@ -306,41 +291,25 @@ impl Oauth2 {
// "verified_email": true,
// "picture": "https://lh4.googleusercontent.com/-Gj5jh_9R0BY/AAAAAAAAAAI/AAAAAAAAAAA/IAjtjfjtjNA/photo.jpg"
// }
let response = reqwest::blocking::Client::new().get(&userinfo_url).send();
let response: Result<HashMap<String, serde_json::Value>, surf::Error> =
surf::get(userinfo_url).recv_json().await;
if response.is_err() {
warn!(context, "Error getting userinfo: {:?}", response);
return None;
}
let response = response.unwrap();
if !response.status().is_success() {
warn!(context, "Error getting userinfo: {:?}", response.status());
return None;
}
let parsed: reqwest::Result<HashMap<String, serde_json::Value>> = response.json();
if parsed.is_err() {
warn!(
context,
"Failed to parse userinfo JSON response: {:?}", parsed
);
return None;
}
if let Ok(response) = parsed {
// CAVE: serde_json::Value.as_str() removes the quotes of json-strings
// but serde_json::Value.to_string() does not!
if let Some(addr) = response.get("email") {
if let Some(s) = addr.as_str() {
Some(s.to_string())
} else {
warn!(context, "E-mail in userinfo is not a string: {}", addr);
None
}
let parsed = response.unwrap();
// CAVE: serde_json::Value.as_str() removes the quotes of json-strings
// but serde_json::Value.to_string() does not!
if let Some(addr) = parsed.get("email") {
if let Some(s) = addr.as_str() {
Some(s.to_string())
} else {
warn!(context, "E-mail missing in userinfo.");
warn!(context, "E-mail in userinfo is not a string: {}", addr);
None
}
} else {
warn!(context, "Failed to parse userinfo.");
warn!(context, "E-mail missing in userinfo.");
None
}
}

View File

@@ -2,7 +2,6 @@
use lazy_static::lazy_static;
use percent_encoding::percent_decode_str;
use reqwest::Url;
use serde::Deserialize;
use crate::chat;
@@ -193,7 +192,7 @@ fn decode_account(_context: &Context, qr: &str) -> Lot {
let mut lot = Lot::new();
if let Ok(url) = Url::parse(payload) {
if let Ok(url) = url::Url::parse(payload) {
if url.scheme() == "https" {
lot.state = LotState::QrAccount;
lot.text1 = url.host_str().map(|x| x.to_string());
@@ -221,25 +220,12 @@ struct CreateAccountResponse {
pub async fn set_config_from_qr(context: &Context, qr: &str) -> Result<(), Error> {
let url_str = &qr[DCACCOUNT_SCHEME.len()..];
let response = reqwest::blocking::Client::new().post(url_str).send();
let response: Result<CreateAccountResponse, surf::Error> =
surf::post(url_str).recv_json().await;
if response.is_err() {
bail!("Cannot create account, request to {} failed", url_str);
}
let response = response.unwrap();
if !response.status().is_success() {
bail!("Request to {} unsuccessful: {:?}", url_str, response);
}
let parsed: reqwest::Result<CreateAccountResponse> = response.json();
if parsed.is_err() {
bail!(
"Failed to parse JSON response from {}: error: {:?}",
url_str,
parsed
);
}
println!("response: {:?}", &parsed);
let parsed = parsed.unwrap();
let parsed = response.unwrap();
context
.set_config(Config::Addr, Some(&parsed.email))

View File

@@ -341,12 +341,10 @@ impl Scheduler {
// wait for all loops to be started
inbox_start_recv
.recv()
.try_join(mvbox_start_recv.recv())
.try_join(sentbox_start_recv.recv())
.try_join(smtp_start_recv.recv())
.await
.map(|_| ())
.unwrap_or_else(|err| error!(ctx, "failed to start scheduler: {}", err));
.join(mvbox_start_recv.recv())
.join(sentbox_start_recv.recv())
.join(smtp_start_recv.recv())
.await;
info!(ctx, "scheduler is running");
}
@@ -384,36 +382,28 @@ impl Scheduler {
async fn interrupt_inbox(&self) {
match self {
Scheduler::Running { ref inbox, .. } => {
inbox.interrupt().await.ok();
}
Scheduler::Running { ref inbox, .. } => inbox.interrupt().await,
_ => {}
}
}
async fn interrupt_mvbox(&self) {
match self {
Scheduler::Running { ref mvbox, .. } => {
mvbox.interrupt().await.ok();
}
Scheduler::Running { ref mvbox, .. } => mvbox.interrupt().await,
_ => {}
}
}
async fn interrupt_sentbox(&self) {
match self {
Scheduler::Running { ref sentbox, .. } => {
sentbox.interrupt().await.ok();
}
Scheduler::Running { ref sentbox, .. } => sentbox.interrupt().await,
_ => {}
}
}
async fn interrupt_smtp(&self) {
match self {
Scheduler::Running { ref smtp, .. } => {
smtp.interrupt().await.ok();
}
Scheduler::Running { ref smtp, .. } => smtp.interrupt().await,
_ => {}
}
}
@@ -492,12 +482,14 @@ impl ConnectionState {
// Trigger shutdown of the run loop.
self.stop_sender.send(()).await;
// Wait for a notification that the run loop has been shutdown.
self.shutdown_receiver.recv().await.ok();
self.shutdown_receiver.recv().await;
}
async fn interrupt(&self) -> Result<(), async_std::sync::TrySendError<()>> {
// Use try_send to avoid blocking on interrupts.
self.idle_interrupt_sender.try_send(())
async fn interrupt(&self) {
if !self.idle_interrupt_sender.is_full() {
// Use try_send to avoid blocking on interrupts.
self.idle_interrupt_sender.send(()).await;
}
}
}
@@ -531,8 +523,8 @@ impl SmtpConnectionState {
}
/// Interrupt any form of idle.
async fn interrupt(&self) -> Result<(), async_std::sync::TrySendError<()>> {
self.state.interrupt().await
async fn interrupt(&self) {
self.state.interrupt().await;
}
/// Shutdown this connection completely.
@@ -579,8 +571,8 @@ impl ImapConnectionState {
}
/// Interrupt any form of idle.
async fn interrupt(&self) -> Result<(), async_std::sync::TrySendError<()>> {
self.state.interrupt().await
async fn interrupt(&self) {
self.state.interrupt().await;
}
/// Shutdown this connection completely.