diff --git a/Cargo.lock b/Cargo.lock index 3f62136d..23eb4485 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1259,6 +1259,7 @@ dependencies = [ "serde_json", "sha-1", "simple_logger", + "thiserror", "tokio", ] diff --git a/discovery/Cargo.toml b/discovery/Cargo.toml index ddb382c1..9ea9df48 100644 --- a/discovery/Cargo.toml +++ b/discovery/Cargo.toml @@ -20,6 +20,7 @@ log = "0.4" rand = "0.8" serde_json = "1.0.25" sha-1 = "0.9" +thiserror = "1.0" tokio = { version = "1.0", features = ["sync", "rt"] } dns-sd = { version = "0.1.3", optional = true } diff --git a/discovery/src/lib.rs b/discovery/src/lib.rs index cd78345d..3625d504 100644 --- a/discovery/src/lib.rs +++ b/discovery/src/lib.rs @@ -3,6 +3,9 @@ //! This device will show up in the list of "available devices". //! Once it is selected from the list, [`Credentials`] are received. //! Those can be used to establish a new Session with [`librespot_core`]. +//! +//! This library uses mDNS and DNS-SD so that other devices can find it, +//! and spawns an http server to answer requests of Spotify clients. #![warn(clippy::all, missing_docs, rust_2018_idioms)] @@ -15,6 +18,7 @@ use std::task::{Context, Poll}; use cfg_if::cfg_if; use futures_core::Stream; use librespot_core as core; +use thiserror::Error; use self::server::DiscoveryServer; @@ -43,6 +47,17 @@ pub struct Builder { port: u16, } +/// Errors that can occur while setting up a [`Discovery`] instance. +#[derive(Debug, Error)] +pub enum Error { + /// Setting up service discovery via DNS-SD failed. + #[error("Setting up dns-sd failed: {0}")] + DnsSdError(#[from] io::Error), + /// Setting up the http server failed. + #[error("Setting up the http server failed: {0}")] + HttpServerError(#[from] hyper::Error), +} + impl Builder { /// Starts a new builder using the provided device id. pub fn new(device_id: String) -> Self { @@ -79,22 +94,10 @@ impl Builder { /// /// # Errors /// If setting up the mdns service or creating the server fails, this function returns an error. - pub fn launch(self) -> io::Result { - Discovery::new(self) - } -} - -impl Discovery { - /// Starts a [`Builder`] with the provided device id. - pub fn builder(device_id: String) -> Builder { - Builder::new(device_id) - } - - fn new(builder: Builder) -> io::Result { - let name = builder.server_config.name.clone(); - let mut port = builder.port; - let server = DiscoveryServer::new(builder.server_config, &mut port) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + pub fn launch(self) -> Result { + let mut port = self.port; + let name = self.server_config.name.clone().into_owned(); + let server = DiscoveryServer::new(self.server_config, &mut port)?; let svc; @@ -114,14 +117,26 @@ impl Discovery { let responder = libmdns::Responder::spawn(&tokio::runtime::Handle::current())?; svc = responder.register( "_spotify-connect._tcp".to_owned(), - name.into_owned(), + name, port, &["VERSION=1.0", "CPath=/"], ) } }; - Ok(Self { server, _svc: svc }) + Ok(Discovery { server, _svc: svc }) + } +} + +impl Discovery { + /// Starts a [`Builder`] with the provided device id. + pub fn builder(device_id: String) -> Builder { + Builder::new(device_id) + } + + /// Create a new instance with the specified device id and default paramaters. + pub fn new(device_id: String) -> Result { + Self::builder(device_id).launch() } }