Преглед изворни кода

Move authentication to a different directory, and make discover use hyper.

Paul Lietar пре 9 година
родитељ
комит
0770f6ce61
12 измењених фајлова са 223 додато и 328 уклоњено
  1. 0 100
      Cargo.lock
  2. 0 1
      Cargo.toml
  3. 188 0
      src/authentication/discovery.rs
  4. 1 1
      src/authentication/facebook.rs
  5. 17 0
      src/authentication/mod.rs
  6. 0 167
      src/discovery.rs
  7. 0 5
      src/lib.in.rs
  8. 0 1
      src/lib.rs
  9. 11 17
      src/main.rs
  10. 5 5
      src/session.rs
  11. 1 1
      src/spirc.rs
  12. 0 30
      src/zeroconf.rs

+ 0 - 100
Cargo.lock

@@ -26,7 +26,6 @@ dependencies = [
  "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "tiny_http 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)",
  "url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -41,11 +40,6 @@ dependencies = [
  "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "ascii"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "aster"
 version = "0.13.1"
@@ -92,20 +86,6 @@ name = "byteorder"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "chrono"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "chunked_transfer"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "clippy"
 version = "0.0.53"
@@ -137,63 +117,6 @@ dependencies = [
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "encoding"
-version = "0.2.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding-index-japanese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding-index-korean"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding-index-simpchinese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding-index-singlebyte"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding-index-tradchinese"
-version = "1.20141219.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "encoding_index_tests"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "eventual"
 version = "0.1.5"
@@ -691,19 +614,6 @@ dependencies = [
  "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "tiny_http"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ascii 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "chrono 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "toml"
 version = "0.1.28"
@@ -767,16 +677,6 @@ name = "unicode-xid"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "url"
-version = "0.2.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "url"
 version = "0.5.7"

+ 0 - 1
Cargo.toml

@@ -32,7 +32,6 @@ rust-crypto     = "~0.2.34"
 rustc-serialize = "~0.3.16"
 tempfile        = "~2.0.0"
 time            = "~0.1.34"
-tiny_http       = "~0.5.1"
 url             = "~0.5.2"
 vorbis          = "~0.0.14"
 

+ 188 - 0
src/authentication/discovery.rs

@@ -0,0 +1,188 @@
+use crypto;
+use crypto::mac::Mac;
+use crypto::digest::Digest;
+use dns_sd::DNSService;
+use hyper;
+use hyper::net::NetworkListener;
+use num::BigUint;
+use url;
+use rand;
+use rustc_serialize::base64::{self, ToBase64, FromBase64};
+use std::collections::BTreeMap;
+use std::io::{Read, Write};
+use std::sync::{mpsc, Mutex};
+
+use authentication::Credentials;
+use diffie_hellman::{DH_GENERATOR, DH_PRIME};
+use util;
+
+struct ServerHandler {
+    credentials_tx: Mutex<mpsc::Sender<Credentials>>,
+    private_key: BigUint,
+    public_key: BigUint,
+    device_id: String,
+    device_name: String,
+}
+
+impl ServerHandler {
+    fn handle_get_info(&self, _params: &BTreeMap<String, String>,
+                       mut response: hyper::server::Response<hyper::net::Fresh>) {
+
+        let public_key = self.public_key.to_bytes_be()
+                                        .to_base64(base64::STANDARD);
+
+        let result = json!({
+            "status": 101,
+            "statusString": "ERROR-OK",
+            "spotifyError": 0,
+            "version": "2.1.0",
+            "deviceID": (self.device_id),
+            "remoteName": (self.device_name),
+            "activeUser": "",
+            "publicKey": (public_key),
+            "deviceType": "UNKNOWN",
+            "libraryVersion": "0.1.0",
+            "accountReq": "PREMIUM",
+            "brandDisplayName": "librespot",
+            "modelDisplayName": "librespot",
+        });
+
+        *response.status_mut() = hyper::status::StatusCode::Ok;
+        response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap();
+    }
+
+    fn handle_add_user(&self, params: &BTreeMap<String, String>,
+                       mut response: hyper::server::Response<hyper::net::Fresh>) {
+
+        let username = params.get("userName").unwrap();
+        let encrypted_blob = params.get("blob").unwrap();
+        let client_key = params.get("clientKey").unwrap();
+
+        let encrypted_blob = encrypted_blob.from_base64().unwrap();
+
+        let client_key = client_key.from_base64().unwrap();
+        let client_key = BigUint::from_bytes_be(&client_key);
+
+        let shared_key = util::powm(&client_key, &self.private_key, &DH_PRIME);
+
+        let iv = &encrypted_blob[0..16];
+        let encrypted = &encrypted_blob[16..encrypted_blob.len() - 20];
+        let cksum = &encrypted_blob[encrypted_blob.len() - 20..encrypted_blob.len()];
+
+        let base_key = {
+            let mut data = [0u8; 20];
+            let mut h = crypto::sha1::Sha1::new();
+            h.input(&shared_key.to_bytes_be());
+            h.result(&mut data);
+            data[..16].to_owned()
+        };
+
+        let checksum_key = {
+            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &base_key);
+            h.input("checksum".as_bytes());
+            h.result().code().to_owned()
+        };
+
+        let encryption_key = {
+            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &base_key);
+            h.input("encryption".as_bytes());
+            h.result().code().to_owned()
+        };
+
+        let mac = {
+            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &checksum_key);
+            h.input(encrypted);
+            h.result().code().to_owned()
+        };
+
+        assert_eq!(&mac[..], cksum);
+
+        let decrypted = {
+            let mut data = vec![0u8; encrypted.len()];
+            let mut cipher = crypto::aes::ctr(crypto::aes::KeySize::KeySize128,
+                                              &encryption_key[0..16],
+                                              &iv);
+            cipher.process(&encrypted, &mut data);
+            String::from_utf8(data).unwrap()
+        };
+
+        let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.device_id);
+
+        self.credentials_tx.lock().unwrap().send(credentials).unwrap();
+
+        let result = json!({
+            "status": 101,
+            "spotifyError": 0,
+            "statusString": "ERROR-OK"
+        });
+
+        *response.status_mut() = hyper::status::StatusCode::Ok;
+        response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap();
+    }
+
+    fn not_found(&self, mut response: hyper::server::Response<hyper::net::Fresh>) {
+
+        *response.status_mut() = hyper::status::StatusCode::NotFound
+    }
+}
+
+impl hyper::server::Handler for ServerHandler {
+    fn handle<'a, 'k>(&'a self,
+                      mut request: hyper::server::Request<'a, 'k>,
+                      response: hyper::server::Response<'a, hyper::net::Fresh>) {
+
+        if let hyper::uri::RequestUri::AbsolutePath(path) = request.uri.clone() {
+            let (_, query, _) = url::parse_path(&path).unwrap();
+            let mut params = query.map_or(vec![], |q| url::form_urlencoded::parse(q.as_bytes()))
+                                  .into_iter().collect::<BTreeMap<_,_>>();
+
+            if request.method == hyper::method::Method::Post {
+                let mut body = Vec::new();
+                request.read_to_end(&mut body).unwrap();
+                let form = url::form_urlencoded::parse(&body);
+                params.extend(form);
+            }
+
+            match params.get("action").map(AsRef::as_ref) {
+                Some("getInfo") => self.handle_get_info(&params, response),
+                Some("addUser") => self.handle_add_user(&params, response),
+                _ => self.not_found(response),
+            }
+        } else {
+            self.not_found(response)
+        }
+    }
+}
+
+pub fn discovery_login(device_name: &str, device_id: &str) -> Result<Credentials, ()> {
+    let (tx, rx) = mpsc::channel();
+
+    let key_data = util::rand_vec(&mut rand::thread_rng(), 95);
+    let private_key = BigUint::from_bytes_be(&key_data);
+    let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
+
+    let handler = ServerHandler {
+        device_name: device_name.to_owned(),
+        device_id: device_id.to_owned(),
+        private_key: private_key,
+        public_key: public_key,
+        credentials_tx: Mutex::new(tx),
+    };
+
+    let mut listener = hyper::net::HttpListener::new("0.0.0.0:0").unwrap();
+    let port = listener.local_addr().unwrap().port();
+
+    let mut server = hyper::Server::new(listener).handle(handler).unwrap();
+
+    let _svc = DNSService::register(Some(device_name),
+                                    "_spotify-connect._tcp",
+                                    None,
+                                    None,
+                                    port,
+                                    &["VERSION=1.0", "CPath=/"]
+                                    ).unwrap();
+
+    let cred = rx.recv().unwrap();
+    server.close().unwrap();
+    Ok(cred)
+}

