Skip to content

Commit 55c4c4a

Browse files
committed
fix panic on malformed discovery requests
1 parent 33bf3a7 commit 55c4c4a

2 files changed

Lines changed: 31 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
- [main] Fixed `--volume-ctrl fixed` not disabling volume control
2323
- [core] Fix default permissions on credentials file and warn user if file is world readable
2424
- [core] Try all resolved addresses for the dealer connection instead of failing after the first one.
25+
- [discovery] Return an HTTP error response instead of panicking on malformed discovery login requests
2526

2627
## [0.8.0] - 2025-11-10
2728

discovery/src/server.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use aes::cipher::{KeyIvInit, StreamCipher};
99
use base64::engine::Engine as _;
1010
use base64::engine::general_purpose::STANDARD as BASE64;
1111
use bytes::Bytes;
12-
use futures_util::{FutureExt, TryFutureExt};
1312
use hmac::{Hmac, Mac};
1413
use http_body_util::{BodyExt, Full};
1514
use hyper::{Method, Request, Response, StatusCode, body::Incoming};
@@ -24,7 +23,7 @@ use super::{DiscoveryError, DiscoveryEvent};
2423

2524
use crate::{
2625
core::config::DeviceType,
27-
core::{Error, authentication::Credentials, diffie_hellman::DhLocalKeys},
26+
core::{Error, authentication::Credentials, diffie_hellman::DhLocalKeys, error::ErrorKind},
2827
};
2928

3029
type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>;
@@ -234,10 +233,28 @@ impl RequestHandler {
234233
res
235234
}
236235

236+
fn error_response(&self, err: &Error) -> Response<Full<Bytes>> {
237+
let status = match err.kind {
238+
ErrorKind::InvalidArgument | ErrorKind::FailedPrecondition => StatusCode::BAD_REQUEST,
239+
_ => StatusCode::SERVICE_UNAVAILABLE,
240+
};
241+
242+
let body = json!({
243+
"status": 102,
244+
"spotifyError": 0,
245+
"statusString": status.canonical_reason().unwrap_or("ERROR"),
246+
})
247+
.to_string();
248+
249+
let mut res = Response::new(Full::new(Bytes::from(body)));
250+
*res.status_mut() = status;
251+
res
252+
}
253+
237254
async fn handle(
238255
self: Arc<Self>,
239256
request: Request<Incoming>,
240-
) -> Result<hyper::Result<Response<Full<Bytes>>>, Error> {
257+
) -> hyper::Result<Response<Full<Bytes>>> {
241258
let mut params = Params::new();
242259

243260
let (parts, body) = request.into_parts();
@@ -257,11 +274,17 @@ impl RequestHandler {
257274

258275
let action = params.get("action").map(Cow::as_ref);
259276

260-
Ok(Ok(match (parts.method, action) {
277+
Ok(match (parts.method, action) {
261278
(Method::GET, Some("getInfo")) => self.handle_get_info(),
262-
(Method::POST, Some("addUser")) => self.handle_add_user(&params)?,
279+
(Method::POST, Some("addUser")) => match self.handle_add_user(&params) {
280+
Ok(response) => response,
281+
Err(err) => {
282+
error!("could not handle discovery request: {err}");
283+
self.error_response(&err)
284+
}
285+
},
263286
_ => self.not_found(),
264-
}))
287+
})
265288
}
266289
}
267290

@@ -325,12 +348,7 @@ impl DiscoveryServer {
325348
let discovery = discovery.clone();
326349

327350
let svc = hyper::service::service_fn(move |request| {
328-
discovery
329-
.clone()
330-
.handle(request)
331-
.inspect_err(|e| error!("could not handle discovery request: {e}"))
332-
.and_then(|x| async move { Ok(x) })
333-
.map(Result::unwrap) // guaranteed by `and_then` above
351+
discovery.clone().handle(request)
334352
});
335353

336354
let conn = server.serve_connection(io, svc);

0 commit comments

Comments
 (0)