Skip to content

Commit

Permalink
discovery::server: fix activeUser field of getInfo
Browse files Browse the repository at this point in the history
The current active user was almost persisted and reported but
wasn't. The handler for the discovery server is under an Arc so I
introduced a Mutex to protect the username field and made setting the
username and sending the credentials atomic so that every valid
credential send corresponds to an active user update.
  • Loading branch information
dsheets committed Dec 17, 2023
1 parent 886617e commit d7de444
Showing 1 changed file with 14 additions and 12 deletions.
26 changes: 14 additions & 12 deletions discovery/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use aes::cipher::{KeyIvInit, StreamCipher};
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::engine::Engine as _;
use futures_core::Stream;
use futures_util::{FutureExt, TryFutureExt};
use futures_util::{lock::Mutex, FutureExt, TryFutureExt};
use hmac::{Hmac, Mac};
use hyper::{
service::{make_service_fn, service_fn},
Expand Down Expand Up @@ -44,7 +44,7 @@ pub struct Config {

struct RequestHandler {
config: Config,
username: Option<String>,
username: Mutex<Option<String>>,
keys: DhLocalKeys,
tx: mpsc::UnboundedSender<Credentials>,
}
Expand All @@ -55,21 +55,19 @@ impl RequestHandler {

let discovery = Self {
config,
username: None,
username: Mutex::new(None),
keys: DhLocalKeys::random(&mut rand::thread_rng()),
tx,
};

(discovery, rx)
}

fn handle_get_info(&self) -> Response<hyper::Body> {
async fn handle_get_info(&self) -> Response<hyper::Body> {
let public_key = BASE64.encode(self.keys.public_key());
let device_type: &str = self.config.device_type.into();
let mut active_user = String::new();
if let Some(username) = &self.username {
active_user = username.to_string();
}
let maybe_username = self.username.lock().await;
let active_user = maybe_username.as_deref().unwrap_or("");

// See: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf/
let body = json!({
Expand Down Expand Up @@ -111,7 +109,7 @@ impl RequestHandler {
Response::new(Body::from(body))
}

fn handle_add_user(&self, params: &Params<'_>) -> Result<Response<hyper::Body>, Error> {
async fn handle_add_user(&self, params: &Params<'_>) -> Result<Response<hyper::Body>, Error> {
let username_key = "userName";
let username = params
.get(username_key)
Expand Down Expand Up @@ -184,7 +182,11 @@ impl RequestHandler {

let credentials = Credentials::with_blob(username, decrypted, &self.config.device_id)?;

self.tx.send(credentials)?;
{
let mut username_field = self.username.lock().await;
self.tx.send(credentials)?;
*username_field = Some(String::from(username));
}

let result = json!({
"status": 101,
Expand Down Expand Up @@ -226,8 +228,8 @@ impl RequestHandler {
let action = params.get("action").map(Cow::as_ref);

Ok(Ok(match (parts.method, action) {
(Method::GET, Some("getInfo")) => self.handle_get_info(),
(Method::POST, Some("addUser")) => self.handle_add_user(&params)?,
(Method::GET, Some("getInfo")) => self.handle_get_info().await,
(Method::POST, Some("addUser")) => self.handle_add_user(&params).await?,
_ => self.not_found(),
}))
}
Expand Down

0 comments on commit d7de444

Please sign in to comment.