+ 1 - 1
src/facebook.rs → src/authentication/facebook.rs

@@ -72,7 +72,7 @@ impl hyper::server::Handler for ServerHandler {
     }
 }
 
-pub fn facebook_get_me_id(token: &str) -> Result<String, ()> {
+fn facebook_get_me_id(token: &str) -> Result<String, ()> {
     let url = format!("https://graph.facebook.com/me?fields=id&access_token={}", token);
 
     let client = hyper::Client::new();

+ 17 - 0
src/authentication.rs → src/authentication/mod.rs

@@ -163,3 +163,20 @@ impl From<StoredCredentials> for Credentials {
     }
 }
 
+#[cfg(feature = "discovery")]
+mod discovery;
+#[cfg(feature = "discovery")]
+pub use self::discovery::discovery_login;
+#[cfg(not(feature = "discovery"))]
+pub fn discovery_login(device_name: &str, device_id: &str) -> Result<Credentials, ()> {
+    Err(())
+}
+
+#[cfg(feature = "facebook")]
+mod facebook;
+#[cfg(feature = "facebook")]
+pub use self::facebook::facebook_login;
+#[cfg(not(feature = "facebook"))]
+pub fn facebook_login() -> Result<Credentials, ()> {
+    Err(())
+}

+ 0 - 167
src/discovery.rs

@@ -1,167 +0,0 @@
-use crypto;
-use crypto::mac::Mac;
-use crypto::digest::Digest;
-use num::BigUint;
-use url;
-use rand;
-use rustc_serialize::base64::{self, ToBase64, FromBase64};
-use tiny_http::{Method, Request, Response, ResponseBox, Server};
-use zeroconf::DNSService;
-
-use authentication::Credentials;
-use session::Session;
-use diffie_hellman::{DH_GENERATOR, DH_PRIME};
-use util;
-
-pub struct DiscoveryManager {
-    session: Session,
-    private_key: BigUint,
-    public_key: BigUint,
-}
-
-fn not_found() -> ResponseBox {
-    Response::from_string("Not found").with_status_code(404).boxed()
-}
-
-impl DiscoveryManager {
-    pub fn new(session: Session) -> DiscoveryManager {
-        let key_data = util::rand_vec(&mut rand::thread_rng(), 95);
-        let private_key = BigUint::from_bytes_be(&key_data);
-        let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
-
-        DiscoveryManager {
-            session: session,
-            private_key: private_key,
-            public_key: public_key,
-        }
-    }
-
-    fn get_info(&self) -> ResponseBox {
-        let public_key = self.public_key.to_bytes_be().to_base64(base64::STANDARD);
-        Response::from_string(json!({
-            "status": 101,
-            "statusString": "ERROR-OK",
-            "spotifyError": 0,
-            "version": "2.1.0",
-            "deviceID": (self.session.device_id()),
-            "remoteName": (self.session.config().device_name),
-            "activeUser": "",
-            "publicKey": (public_key),
-            "deviceType": "UNKNOWN",
-            "libraryVersion": "0.1.0",
-            "accountReq": "PREMIUM",
-            "brandDisplayName": "librespot",
-            "modelDisplayName": "librespot",
-        }).to_string()).boxed()
-    }
-
-    fn add_user(&self, params: &[(String, String)]) -> (ResponseBox, Credentials) {
-        let &(_, ref username) = params.iter().find(|&&(ref key, _)| key == "userName").unwrap();
-        let &(_, ref encrypted_blob) = params.iter().find(|&&(ref key, _)| key == "blob").unwrap();
-        let &(_, ref client_key) = params.iter().find(|&&(ref key, _)| key == "clientKey").unwrap();
-
-        let encrypted_blob = encrypted_blob.from_base64().unwrap();
-
-        let client_key = client_key.from_base64().unwrap();
-        let client_key = BigUint::from_bytes_be(&client_key);
-
-        let shared_key = util::powm(&client_key, &self.private_key, &DH_PRIME);
-
-        let iv = &encrypted_blob[0..16];
-        let encrypted = &encrypted_blob[16..encrypted_blob.len() - 20];
-        let cksum = &encrypted_blob[encrypted_blob.len() - 20..encrypted_blob.len()];
-
-        let base_key = {
-            let mut data = [0u8; 20];
-            let mut h = crypto::sha1::Sha1::new();
-            h.input(&shared_key.to_bytes_be());
-            h.result(&mut data);
-            data[..16].to_owned()
-        };
-
-        let checksum_key = {
-            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &base_key);
-            h.input("checksum".as_bytes());
-            h.result().code().to_owned()
-        };
-
-        let encryption_key = {
-            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &base_key);
-            h.input("encryption".as_bytes());
-            h.result().code().to_owned()
-        };
-
-        let mac = {
-            let mut h = crypto::hmac::Hmac::new(crypto::sha1::Sha1::new(), &checksum_key);
-            h.input(encrypted);
-            h.result().code().to_owned()
-        };
-
-        assert_eq!(&mac[..], cksum);
-
-        let decrypted = {
-            let mut data = vec![0u8; encrypted.len()];
-            let mut cipher = crypto::aes::ctr(crypto::aes::KeySize::KeySize128,
-                                              &encryption_key[0..16],
-                                              &iv);
-            cipher.process(&encrypted, &mut data);
-            String::from_utf8(data).unwrap()
-        };
-
-        let response = Response::from_string(json!({
-            "status": 101,
-            "spotifyError": 0,
-            "statusString": "ERROR-OK"
-        }).to_string()).boxed();
-
-        let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.session.device_id());
-
-        (response, credentials)
-    }
-
-    fn handle_request(&self, mut request: Request) -> Option<Credentials> {
-        let (_, query, _) = url::parse_path(request.url()).unwrap();
-        let mut params = query.map_or(vec![], |q| url::form_urlencoded::parse(q.as_bytes()));
-
-        if *request.method() == Method::Post {
-            let mut body = Vec::new();
-            request.as_reader().read_to_end(&mut body).unwrap();
-            let form = url::form_urlencoded::parse(&body);
-            params.extend(form);
-        }
-
-        println!("{:?}", params);
-
-        let &(_, ref action) = params.iter().find(|&&(ref key, _)| key == "action").unwrap();
-        let (response, credentials) = match action.as_ref() {
-            "getInfo" => (self.get_info(), None),
-            "addUser" => {
-                let (response, credentials) = self.add_user(&params);
-                (response, Some(credentials))
-            }
-            _ => (not_found(), None)
-        };
-
-        request.respond(response).unwrap();
-        credentials
-    }
-
-    pub fn run(&mut self) -> Credentials {
-        let server = Server::http("0.0.0.0:8000").unwrap();
-        let _svc = DNSService::register(Some(&self.session.config().device_name),
-                                        "_spotify-connect._tcp",
-                                        None,
-                                        None,
-                                        8000,
-                                        &["VERSION=1.0", "CPath=/"]
-                                        ).unwrap();
-
-        for request in server.incoming_requests() {
-            if let Some(credentials) = self.handle_request(request) {
-                return credentials;
-            }
-        }
-
-        panic!("No credentials obtained !");
-    }
-}

