mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
fix: map authentication errors to a custom error type
This commit is contained in:
parent
06f5aa9c90
commit
71e9295ee8
4 changed files with 51 additions and 14 deletions
|
@ -13,6 +13,7 @@ use std::ops::FnOnce;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::protocol::authentication::AuthenticationType;
|
use crate::protocol::authentication::AuthenticationType;
|
||||||
|
use crate::protocol::keyexchange::{APLoginFailed, ErrorCode};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Credentials {
|
pub struct Credentials {
|
||||||
|
@ -191,3 +192,37 @@ pub fn get_credentials<F: FnOnce(&String) -> String>(
|
||||||
(None, _, None) => None,
|
(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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use tokio_core::net::TcpStream;
|
||||||
use tokio_core::reactor::Handle;
|
use tokio_core::reactor::Handle;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::authentication::Credentials;
|
use crate::authentication::{AuthenticationError, Credentials};
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
|
||||||
use crate::proxytunnel;
|
use crate::proxytunnel;
|
||||||
|
@ -66,7 +66,7 @@ pub fn authenticate(
|
||||||
transport: Transport,
|
transport: Transport,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
device_id: String,
|
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::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
|
||||||
use crate::protocol::keyexchange::APLoginFailed;
|
use crate::protocol::keyexchange::APLoginFailed;
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ pub fn authenticate(
|
||||||
transport
|
transport
|
||||||
.send((cmd, data))
|
.send((cmd, data))
|
||||||
.and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
|
.and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
|
||||||
|
.map_err(|io_err| io_err.into())
|
||||||
.and_then(|(packet, transport)| match packet {
|
.and_then(|(packet, transport)| match packet {
|
||||||
Some((0xac, data)) => {
|
Some((0xac, data)) => {
|
||||||
let welcome_data: APWelcome =
|
let welcome_data: APWelcome =
|
||||||
|
@ -118,10 +119,7 @@ pub fn authenticate(
|
||||||
Some((0xad, data)) => {
|
Some((0xad, data)) => {
|
||||||
let error_data: APLoginFailed =
|
let error_data: APLoginFailed =
|
||||||
protobuf::parse_from_bytes(data.as_ref()).unwrap();
|
protobuf::parse_from_bytes(data.as_ref()).unwrap();
|
||||||
panic!(
|
Err(error_data.into())
|
||||||
"Authentication failed with reason: {:?}",
|
|
||||||
error_data.get_error_code()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),
|
Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),
|
||||||
|
|
|
@ -19,6 +19,8 @@ use crate::config::SessionConfig;
|
||||||
use crate::connection;
|
use crate::connection;
|
||||||
use crate::mercury::MercuryManager;
|
use crate::mercury::MercuryManager;
|
||||||
|
|
||||||
|
pub use crate::authentication::{AuthenticationError, AuthenticationErrorKind};
|
||||||
|
|
||||||
struct SessionData {
|
struct SessionData {
|
||||||
country: String,
|
country: String,
|
||||||
time_delta: i64,
|
time_delta: i64,
|
||||||
|
@ -53,16 +55,18 @@ impl Session {
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
cache: Option<Cache>,
|
cache: Option<Cache>,
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
) -> Box<dyn Future<Item = Session, Error = io::Error>> {
|
) -> Box<dyn Future<Item = Session, Error = AuthenticationError>> {
|
||||||
let access_point =
|
let access_point =
|
||||||
apresolve_or_fallback::<io::Error>(&handle, &config.proxy, &config.ap_port);
|
apresolve_or_fallback::<io::Error>(&handle, &config.proxy, &config.ap_port);
|
||||||
|
|
||||||
let handle_ = handle.clone();
|
let handle_ = handle.clone();
|
||||||
let proxy = config.proxy.clone();
|
let proxy = config.proxy.clone();
|
||||||
let connection = access_point.and_then(move |addr| {
|
let connection = access_point
|
||||||
info!("Connecting to AP \"{}\"", addr);
|
.and_then(move |addr| {
|
||||||
connection::connect(addr, &handle_, &proxy)
|
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 device_id = config.device_id.clone();
|
||||||
let authentication = connection.and_then(move |connection| {
|
let authentication = connection.and_then(move |connection| {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use futures::{Async, Future, Poll, Stream};
|
||||||
use log::{error, info, trace, warn};
|
use log::{error, info, trace, warn};
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::{self, stderr, Write};
|
use std::io::{stderr, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
@ -16,7 +16,7 @@ use url::Url;
|
||||||
use librespot::core::authentication::{get_credentials, Credentials};
|
use librespot::core::authentication::{get_credentials, Credentials};
|
||||||
use librespot::core::cache::Cache;
|
use librespot::core::cache::Cache;
|
||||||
use librespot::core::config::{ConnectConfig, DeviceType, SessionConfig, VolumeCtrl};
|
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::core::version;
|
||||||
|
|
||||||
use librespot::connect::discovery::{discovery, DiscoveryStream};
|
use librespot::connect::discovery::{discovery, DiscoveryStream};
|
||||||
|
@ -406,7 +406,7 @@ struct Main {
|
||||||
|
|
||||||
spirc: Option<Spirc>,
|
spirc: Option<Spirc>,
|
||||||
spirc_task: Option<SpircTask>,
|
spirc_task: Option<SpircTask>,
|
||||||
connect: Box<dyn Future<Item = Session, Error = io::Error>>,
|
connect: Box<dyn Future<Item = Session, Error = AuthenticationError>>,
|
||||||
|
|
||||||
shutdown: bool,
|
shutdown: bool,
|
||||||
last_credentials: Option<Credentials>,
|
last_credentials: Option<Credentials>,
|
||||||
|
|
Loading…
Reference in a new issue