diff --git a/Cargo.lock b/Cargo.lock index 52784b2c..1fa25197 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,9 +138,15 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atomic_refcell" version = "0.1.13" @@ -168,12 +174,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -203,7 +203,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -415,15 +415,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct 0.6.1", -] - [[package]] name = "ctr" version = "0.9.2" @@ -624,7 +615,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -744,7 +735,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -916,16 +907,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 0.2.11", + "http", "indexmap 2.2.3", "slab", "tokio", @@ -947,14 +938,14 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "headers" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "headers-core", - "http 0.2.11", + "http", "httpdate", "mime", "sha1", @@ -962,11 +953,11 @@ dependencies = [ [[package]] name = "headers-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 0.2.11", + "http", ] [[package]] @@ -1016,17 +1007,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.0.0" @@ -1040,12 +1020,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 0.2.11", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", "pin-project-lite", ] @@ -1069,78 +1061,83 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", - "http 0.2.11", + "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] [[package]] -name = "hyper-proxy" -version = "0.9.1" +name = "hyper-proxy2" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" +checksum = "9043b7b23fb0bc4a1c7014c27b50a4fc42cc76206f71d34fc0dfe5b28ddc3faf" dependencies = [ "bytes", - "futures", + "futures-util", "headers", - "http 0.2.11", + "http", "hyper", - "hyper-rustls 0.22.1", - "rustls-native-certs 0.5.0", + "hyper-rustls", + "hyper-util", + "pin-project-lite", + "rustls-native-certs", "tokio", - "tokio-rustls 0.22.0", + "tokio-rustls", "tower-service", - "webpki 0.21.4", + "webpki", ] [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ - "ct-logs", "futures-util", + "http", "hyper", + "hyper-util", "log", - "rustls 0.19.1", - "rustls-native-certs 0.5.0", + "rustls", + "rustls-native-certs", + "rustls-pki-types", "tokio", - "tokio-rustls 0.22.0", - "webpki 0.21.4", + "tokio-rustls", + "tower-service", ] [[package]] -name = "hyper-rustls" -version = "0.24.2" +name = "hyper-util" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ + "bytes", + "futures-channel", "futures-util", - "http 0.2.11", + "http", + "http-body", "hyper", - "log", - "rustls 0.21.10", - "rustls-native-certs 0.6.3", + "pin-project-lite", + "socket2", "tokio", - "tokio-rustls 0.24.1", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1414,7 +1411,7 @@ dependencies = [ "thiserror", "tokio", "url", - "webpki 0.22.4", + "webpki", ] [[package]] @@ -1427,7 +1424,9 @@ dependencies = [ "ctr", "futures-core", "futures-util", + "http-body-util", "hyper", + "hyper-util", "librespot-core", "log", "parking_lot", @@ -1460,7 +1459,7 @@ name = "librespot-core" version = "0.5.0-dev" dependencies = [ "aes", - "base64 0.21.7", + "base64", "byteorder", "bytes", "data-encoding", @@ -1471,11 +1470,13 @@ dependencies = [ "futures-util", "governor", "hmac", - "http 0.2.11", + "http", + "http-body-util", "httparse", "hyper", - "hyper-proxy", - "hyper-rustls 0.24.2", + "hyper-proxy2", + "hyper-rustls", + "hyper-util", "librespot-protocol", "log", "nonzero_ext", @@ -1512,7 +1513,8 @@ name = "librespot-discovery" version = "0.5.0-dev" dependencies = [ "aes", - "base64 0.21.7", + "base64", + "bytes", "cfg-if", "ctr", "dns-sd", @@ -1522,7 +1524,9 @@ dependencies = [ "futures-util", "hex", "hmac", + "http-body-util", "hyper", + "hyper-util", "libmdns", "librespot-core", "log", @@ -1827,7 +1831,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -2040,6 +2044,26 @@ dependencies = [ "indexmap 2.2.3", ] +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2149,9 +2173,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -2310,21 +2334,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -2336,7 +2345,7 @@ dependencies = [ "getrandom", "libc", "spin 0.9.8", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -2415,31 +2424,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.1", - "log", - "ring 0.16.20", - "sct 0.6.1", - "webpki 0.21.4", -] - -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.8", - "rustls-webpki 0.101.7", - "sct 0.7.1", -] - [[package]] name = "rustls" version = "0.22.2" @@ -2447,37 +2431,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" -dependencies = [ - "openssl-probe", - "rustls 0.19.1", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -2485,28 +2445,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.0", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" dependencies = [ - "base64 0.21.7", + "base64", "rustls-pki-types", ] @@ -2516,25 +2467,15 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "rustls-webpki" version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -2573,26 +2514,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "sdl2" version = "0.36.0" @@ -2656,7 +2577,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -2890,9 +2811,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.50" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -2961,7 +2882,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] @@ -3049,28 +2970,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", -] - -[[package]] -name = "tokio-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" -dependencies = [ - "rustls 0.19.1", - "tokio", - "webpki 0.21.4", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.10", - "tokio", + "syn 2.0.66", ] [[package]] @@ -3079,7 +2979,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.2", + "rustls", "rustls-pki-types", "tokio", ] @@ -3103,11 +3003,11 @@ checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", - "rustls 0.22.2", - "rustls-native-certs 0.7.0", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tungstenite", ] @@ -3181,6 +3081,27 @@ dependencies = [ "winnow 0.6.2", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3221,11 +3142,11 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.0.0", + "http", "httparse", "log", "rand", - "rustls 0.22.2", + "rustls", "rustls-pki-types", "sha1", "thiserror", @@ -3266,12 +3187,6 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -3381,7 +3296,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -3415,7 +3330,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3436,24 +3351,14 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "webpki" version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3752,7 +3657,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn 2.0.66", ] [[package]] diff --git a/audio/Cargo.toml b/audio/Cargo.toml index 94b900c7..9d5ccd8a 100644 --- a/audio/Cargo.toml +++ b/audio/Cargo.toml @@ -19,7 +19,9 @@ bytes = "1" ctr = "0.9" futures-core = "0.3" futures-util = "0.3" -hyper = { version = "0.14", features = ["client"] } +hyper = { version = "1.3", features = [] } +hyper-util = { version = "0.1", features = ["client"] } +http-body-util = "0.1.1" log = "0.4" parking_lot = { version = "0.12", features = ["deadlock_detection"] } tempfile = "3" diff --git a/audio/src/fetch/mod.rs b/audio/src/fetch/mod.rs index f6071936..d1617106 100644 --- a/audio/src/fetch/mod.rs +++ b/audio/src/fetch/mod.rs @@ -12,7 +12,8 @@ use std::{ }; use futures_util::{future::IntoStream, StreamExt, TryFutureExt}; -use hyper::{client::ResponseFuture, header::CONTENT_RANGE, Body, Response, StatusCode}; +use hyper::{body::Incoming, header::CONTENT_RANGE, Response, StatusCode}; +use hyper_util::client::legacy::ResponseFuture; use parking_lot::{Condvar, Mutex}; use tempfile::NamedTempFile; use thiserror::Error; @@ -133,7 +134,7 @@ pub enum AudioFile { #[derive(Debug)] pub struct StreamingRequest { streamer: IntoStream, - initial_response: Option>, + initial_response: Option>, offset: usize, length: usize, } diff --git a/audio/src/fetch/receive.rs b/audio/src/fetch/receive.rs index 0b001113..5f92380a 100644 --- a/audio/src/fetch/receive.rs +++ b/audio/src/fetch/receive.rs @@ -7,6 +7,7 @@ use std::{ use bytes::Bytes; use futures_util::StreamExt; +use http_body_util::BodyExt; use hyper::StatusCode; use tempfile::NamedTempFile; use tokio::sync::{mpsc, oneshot}; @@ -97,7 +98,7 @@ async fn receive_data( } let body = response.into_body(); - let data = match hyper::body::to_bytes(body).await { + let data = match body.collect().await.map(|b| b.to_bytes()) { Ok(bytes) => bytes, Err(e) => break Err(e.into()), }; diff --git a/core/Cargo.toml b/core/Cargo.toml index 2f515480..c9fb2b02 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -25,10 +25,12 @@ futures-util = { version = "0.3", features = ["alloc", "bilock", "sink", "unstab governor = { version = "0.6", default-features = false, features = ["std", "jitter"] } hmac = "0.12" httparse = "1.7" -http = "0.2" -hyper = { version = "0.14", features = ["client", "http1", "http2", "tcp"] } -hyper-proxy = { version = "0.9", default-features = false, features = ["rustls"] } -hyper-rustls = { version = "0.24", features = ["http2"] } +http = "1.0" +hyper = { version = "1.3", features = ["http1", "http2"] } +hyper-util = { version = "0.1", features = ["client"] } +http-body-util = "0.1.1" +hyper-proxy2 = { version = "0.1", default-features = false, features = ["rustls"] } +hyper-rustls = { version = "0.26", features = ["http2"] } log = "0.4" nonzero_ext = "0.3" num-bigint = { version = "0.4", features = ["rand"] } diff --git a/core/src/apresolve.rs b/core/src/apresolve.rs index 8eb1c4eb..37e4ba3d 100644 --- a/core/src/apresolve.rs +++ b/core/src/apresolve.rs @@ -1,6 +1,7 @@ use std::collections::VecDeque; -use hyper::{Body, Method, Request}; +use bytes::Bytes; +use hyper::{Method, Request}; use serde::Deserialize; use crate::Error; @@ -85,7 +86,7 @@ impl ApResolver { let req = Request::builder() .method(Method::GET) .uri("https://apresolve.spotify.com/?type=accesspoint&type=dealer&type=spclient") - .body(Body::empty())?; + .body(Bytes::new())?; let body = self.session().http_client().request_body(req).await?; let data: ApResolveData = serde_json::from_slice(body.as_ref())?; diff --git a/core/src/error.rs b/core/src/error.rs index ca58e779..13491a39 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -321,7 +321,7 @@ impl From for Error { impl From for Error { fn from(err: hyper::Error) -> Self { - if err.is_parse() || err.is_parse_too_large() || err.is_parse_status() || err.is_user() { + if err.is_parse() || err.is_parse_status() || err.is_user() { return Self::new(ErrorKind::Internal, err); } @@ -329,10 +329,6 @@ impl From for Error { return Self::new(ErrorKind::Cancelled, err); } - if err.is_connect() { - return Self::new(ErrorKind::Unavailable, err); - } - if err.is_incomplete_message() { return Self::new(ErrorKind::DataLoss, err); } @@ -349,6 +345,16 @@ impl From for Error { } } +impl From for Error { + fn from(err: hyper_util::client::legacy::Error) -> Self { + if err.is_connect() { + return Self::new(ErrorKind::Unavailable, err); + } + + Self::new(ErrorKind::Unknown, err) + } +} + impl From for Error { fn from(err: time::error::Parse) -> Self { Self::new(ErrorKind::FailedPrecondition, err) diff --git a/core/src/http_client.rs b/core/src/http_client.rs index 14efdcdf..4b500cd6 100644 --- a/core/src/http_client.rs +++ b/core/src/http_client.rs @@ -10,13 +10,14 @@ use governor::{ clock::MonotonicClock, middleware::NoOpMiddleware, state::InMemoryState, Quota, RateLimiter, }; use http::{header::HeaderValue, Uri}; -use hyper::{ - client::{HttpConnector, ResponseFuture}, - header::USER_AGENT, - Body, Client, HeaderMap, Request, Response, StatusCode, -}; -use hyper_proxy::{Intercept, Proxy, ProxyConnector}; +use http_body_util::{BodyExt, Full}; +use hyper::{body::Incoming, header::USER_AGENT, HeaderMap, Request, Response, StatusCode}; +use hyper_proxy2::{Intercept, Proxy, ProxyConnector}; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; +use hyper_util::{ + client::legacy::{connect::HttpConnector, Client, ResponseFuture}, + rt::TokioExecutor, +}; use nonzero_ext::nonzero; use once_cell::sync::OnceCell; use parking_lot::Mutex; @@ -89,7 +90,7 @@ impl From for Error { } } -type HyperClient = Client>, Body>; +type HyperClient = Client>, Full>; pub struct HttpClient { user_agent: HeaderValue, @@ -146,7 +147,7 @@ impl HttpClient { fn try_create_hyper_client(proxy_url: Option<&Url>) -> Result { // configuring TLS is expensive and should be done once per process let https_connector = HttpsConnectorBuilder::new() - .with_native_roots() + .with_native_roots()? .https_or_http() .enable_http1() .enable_http2() @@ -160,7 +161,7 @@ impl HttpClient { }; let proxy_connector = ProxyConnector::from_proxy(https_connector, proxy)?; - let client = Client::builder() + let client = Client::builder(TokioExecutor::new()) .http2_adaptive_window(true) .build(proxy_connector); Ok(client) @@ -171,23 +172,20 @@ impl HttpClient { .get_or_try_init(|| Self::try_create_hyper_client(self.proxy_url.as_ref())) } - pub async fn request(&self, req: Request) -> Result, Error> { + pub async fn request(&self, req: Request) -> Result, Error> { debug!("Requesting {}", req.uri().to_string()); // `Request` does not implement `Clone` because its `Body` may be a single-shot stream. // As correct as that may be technically, we now need all this boilerplate to clone it // ourselves, as any `Request` is moved in the loop. - let (parts, body) = req.into_parts(); - let body_as_bytes = hyper::body::to_bytes(body) - .await - .unwrap_or_else(|_| Bytes::new()); + let (parts, body_as_bytes) = req.into_parts(); loop { let mut req = Request::builder() .method(parts.method.clone()) .uri(parts.uri.clone()) .version(parts.version) - .body(Body::from(body_as_bytes.clone()))?; + .body(body_as_bytes.clone())?; *req.headers_mut() = parts.headers.clone(); let request = self.request_fut(req)?; @@ -212,20 +210,21 @@ impl HttpClient { } } - return Ok(response?); + let response = response?; + return Ok(response); } } - pub async fn request_body(&self, req: Request) -> Result { + pub async fn request_body(&self, req: Request) -> Result { let response = self.request(req).await?; - Ok(hyper::body::to_bytes(response.into_body()).await?) + Ok(response.into_body().collect().await?.to_bytes()) } - pub fn request_stream(&self, req: Request) -> Result, Error> { + pub fn request_stream(&self, req: Request) -> Result, Error> { Ok(self.request_fut(req)?.into_stream()) } - pub fn request_fut(&self, mut req: Request) -> Result { + pub fn request_fut(&self, mut req: Request) -> Result { let headers_mut = req.headers_mut(); headers_mut.insert(USER_AGENT, self.user_agent.clone()); @@ -251,7 +250,7 @@ impl HttpClient { )) })?; - Ok(self.hyper_client()?.request(req)) + Ok(self.hyper_client()?.request(req.map(Full::new))) } pub fn get_retry_after(headers: &HeaderMap) -> Option { diff --git a/core/src/spclient.rs b/core/src/spclient.rs index 072cf40c..5a41d148 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -10,10 +10,10 @@ use data_encoding::HEXUPPER_PERMISSIVE; use futures_util::future::IntoStream; use http::header::HeaderValue; use hyper::{ - client::ResponseFuture, header::{HeaderName, ACCEPT, AUTHORIZATION, CONTENT_TYPE, RANGE}, - Body, HeaderMap, Method, Request, + HeaderMap, Method, Request, }; +use hyper_util::client::legacy::ResponseFuture; use protobuf::{Enum, Message, MessageFull}; use rand::RngCore; use sha1::{Digest, Sha1}; @@ -156,7 +156,7 @@ impl SpClient { .method(&Method::POST) .uri("https://clienttoken.spotify.com/v1/clienttoken") .header(ACCEPT, HeaderValue::from_static("application/x-protobuf")) - .body(Body::from(body))?; + .body(body.into())?; self.session().http_client().request_body(request).await } @@ -465,7 +465,7 @@ impl SpClient { let mut request = Request::builder() .method(method) .uri(url) - .body(Body::from(body.to_owned()))?; + .body(body.to_owned().into())?; // Reconnection logic: keep getting (cached) tokens because they might have expired. let token = self @@ -727,7 +727,7 @@ impl SpClient { RANGE, HeaderValue::from_str(&format!("bytes={}-{}", offset, offset + length - 1))?, ) - .body(Body::empty())?; + .body(Bytes::new())?; let stream = self.session().http_client().request_stream(req)?; @@ -738,7 +738,7 @@ impl SpClient { let request = Request::builder() .method(&Method::GET) .uri(url) - .body(Body::empty())?; + .body(Bytes::new())?; self.session().http_client().request_body(request).await } diff --git a/discovery/Cargo.toml b/discovery/Cargo.toml index f4414ebd..345859b1 100644 --- a/discovery/Cargo.toml +++ b/discovery/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" [dependencies] aes = "0.8" base64 = "0.21" +bytes = "1" cfg-if = "1.0" ctr = "0.9" dns-sd = { version = "0.1.3", optional = true } @@ -18,7 +19,9 @@ form_urlencoded = "1.0" futures-core = "0.3" futures-util = "0.3" hmac = "0.12" -hyper = { version = "0.14", features = ["http1", "server", "tcp"] } +hyper = { version = "1.3", features = ["http1"] } +hyper-util = { version = "0.1", features = ["server-auto", "server-graceful", "service"] } +http-body-util = "0.1.1" libmdns = "0.8" log = "0.4" rand = "0.8" diff --git a/discovery/src/lib.rs b/discovery/src/lib.rs index 1764640b..8caeadfb 100644 --- a/discovery/src/lib.rs +++ b/discovery/src/lib.rs @@ -124,7 +124,7 @@ impl Builder { 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 server = DiscoveryServer::new(self.server_config, &mut port)?; let _zeroconf_ip = self.zeroconf_ip; let svc; diff --git a/discovery/src/server.rs b/discovery/src/server.rs index ccdbe685..6167275d 100644 --- a/discovery/src/server.rs +++ b/discovery/src/server.rs @@ -2,7 +2,7 @@ use std::{ borrow::Cow, collections::BTreeMap, convert::Infallible, - net::{Ipv4Addr, SocketAddr}, + net::{Ipv4Addr, SocketAddr, TcpListener}, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -11,14 +11,14 @@ use std::{ use aes::cipher::{KeyIvInit, StreamCipher}; use base64::engine::general_purpose::STANDARD as BASE64; use base64::engine::Engine as _; +use bytes::Bytes; use futures_core::Stream; use futures_util::{FutureExt, TryFutureExt}; use hmac::{Hmac, Mac}; -use hyper::{ - service::{make_service_fn, service_fn}, - Body, Method, Request, Response, StatusCode, -}; +use http_body_util::{BodyExt, Full}; +use hyper::{body::Incoming, Method, Request, Response, StatusCode}; +use hyper_util::{rt::TokioIo, server::graceful::GracefulShutdown}; use log::{debug, error, warn}; use serde_json::json; use sha1::{Digest, Sha1}; @@ -63,7 +63,7 @@ impl RequestHandler { (discovery, rx) } - fn handle_get_info(&self) -> Response { + fn handle_get_info(&self) -> Response> { let public_key = BASE64.encode(self.keys.public_key()); let device_type: &str = self.config.device_type.into(); let mut active_user = String::new(); @@ -107,11 +107,11 @@ impl RequestHandler { // - "deviceAPI_isGroup": False }) .to_string(); - - Response::new(Body::from(body)) + let body = Bytes::from(body); + Response::new(Full::new(body)) } - fn handle_add_user(&self, params: &Params<'_>) -> Result, Error> { + fn handle_add_user(&self, params: &Params<'_>) -> Result>, Error> { let username_key = "userName"; let username = params .get(username_key) @@ -171,7 +171,8 @@ impl RequestHandler { }); let body = result.to_string(); - return Ok(Response::new(Body::from(body))); + let body = Bytes::from(body); + return Ok(Response::new(Full::new(body))); } let decrypted = { @@ -193,10 +194,11 @@ impl RequestHandler { }); let body = result.to_string(); - Ok(Response::new(Body::from(body))) + let body = Bytes::from(body); + Ok(Response::new(Full::new(body))) } - fn not_found(&self) -> Response { + fn not_found(&self) -> Response> { let mut res = Response::default(); *res.status_mut() = StatusCode::NOT_FOUND; res @@ -204,8 +206,8 @@ impl RequestHandler { async fn handle( self: Arc, - request: Request, - ) -> Result>, Error> { + request: Request, + ) -> Result>>, Error> { let mut params = Params::new(); let (parts, body) = request.into_parts(); @@ -219,7 +221,7 @@ impl RequestHandler { debug!("{:?} {:?} {:?}", parts.method, parts.uri.path(), params); } - let body = hyper::body::to_bytes(body).await?; + let body = body.collect().await?.to_bytes(); params.extend(form_urlencoded::parse(&body)); @@ -239,52 +241,77 @@ pub struct DiscoveryServer { } impl DiscoveryServer { - pub fn new(config: Config, port: &mut u16) -> Result, Error> { + pub fn new(config: Config, port: &mut u16) -> Result { let (discovery, cred_rx) = RequestHandler::new(config); - let discovery = Arc::new(discovery); + let address = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), *port); let (close_tx, close_rx) = oneshot::channel(); - let address = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), *port); - - let make_service = make_service_fn(move |_| { - let discovery = discovery.clone(); - async move { - Ok::<_, hyper::Error>(service_fn(move |request| { - discovery - .clone() - .handle(request) - .inspect_err(|e| error!("could not handle discovery request: {}", e)) - .and_then(|x| async move { Ok(x) }) - .map(Result::unwrap) // guaranteed by `and_then` above - })) + let listener = match TcpListener::bind(address) { + Ok(listener) => listener, + Err(e) => { + warn!("Discovery server failed to start: {e}"); + return Err(e.into()); } - }); + }; - let server = hyper::Server::try_bind(&address)?.serve(make_service); + listener.set_nonblocking(true)?; + let listener = tokio::net::TcpListener::from_std(listener)?; - *port = server.local_addr().port(); - debug!("Zeroconf server listening on 0.0.0.0:{}", *port); + match listener.local_addr() { + Ok(addr) => { + *port = addr.port(); + debug!("Zeroconf server listening on 0.0.0.0:{}", *port); + } + Err(e) => { + warn!("Discovery server failed to start: {e}"); + return Err(e.into()); + } + } - tokio::spawn(async { - let result = server - .with_graceful_shutdown(async { - if let Err(e) = close_rx.await { - debug!("unable to close discovery Rx channel completely: {e}"); + tokio::spawn(async move { + let discovery = Arc::new(discovery); + + let server = hyper::server::conn::http1::Builder::new(); + let graceful = GracefulShutdown::new(); + let mut close_rx = std::pin::pin!(close_rx); + loop { + tokio::select! { + Ok((stream, _)) = listener.accept() => { + let io = TokioIo::new(stream); + let discovery = discovery.clone(); + + let svc = hyper::service::service_fn(move |request| { + discovery + .clone() + .handle(request) + .inspect_err(|e| error!("could not handle discovery request: {}", e)) + .and_then(|x| async move { Ok(x) }) + .map(Result::unwrap) // guaranteed by `and_then` above + }); + + let conn = server.serve_connection(io, svc); + let fut = graceful.watch(conn); + tokio::spawn(async move { + // Errors are logged in the service_fn + let _ = fut.await; + }); } - debug!("Shutting down discovery server"); - }) - .await; - - if let Err(e) = result { - warn!("Discovery server failed: {}", e); + _ = &mut close_rx => { + debug!("Shutting down discovery server"); + break; + } + } } + + graceful.shutdown().await; + debug!("Discovery server stopped"); }); - Ok(Ok(Self { + Ok(Self { cred_rx, _close_tx: close_tx, - })) + }) } }