Merge pull request #566 from xou816/fix/map-auth-errors

fix: map authentication errors to a custom error type
This commit is contained in:
Sasha Hilton 2021-02-06 02:54:11 +00:00 committed by GitHub
commit 84ba421818
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 14 deletions

View file

@ -7,6 +7,7 @@ use sha1::{Digest, Sha1};
use std::io::{self, Read};
use crate::protocol::authentication::AuthenticationType;
use crate::protocol::keyexchange::{APLoginFailed, ErrorCode};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Credentials {
@ -164,3 +165,37 @@ pub fn get_credentials<F: FnOnce(&String) -> String>(
(None, _, None) => None,
}
}
error_chain! {
types {
AuthenticationError, AuthenticationErrorKind, AuthenticationResultExt, AuthenticationResult;
}
foreign_links {
Io(::std::io::Error);
}
errors {
BadCredentials {
description("Bad credentials")
display("Authentication failed with error: Bad credentials")
}
PremiumAccountRequired {
description("Premium account required")
display("Authentication failed with error: Premium account required")
}
}
}
impl From<APLoginFailed> for AuthenticationError {
fn from(login_failure: APLoginFailed) -> Self {
let error_code = login_failure.get_error_code();
match error_code {
ErrorCode::BadCredentials => Self::from_kind(AuthenticationErrorKind::BadCredentials),
ErrorCode::PremiumAccountRequired => {
Self::from_kind(AuthenticationErrorKind::PremiumAccountRequired)
}
_ => format!("Authentication failed with error: {:?}", error_code).into(),
}
}
}

View file

@ -13,7 +13,7 @@ use tokio_core::net::TcpStream;
use tokio_core::reactor::Handle;
use url::Url;
use crate::authentication::Credentials;
use crate::authentication::{AuthenticationError, Credentials};
use crate::version;
use crate::proxytunnel;
@ -66,7 +66,7 @@ pub fn authenticate(
transport: Transport,
credentials: Credentials,
device_id: String,
) -> Box<dyn Future<Item = (Transport, Credentials), Error = io::Error>> {
) -> Box<dyn Future<Item = (Transport, Credentials), Error = AuthenticationError>> {
use crate::protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
use crate::protocol::keyexchange::APLoginFailed;
@ -101,6 +101,7 @@ pub fn authenticate(
transport
.send((cmd, data))
.and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
.map_err(|io_err| io_err.into())
.and_then(|(packet, transport)| match packet {
Some((0xac, data)) => {
let welcome_data: APWelcome =
@ -118,10 +119,7 @@ pub fn authenticate(
Some((0xad, data)) => {
let error_data: APLoginFailed =
protobuf::parse_from_bytes(data.as_ref()).unwrap();
panic!(
"Authentication failed with reason: {:?}",
error_data.get_error_code()
)
Err(error_data.into())
}
Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),

View file

@ -19,6 +19,8 @@ use crate::config::SessionConfig;
use crate::connection;
use crate::mercury::MercuryManager;
pub use crate::authentication::{AuthenticationError, AuthenticationErrorKind};
struct SessionData {
country: String,
time_delta: i64,
@ -53,16 +55,18 @@ impl Session {
credentials: Credentials,
cache: Option<Cache>,
handle: Handle,
) -> Box<dyn Future<Item = Session, Error = io::Error>> {
) -> Box<dyn Future<Item = Session, Error = AuthenticationError>> {
let access_point =
apresolve_or_fallback::<io::Error>(&handle, &config.proxy, &config.ap_port);
let handle_ = handle.clone();
let proxy = config.proxy.clone();
let connection = access_point.and_then(move |addr| {
let connection = access_point
.and_then(move |addr| {
info!("Connecting to AP \"{}\"", addr);
connection::connect(addr, &handle_, &proxy)
});
})
.map_err(|io_err| io_err.into());
let device_id = config.device_id.clone();
let authentication = connection.and_then(move |connection| {

View file

@ -3,7 +3,7 @@ use futures::{Async, Future, Poll, Stream};
use log::{error, info, trace, warn};
use sha1::{Digest, Sha1};
use std::env;
use std::io::{self, stderr, Write};
use std::io::{stderr, Write};
use std::mem;
use std::path::Path;
use std::process::exit;
@ -16,7 +16,7 @@ use url::Url;
use librespot::core::authentication::{get_credentials, Credentials};
use librespot::core::cache::Cache;
use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig, VolumeCtrl};
use librespot::core::session::Session;
use librespot::core::session::{AuthenticationError, Session};
use librespot::core::version;
use librespot::connect::discovery::{discovery, DiscoveryStream};
@ -436,7 +436,7 @@ struct Main {
spirc: Option<Spirc>,
spirc_task: Option<SpircTask>,
connect: Box<dyn Future<Item = Session, Error = io::Error>>,
connect: Box<dyn Future<Item = Session, Error = AuthenticationError>>,
shutdown: bool,
last_credentials: Option<Credentials>,