+ 0 - 5
src/lib.in.rs

@@ -8,7 +8,6 @@ pub mod authentication;
 pub mod cache;
 mod connection;
 mod diffie_hellman;
-pub mod discovery;
 pub mod mercury;
 pub mod metadata;
 pub mod player;
@@ -17,9 +16,5 @@ pub mod spirc;
 pub mod link;
 pub mod stream;
 pub mod apresolve;
-mod zeroconf;
-
-#[cfg(feature = "facebook")]
-pub mod facebook;
 
 pub use album_cover::get_album_cover;

+ 0 - 1
src/lib.rs

@@ -23,7 +23,6 @@ extern crate shannon;
 extern crate rand;
 extern crate rustc_serialize;
 extern crate time;
-extern crate tiny_http;
 extern crate tempfile;
 extern crate url;
 

+ 11 - 17
src/main.rs

@@ -10,20 +10,12 @@ use std::path::PathBuf;
 use std::thread;
 
 use librespot::audio_sink::DefaultSink;
-use librespot::authentication::Credentials;
-use librespot::discovery::DiscoveryManager;
+use librespot::authentication::{Credentials, facebook_login, discovery_login};
+use librespot::cache::{Cache, DefaultCache, NoCache};
 use librespot::player::Player;
 use librespot::session::{Bitrate, Config, Session};
 use librespot::spirc::SpircManager;
 use librespot::util::version::version_string;
