diff --git a/Cargo.lock b/Cargo.lock index 03b486a7..73f8800a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,10 +7,11 @@ dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "eventual 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)", "json_macros 0.3.1 (git+https://github.com/plietar/json_macros)", "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libpulse-sys 0.0.0 (git+https://github.com/astro/libpulse-sys)", @@ -29,14 +30,14 @@ dependencies = [ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)", "tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)", - "url 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vorbis 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -81,6 +82,29 @@ dependencies = [ "syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bit-set" version = "0.4.0" @@ -125,13 +149,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cookie" -version = "0.2.5" +name = "crossbeam" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "ctrlc" @@ -143,6 +163,15 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dbghelp-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dns-parser" version = "0.3.2" @@ -167,6 +196,14 @@ dependencies = [ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "eventual" version = "0.1.7" @@ -185,6 +222,16 @@ dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-cpupool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.41" @@ -195,14 +242,6 @@ name = "getopts" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "hpack" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "httparse" version = "1.2.1" @@ -210,20 +249,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.11.0-a.0" +source = "git+https://github.com/hyperium/hyper#39a53fcd3364634125dafcf4d7a1d191241a7ff0" dependencies = [ - "cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -337,7 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdns" version = "0.2.0" -source = "git+https://github.com/plietar/rust-mdns#8ea956858dcd900b02d795f35f884034d15cf8e8" +source = "git+https://github.com/plietar/rust-mdns#51f0ffded504a576350fc5a8b4bdfe7144db3f6e" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)", @@ -630,6 +670,14 @@ name = "regex-syntax" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "relay" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rpassword" version = "0.3.0" @@ -653,6 +701,11 @@ dependencies = [ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-demangle" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-serialize" version = "0.3.22" @@ -706,7 +759,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -752,15 +805,6 @@ name = "smallvec" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "solicit" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syncbox" version = "0.2.4" @@ -1003,11 +1047,6 @@ dependencies = [ "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "traitobject" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "tremor" version = "0.1.0" @@ -1028,11 +1067,6 @@ dependencies = [ "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicase" version = "1.4.0" @@ -1064,18 +1098,6 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "url" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "url" version = "1.3.0" @@ -1090,14 +1112,6 @@ name = "utf8-ranges" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "uuid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "vergen" version = "0.1.1" @@ -1185,6 +1199,8 @@ dependencies = [ "checksum aster 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258989846dd255a1e0eeef92d425d345477c9999433cecc9f0879f4549d5e5c9" "checksum aster 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88bb8ecdf6a7eaddb7bfd872ebf5e085d343ca42ce98c582dba8046e3450b524" "checksum aster 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "022822e5621c840afed9d4fbdf52104bfc2ff6f0f64016a6bbe4e10d7ec70535" +"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" +"checksum backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" @@ -1193,18 +1209,20 @@ dependencies = [ "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" -"checksum cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e3d6405328b6edb412158b3b7710e2634e23f3614b9bb1c412df7952489a626" +"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77f98bb69e3fefadcc5ca80a1368a55251f70295168203e01165bcaecb270891" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)" = "" "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" +"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f" "checksum eventual 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b9bda6d089b434ca50f3d6feb5fca421309b8bac97b8be9af51cff879fa3f54b" "checksum futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3e0b237aed5d8b61bc7d6ee1b8ebd719d0a934a38d363c5e56daf34bb634d9b2" +"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82" "checksum gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)" = "3689e1982a563af74960ae3a4758aa632bb8fd984cfc3cc3b60ee6109477ab6e" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" "checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" -"checksum hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb3fc65554155980167fb821d05c7c66177f92464976c0b676a19d9e03387a7" +"checksum hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)" = "" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum json_macros 0.3.1 (git+https://github.com/plietar/json_macros)" = "" @@ -1251,8 +1269,10 @@ dependencies = [ "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6e42be826e215f30ff830904f8f4a0933c6e2ae890e1af8b408f5bae60081e" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc" "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" @@ -1260,13 +1280,12 @@ dependencies = [ "checksum serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4aab5b62fb90ac9c99d5a55caa7c37e06a15d1b189ccc2b117782655fd11f" "checksum serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da68810d845f8e33a80243c28794650397056cbe7aea4c9c7516f55d1061c94e" "checksum serde_codegen_internals 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0115c5c602e81c61b787fb0f0fa76a614f8dbe9100b2b59b7d590155672c80" -"checksum serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7d3c184d35801fb8b32b46a7d58d57dbcc150b0eb2b46a1eb79645e8ecfd5b" +"checksum serde_json 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6555a29b090ddb20dbb00226dede6b824149b4c32d6034af6040e22424939311" "checksum serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cf1c01933271e1e72bb788e0499d1bca8af2c09efcc3ddc0b04ff22d080b83" "checksum shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)" = "" "checksum shannon-sys 0.1.0 (git+https://github.com/plietar/rust-shannon)" = "" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2" "checksum syncbox 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "05bc2b72659ac27a2d0e7c4166c8596578197c4c41f767deab12c81f523b85c7" "checksum syntex 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84f37b94d7ee762bcac58741f73a95465cf87188c3b93f10df9245aff821b2b4" "checksum syntex 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd253b0d7d787723a33384d426f0ebec7f8edccfaeb2022d0177162bb134da0" @@ -1290,19 +1309,15 @@ dependencies = [ "checksum tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0800e9475303171ffbc79394079ef503b6d00949649799208f4fc8f1eca20892" "checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616" "checksum tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "" "checksum tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" "checksum unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b61814f3e7fd0e0f15370f767c7c943e08bc2e3214233ae8f88522b334ceb778" "checksum unicode-normalization 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5e94e9f6961090fcc75180629c4ef33e5310d6ed2c0dd173f4ca63c9043b669e" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum url 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3440c1ed62af4a2aee71c6fb78ef32ddcb75cfa24bf42f45e07c02b6d6a2f6" "checksum url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbcb1997952b5a73b438a90940834621a8002e59640a8d92a1c05ef8fa58a1da" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum uuid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "885acc3b17fdef6230d1f7765dff1106dfd5e75a93c2f26459fbf600ed6dcc14" "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum vorbis 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "760993e54524128b88d4d7aff09c773c2f16a9f18db3c8ae1ccca5afd1287656" diff --git a/Cargo.toml b/Cargo.toml index 69548efa..122a93ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,13 +27,13 @@ ctrlc = { version = "2.0", features = ["termination"] } env_logger = "0.3.2" eventual = "0.1.6" getopts = "0.2.14" -hyper = { version = "0.9.1", default-features = false } +hyper = { git = "https://github.com/hyperium/hyper" } lazy_static = "0.2.0" linear-map = "1.0" lmdb-rs = "0.7.2" log = "0.3.5" num = "0.1.30" -protobuf = "1.0.15" +protobuf = "1.1" rand = "0.3.13" rpassword = "0.3.0" rust-crypto = "0.2.34" @@ -43,7 +43,7 @@ serde_json = "0.8" serde_macros = { version = "0.8", optional = true } shannon = { git = "https://github.com/plietar/rust-shannon" } tempfile = "2.1" -url = "0.5.0" +url = "1.3" vorbis = "0.1.0" tremor = { git = "https://github.com/plietar/rust-tremor", optional = true } @@ -57,9 +57,10 @@ protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" } mdns = { git = "https://github.com/plietar/rust-mdns" } +error-chain = "0.7.0" futures = "0.1.8" -tokio-proto = "0.1.0" tokio-core = "0.1.2" +tokio-proto = "0.1.0" [build-dependencies] vergen = "0.1.0" diff --git a/src/apresolve.rs b/src/apresolve.rs index 809b9bcb..087b60d9 100644 --- a/src/apresolve.rs +++ b/src/apresolve.rs @@ -1,27 +1,56 @@ -const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/"; const AP_FALLBACK : &'static str = "ap.spotify.com:80"; +const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/"; -use hyper; -use std::io::Read; +use futures::{Future, Stream}; +use hyper::{self, Url, Client}; use serde_json; +use tokio_core::reactor::Handle; +error_chain! { } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct APResolveData { ap_list: Vec } -pub fn apresolve() -> String { - let client = hyper::Client::new(); +pub fn apresolve(handle: &Handle) -> Box> { + let url = Url::parse(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL"); - (|| { - let mut response = client.get(APRESOLVE_ENDPOINT).send().map_err(|_| ())?; - let mut data = String::new(); - response.read_to_string(&mut data).map_err(|_| ())?; + let client = Client::new(&handle); + let response = client.get(url); - let data : APResolveData = serde_json::from_str(&data).map_err(|_| ())?; - data.ap_list.first().map(Clone::clone).ok_or(()) - })().unwrap_or_else(|_| { - warn!("failed to resolve AP, using fallback"); - AP_FALLBACK.into() - }) + let body = response.and_then(|response| { + response.body().fold(Vec::new(), |mut acc, chunk| { + acc.extend_from_slice(chunk.as_ref()); + Ok::<_, hyper::Error>(acc) + }) + }); + let body = body.then(|result| result.chain_err(|| "HTTP error")); + let body = body.and_then(|body| { + String::from_utf8(body).chain_err(|| "invalid UTF8 in response") + }); + + let data = body.and_then(|body| { + serde_json::from_str::(&body) + .chain_err(|| "invalid JSON") + }); + + let ap = data.and_then(|data| { + let ap = data.ap_list.first().ok_or("empty AP List")?; + Ok(ap.clone()) + }); + + Box::new(ap) +} + +pub fn apresolve_or_fallback(handle: &Handle) + -> Box> + where E: 'static +{ + let ap = apresolve(handle).or_else(|e| { + warn!("Failed to resolve Access Point: {}", e.description()); + warn!("Using fallback \"{}\"", AP_FALLBACK); + Ok(AP_FALLBACK.into()) + }); + + Box::new(ap) } diff --git a/src/authentication/discovery.rs b/src/authentication/discovery.rs index a27e7095..33f1b60c 100644 --- a/src/authentication/discovery.rs +++ b/src/authentication/discovery.rs @@ -1,34 +1,70 @@ -use crypto; -use crypto::mac::Mac; use crypto::digest::Digest; -use hyper; -use hyper::net::NetworkListener; +use crypto::mac::Mac; +use crypto; +use diffie_hellman::{DH_GENERATOR, DH_PRIME}; +use futures::{Future, Stream, BoxFuture}; +use futures::sync::mpsc; +use hyper::{self, Get, Post, StatusCode}; +use hyper::server::{Server, Service, NewService, Request, Response}; +use mdns; use num::BigUint; -use url; use rand; use rustc_serialize::base64::{self, ToBase64, FromBase64}; +use std::io; use std::collections::BTreeMap; -use std::io::{Read, Write}; -use std::sync::{mpsc, Mutex}; -use mdns; +use std::sync::Arc; +use url; +use tokio_core::reactor::Handle; +use std::net::SocketAddr; use authentication::Credentials; -use diffie_hellman::{DH_GENERATOR, DH_PRIME}; +use connection::adaptor::adapt_future; use util; -struct ServerHandler { - credentials_tx: Mutex>, +#[derive(Clone)] +struct Discovery(Arc); +struct DiscoveryInner { private_key: BigUint, public_key: BigUint, device_id: String, device_name: String, + tx: mpsc::UnboundedSender, } -impl ServerHandler { - fn handle_get_info(&self, _params: &BTreeMap, - mut response: hyper::server::Response) { +impl Discovery { + pub fn new(device_name: String, device_id: String) + -> (Discovery, mpsc::UnboundedReceiver) + { + let (tx, rx) = mpsc::unbounded(); - let public_key = self.public_key.to_bytes_be() + 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 discovery = Discovery(Arc::new(DiscoveryInner { + device_name: device_name.to_owned(), + device_id: device_id.to_owned(), + private_key: private_key, + public_key: public_key, + tx: tx, + })); + + (discovery, rx) + } + + pub fn serve(&self, addr: &SocketAddr, handle: &Handle) + -> hyper::Result + { + let server = Server::http(&addr, handle)?; + server.handle(self.clone(), handle) + } +} + +impl Discovery { + fn handle_get_info(&self, _params: &BTreeMap) + -> ::futures::Finished + { + let public_key = self.0.public_key.to_bytes_be() .to_base64(base64::STANDARD); let result = json!({ @@ -36,8 +72,8 @@ impl ServerHandler { "statusString": "ERROR-OK", "spotifyError": 0, "version": "2.1.0", - "deviceID": (self.device_id), - "remoteName": (self.device_name), + "deviceID": (self.0.device_id), + "remoteName": (self.0.device_name), "activeUser": "", "publicKey": (public_key), "deviceType": "UNKNOWN", @@ -47,13 +83,13 @@ impl ServerHandler { "modelDisplayName": "librespot", }); - *response.status_mut() = hyper::status::StatusCode::Ok; - response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap(); + let body = result.to_string(); + ::futures::finished(Response::new().with_body(body)) } - fn handle_add_user(&self, params: &BTreeMap, - mut response: hyper::server::Response) { - + fn handle_add_user(&self, params: &BTreeMap) + -> ::futures::Finished + { let username = params.get("userName").unwrap(); let encrypted_blob = params.get("blob").unwrap(); let client_key = params.get("clientKey").unwrap(); @@ -63,7 +99,7 @@ impl ServerHandler { 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 shared_key = util::powm(&client_key, &self.0.private_key, &DH_PRIME); let iv = &encrypted_blob[0..16]; let encrypted = &encrypted_blob[16..encrypted_blob.len() - 20]; @@ -106,9 +142,9 @@ impl ServerHandler { String::from_utf8(data).unwrap() }; - let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.device_id); + let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.0.device_id); - self.credentials_tx.lock().unwrap().send(credentials).unwrap(); + self.0.tx.send(credentials).unwrap(); let result = json!({ "status": 101, @@ -116,74 +152,87 @@ impl ServerHandler { "statusString": "ERROR-OK" }); - *response.status_mut() = hyper::status::StatusCode::Ok; - response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap(); + let body = result.to_string(); + ::futures::finished(Response::new().with_body(body)) } - fn not_found(&self, mut response: hyper::server::Response) { - - *response.status_mut() = hyper::status::StatusCode::NotFound + fn not_found(&self) + -> ::futures::Finished + { + ::futures::finished(Response::new().with_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>) { +impl Service for Discovery { + type Request = Request; + type Response = Response; + type Error = hyper::Error; + type Future = BoxFuture; - 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::>(); + fn call(&self, request: Request) -> Self::Future { + let mut params = BTreeMap::new(); - 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); - } - - debug!("{:?} {:?} {:?}", request.method, path, params); - - match params.get("action").map(AsRef::as_ref) { - Some("getInfo") => self.handle_get_info(¶ms, response), - Some("addUser") => self.handle_add_user(¶ms, response), - _ => self.not_found(response), - } - } else { - self.not_found(response) + let (method, uri, _, _, body) = request.deconstruct(); + if let Some(query) = uri.query() { + params.extend(url::form_urlencoded::parse(query.as_bytes()).into_owned()); } + + debug!("{:?} {:?} {:?}", method, uri.path(), params); + + let this = self.clone(); + body.fold(Vec::new(), |mut acc, chunk| { + acc.extend_from_slice(chunk.as_ref()); + Ok::<_, hyper::Error>(acc) + }).map(move |body| { + params.extend(url::form_urlencoded::parse(&body).into_owned()); + params + }).and_then(move |params| { + match (method, params.get("action").map(AsRef::as_ref)) { + (Get, Some("getInfo")) => this.handle_get_info(¶ms), + (Post, Some("addUser")) => this.handle_add_user(¶ms), + _ => this.not_found(), + } + }).boxed() } } -pub fn discovery_login(device_name: &str, device_id: &str) -> Result { - let (tx, rx) = mpsc::channel(); +impl NewService for Discovery { + type Request = Request; + type Response = Response; + type Error = hyper::Error; + type Instance = Self; - 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 responder = mdns::Responder::new().unwrap(); - let _svc = responder.register( - "_spotify-connect._tcp".to_owned(), - device_name.to_owned(), - port, - &["VERSION=1.0", "CPath=/"]); - - let cred = rx.recv().unwrap(); - server.close().unwrap(); - Ok(cred) + fn new_service(&self) -> io::Result { + Ok(self.clone()) + } +} + +pub fn discovery_login(device_name: A, device_id: B) -> Result + where A: Into, + B: Into +{ + let device_name = device_name.into(); + let device_id = device_id.into(); + + let (discovery, rx) = Discovery::new(device_name.clone(), device_id); + + let addr = "0.0.0.0:0".parse().unwrap(); + let cred = adapt_future(move |handle| { + let addr = discovery.serve(&addr, &handle).unwrap(); + + let responder = mdns::Responder::spawn(&handle).unwrap(); + let svc = responder.register( + "_spotify-connect._tcp".to_owned(), + device_name, + addr.port(), + &["VERSION=1.0", "CPath=/"]); + + rx.into_future() + .map(move |(creds, _)| (creds, svc)) + .map_err(|(e, _)| e) + }); + + + let (creds, _svc) = cred.wait().unwrap().unwrap(); + Ok(creds.unwrap()) } diff --git a/src/authentication/mod.rs b/src/authentication/mod.rs index 7fec380f..8d69f610 100644 --- a/src/authentication/mod.rs +++ b/src/authentication/mod.rs @@ -197,7 +197,8 @@ pub fn get_credentials(session: &Session, username: Option, password: Op (None, _, None) => { info!("No username provided and no stored credentials, starting discovery ..."); - discovery_login(&session.config().device_name, session.device_id()).unwrap() + discovery_login(session.config().device_name.clone(), + session.device_id()).unwrap() } } } diff --git a/src/connection/adaptor.rs b/src/connection/adaptor.rs index a8458c7b..aab88399 100644 --- a/src/connection/adaptor.rs +++ b/src/connection/adaptor.rs @@ -1,5 +1,6 @@ use futures::future::ok; use futures::sync::mpsc; +use futures::sync::oneshot; use futures::{Future, Sink, Stream, BoxFuture, IntoFuture}; use std::thread; use tokio_core::reactor::Core; @@ -52,7 +53,7 @@ fn adapt_stream(stream: S, tx: mpsc::Sender>) -> Bo } pub fn adapt(f: F) -> (SinkAdaptor, StreamAdaptor) - where F: FnOnce(&Handle) -> U + Send + 'static, + where F: FnOnce(Handle) -> U + Send + 'static, U: IntoFuture, S: Sink + Stream + Send + 'static, S::Item: Send + 'static, @@ -69,7 +70,7 @@ pub fn adapt(f: F) -> (SinkAdaptor, StreamAdaptor(f: F) -> (SinkAdaptor, StreamAdaptor(f: F) -> oneshot::Receiver> + where F: FnOnce(Handle) -> U + Send + 'static, + U: IntoFuture, + U::Item: Send + 'static, + U::Error: Send + 'static, +{ + let (tx, rx) = oneshot::channel(); + + thread::spawn(move || { + let mut core = Core::new().unwrap(); + let handle = core.handle(); + + let task = f(handle).into_future(); + let result = core.run(task); + + tx.complete(result); + }); + + rx +} diff --git a/src/lib.in.rs b/src/lib.in.rs index 8b6ddfe4..57686bb6 100644 --- a/src/lib.in.rs +++ b/src/lib.in.rs @@ -2,5 +2,4 @@ pub mod apresolve; pub mod authentication; pub mod connection; pub mod mercury; -pub mod session; pub mod spirc; diff --git a/src/lib.rs b/src/lib.rs index d8f3378b..1ce4b166 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ #![cfg_attr(feature="clippy", feature(plugin))] #![cfg_attr(feature="clippy", plugin(clippy))] +#[macro_use] extern crate error_chain; +#[macro_use] extern crate futures; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; @@ -29,11 +31,9 @@ extern crate serde; extern crate serde_json; extern crate shannon; extern crate tempfile; -extern crate url; - -#[macro_use] extern crate futures; extern crate tokio_core; extern crate tokio_proto; +extern crate url; extern crate librespot_protocol as protocol; @@ -60,6 +60,7 @@ pub mod diffie_hellman; pub mod link; pub mod metadata; pub mod player; +pub mod session; pub mod stream; pub mod util; pub mod version; diff --git a/src/session.rs b/src/session.rs index af976685..c913e489 100644 --- a/src/session.rs +++ b/src/session.rs @@ -12,7 +12,7 @@ use futures::Stream; use futures::sync::oneshot; use album_cover::AlbumCover; -use apresolve::apresolve; +use apresolve::apresolve_or_fallback; use audio_file::AudioFile; use audio_key::{AudioKeyManager, AudioKey, AudioKeyError}; use authentication::Credentials; @@ -101,26 +101,29 @@ impl Session { } pub fn login(&self, credentials: Credentials) -> Result { - let addr = apresolve(); let device_id = self.device_id().to_owned(); let (creds_tx, creds_rx) = oneshot::channel(); - info!("Connecting to AP {}", addr); - let (tx, rx) = adaptor::adapt(move |handle| { - let connection = connection::connect(&addr as &str, &handle); - let authentication = connection.and_then(|connection| { - connection::authenticate(connection, credentials, device_id) - }); + let access_point = apresolve_or_fallback::(&handle); - authentication.map(|(transport, creds)| { - creds_tx.complete(creds); - transport.map(|(cmd, data)| (cmd, data.as_ref().to_owned())) - }) + let connection = access_point.and_then(move |addr| { + info!("Connecting to AP \"{}\"", addr); + connection::connect::<&str>(&addr, &handle) + }); + + let authentication = connection.and_then(move |connection| { + connection::authenticate(connection, credentials, device_id) + }); + + authentication.map(|(transport, creds)| { + creds_tx.complete(creds); + transport.map(|(cmd, data)| (cmd, data.as_ref().to_owned())) + }) }); - let reusable_credentials = creds_rx.wait().unwrap(); + let reusable_credentials: Credentials = creds_rx.wait().unwrap(); self.0.data.write().unwrap().canonical_username = reusable_credentials.username.clone(); *self.0.rx_connection.lock().unwrap() = Some(rx);