-use librespot::cache::{Cache, DefaultCache, NoCache};
-
-#[cfg(feature = "facebook")]
-use librespot::facebook::facebook_login;
-#[cfg(not(feature = "facebook"))]
-fn facebook_login() -> Result<Credentials, ()> {
-    Err(())
-}
 
 static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
 
@@ -117,13 +109,15 @@ fn main() {
         } else {
             None
         }
-    }).or_else(|| session.cache().get_credentials())
-      .unwrap_or_else(|| {
-        println!("No username provided and no stored credentials, starting discovery ...");
-
-        let mut discovery = DiscoveryManager::new(session.clone());
-        discovery.run()
-    });
+    }).or_else(|| {
+        if cfg!(feature = "discovery") {
+            println!("No username provided and no stored credentials, starting discovery ...");
+            Some(discovery_login(&session.config().device_name,
+                                 session.device_id()).unwrap())
+        } else {
+            None
+        }
+    }).expect("No username provided and no stored credentials.");
 
     std::env::remove_var(PASSWORD_ENV_NAME);
 

+ 5 - 5
src/session.rs

@@ -42,11 +42,11 @@ pub struct Config {
 pub struct SessionData {
     country: String,
     canonical_username: String,
-    device_id: String,
 }
 
 pub struct SessionInternal {
     config: Config,
+    device_id: String,
     data: RwLock<SessionData>,
 
     cache: Box<Cache + Send + Sync>,
@@ -71,10 +71,10 @@ impl Session {
 
         Session(Arc::new(SessionInternal {
             config: config,
+            device_id: device_id,
             data: RwLock::new(SessionData {
                 country: String::new(),
                 canonical_username: String::new(),
-                device_id: device_id,
             }),
 
             rx_connection: Mutex::new(None),
@@ -190,7 +190,7 @@ impl Session {
                 cpu_family: protocol::authentication::CpuFamily::CPU_UNKNOWN,
                 os: protocol::authentication::Os::OS_UNKNOWN,
                 system_information_string: "librespot".to_owned(),
-                device_id: self.device_id(),
+                device_id: self.device_id().to_owned(),
             },
             version_string: util::version::version_string(),
             appkey => {
@@ -348,7 +348,7 @@ impl Session {
         self.0.data.read().unwrap().country.clone()
     }
 
-    pub fn device_id(&self) -> String {
-        self.0.data.read().unwrap().device_id.clone()
+    pub fn device_id(&self) -> &str {
+        &self.0.device_id
     }
 }

+ 1 - 1
src/spirc.rs

@@ -46,7 +46,7 @@ struct SpircInternal {
 
 impl SpircManager {
     pub fn new(session: Session, player: Player) -> SpircManager {
-        let ident = session.device_id();
+        let ident = session.device_id().to_owned();
         let name = session.config().device_name.clone();
 
         SpircManager(Arc::new(Mutex::new(SpircInternal {

+ 0 - 30
src/zeroconf.rs

@@ -1,30 +0,0 @@
-#[cfg(feature = "dns-sd")]
-pub use dns_sd::*;
-#[cfg(not(feature = "dns-sd"))]
-pub use self::stub::*;
-
-#[cfg(not(feature = "dns-sd"))]
-pub mod stub {
-    use std;
-    use std::io::Write;
-
-    #[derive(Debug)]
-    pub struct DNSService;
-
-    pub type DNSError = ();
-
-    impl DNSService {
-        pub fn register(_: Option<&str>,
-                        _: &str,
-                        _: Option<&str>,
-                        _: Option<&str>,
-                        _: u16,
-                        _: &[&str])
-                        -> std::result::Result<DNSService, DNSError> {
-            writeln!(&mut std::io::stderr(),
-                     "WARNING: dns-sd is not enabled. Service will probably not be visible")
-                .unwrap();
-            Ok(DNSService)
-        }
-    }
-}