Allow switching user accounts at runtime

Fixes #130
This commit is contained in:
Paul Lietar 2017-02-22 04:17:04 +00:00
parent 2853e2230b
commit d940ed161a
12 changed files with 437 additions and 194 deletions

161
Cargo.lock generated
View file

@ -6,7 +6,6 @@ dependencies = [
"base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -27,13 +26,14 @@ dependencies = [
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
"shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)",
"tempfile 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)",
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -61,7 +61,7 @@ name = "aster"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -72,6 +72,14 @@ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-set"
version = "0.4.0"
@ -100,6 +108,11 @@ name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "0.5.3"
@ -120,16 +133,6 @@ name = "crossbeam"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ctrlc"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dns-parser"
version = "0.3.2"
@ -169,7 +172,7 @@ dependencies = [
[[package]]
name = "futures-cpupool"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -195,11 +198,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.11.0-a.0"
source = "git+https://github.com/hyperium/hyper#2f18ce20348392893f6815519f8c0ad2b5649e66"
source = "git+https://github.com/hyperium/hyper#435fe84bf52fbbf819068402d6c8e902aa7a6685"
dependencies = [
"base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.3 (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)",
@ -220,7 +223,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -336,6 +339,15 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-uds"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.2.0"
@ -454,8 +466,8 @@ version = "0.6.0"
source = "git+https://github.com/plietar/rust-protobuf-macros#f186dc5a16c0d79f14c319ac8ce30b06de0cefee"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -465,7 +477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -489,7 +501,7 @@ dependencies = [
"aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -554,36 +566,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.9.6"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_codegen_internals"
version = "0.13.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "0.9.6"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "0.9.5"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -617,37 +629,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.11.4"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex"
version = "0.58.0"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_errors"
version = "0.58.0"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_pos"
version = "0.58.0"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
@ -655,14 +676,14 @@ dependencies = [
[[package]]
name = "syntex_syntax"
version = "0.58.0"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -711,7 +732,7 @@ dependencies = [
[[package]]
name = "thread_local"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -765,6 +786,20 @@ dependencies = [
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-signal"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.10 (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)",
"mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tremor"
version = "0.1.0"
@ -795,7 +830,7 @@ dependencies = [
[[package]]
name = "unicode-bidi"
version = "0.2.4"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -919,22 +954,23 @@ dependencies = [
"checksum alsa 0.0.1 (git+https://github.com/plietar/rust-alsa)" = "<none>"
"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0"
"checksum base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d156a04ec694d726e92ea3c13e4a62949b4f0488a9344f04341d679ec6b127b"
"checksum base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065a0ce220ab84d0b6d5ae3e7bb77232209519c366f51f946fe28c19e84989d0"
"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"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
"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 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 dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)" = "<none>"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
"checksum error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92ecf0a508c8e074c0e6fa8fe0fa38414848ad4dfc4db6f74c5e9753330b248"
"checksum futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c1913eb7083840b1bbcbf9631b7fda55eaf35fe7ead13cca034e8946f9e2bc41"
"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
"checksum futures-cpupool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e48a3fff6a58fe9df1eed13d2599650416a987386c43a19aec656c3e6a2c229"
"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
@ -954,6 +990,7 @@ dependencies = [
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
"checksum mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "eecdbdd49a849336e77b453f021c89972a2cfb5b51931a0026ae0ac4602de681"
"checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de"
"checksum miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a78d2605eb97302c10cf944b8d96b0a2a890c52957caf92fcd1f24f69049579"
"checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2"
"checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2"
@ -969,7 +1006,7 @@ dependencies = [
"checksum protobuf 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22eaac7d4be49a479dbd875f6f84ab79eef282aa51ba36ce884ec10efd91d355"
"checksum protobuf_macros 0.6.0 (git+https://github.com/plietar/rust-protobuf-macros)" = "<none>"
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
"checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"
"checksum quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08de3f12e670f83f61e450443cbae34496a35b665691fd8e99b24ec662f75865"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
"checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
@ -981,33 +1018,35 @@ dependencies = [
"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"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9"
"checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96"
"checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf"
"checksum serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cf37ce931677e98b4fa5e6469aaa3ab4b6228309ea33b1b22d3ec055adfc4515"
"checksum serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "204db0f2a5335be7313fd4453132fd56d2085aed081c673140a256772903e116"
"checksum serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5113d5bd16471b183803b374f0fe4877ad9658b95e33b11f4a004d73aacc74a"
"checksum serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e88ec062a02cbebfd6276044a305d665a9919b497aa6acb2e12c070d1a50d32d"
"checksum serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6501ac6f8b74f9b1033f7ddf79a08edfa0f58d6f8e3190cb8dc97736afa257a8"
"checksum shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)" = "<none>"
"checksum shannon-sys 0.1.0 (git+https://github.com/plietar/rust-shannon)" = "<none>"
"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 syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f94368aae82bb29656c98443a7026ca931a659e8d19dcdc41d6e273054e820"
"checksum syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35f3cc9d446323ef8fefad933b65cd6de271d29fa14a2e9d036a084770c6d6d5"
"checksum syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3af03823ea45d420dd2c1a44bb074e13ea55f9b99afe960fd58eb4069b7f6cad"
"checksum syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e502a4a904d9f37cf975dbdbb0b08f2d111322f6792bda6eb095b4112c9a24b"
"checksum syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf936464c3863952ea3fab848860ea891eba8647b6008b04c36f0bb007192a3"
"checksum syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e28da8d02d75d1e58b89258e0741128f0b0d8a8309fb5c627be0fbd37a76c67"
"checksum synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fece1853fb872b0acdc3ff88f37c474018e125ef81cd4cb8c0ca515746b62ed"
"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e"
"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c"
"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047"
"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791"
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
"checksum tempfile 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3213fd2b7ed87e39306737ccfac04b1233b57a33ca64cfbf52f2ffaa2b765e2f"
"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
"checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
"checksum tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1be481b55126f02ef88ff86748086473cb537a949fc4a8f4be403a530ae54b"
"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 tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d121715f6917878a0df69f39365d01dd66c4463e4ba19efdcddcdfeb1bcb2bc"
"checksum tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
"checksum tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
"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-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"

View file

@ -25,7 +25,6 @@ path = "protocol"
base64 = "0.3.0"
bit-set = "0.4.0"
byteorder = "1.0"
ctrlc = { version = "2.0", features = ["termination"] }
env_logger = "0.4.0"
getopts = "0.2.14"
hyper = { git = "https://github.com/hyperium/hyper" }
@ -59,6 +58,7 @@ error-chain = { version = "0.9.0", default_features = false }
futures = "0.1.8"
tokio-core = "0.1.2"
tokio-proto = "0.1.0"
tokio-signal = "0.1"
[build-dependencies]
vergen = "0.1.0"

View file

@ -4,7 +4,7 @@ use crypto::mac::Mac;
use crypto;
use diffie_hellman::{DH_GENERATOR, DH_PRIME};
use futures::sync::mpsc;
use futures::{Future, Stream, BoxFuture};
use futures::{Future, Stream, BoxFuture, Poll, Async};
use hyper::server::{Service, NewService, Request, Response, Http};
use hyper::{self, Get, Post, StatusCode};
use mdns;
@ -12,7 +12,6 @@ use num_bigint::BigUint;
use rand;
use std::collections::BTreeMap;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio_core::net::TcpListener;
use tokio_core::reactor::Handle;
@ -51,26 +50,6 @@ impl Discovery {
(discovery, rx)
}
pub fn serve(&self, addr: &SocketAddr, handle: &Handle)
-> hyper::Result<SocketAddr>
{
let listener = TcpListener::bind(addr, handle)?;
let addr = listener.local_addr()?;
let http = Http::new();
let svc = self.clone();
let handle_ = handle.clone();
let task = listener.incoming().for_each(move |(socket, addr)| {
http.bind_connection(&handle_, socket, addr, svc.clone());
Ok(())
});
handle.spawn(task.map_err(|e| panic!(e)));
Ok(addr)
}
}
impl Discovery {
@ -189,7 +168,9 @@ impl Service for Discovery {
params.extend(url::form_urlencoded::parse(query.as_bytes()).into_owned());
}
debug!("{:?} {:?} {:?}", method, uri.path(), params);
if method != Get {
debug!("{:?} {:?} {:?}", method, uri.path(), params);
}
let this = self.clone();
body.fold(Vec::new(), |mut acc, chunk| {
@ -219,34 +200,51 @@ impl NewService for Discovery {
}
}
use tokio_core::reactor::Core;
pub struct DiscoveryStream {
credentials: mpsc::UnboundedReceiver<Credentials>,
_svc: mdns::Service,
task: Box<Future<Item=(), Error=io::Error>>,
}
pub fn discovery_login<A,B>(device_name: A, device_id: B) -> Result<Credentials, ()>
where A: Into<String>,
B: Into<String>
pub fn discovery(handle: &Handle, device_name: String, device_id: String)
-> io::Result<DiscoveryStream>
{
let device_name = device_name.into();
let device_id = device_id.into();
let (discovery, creds_rx) = Discovery::new(device_name.clone(), device_id);
let creds_rx = creds_rx.into_future()
.map(move |(creds, _)| creds.unwrap()).map_err(|(e, _)| e);
let listener = TcpListener::bind(&"0.0.0.0:0".parse().unwrap(), handle)?;
let addr = listener.local_addr()?;
let addr = "0.0.0.0:0".parse().unwrap();
let http = Http::new();
let handle_ = handle.clone();
let task = Box::new(listener.incoming().for_each(move |(socket, addr)| {
http.bind_connection(&handle_, socket, addr, discovery.clone());
Ok(())
}));
let mut core = Core::new().unwrap();
let handle = core.handle();
let listening_addr = discovery.serve(&addr, &handle).unwrap();
let responder = mdns::Responder::spawn(&handle).unwrap();
let _svc = responder.register(
let responder = mdns::Responder::spawn(&handle)?;
let svc = responder.register(
"_spotify-connect._tcp".to_owned(),
device_name,
listening_addr.port(),
addr.port(),
&["VERSION=1.0", "CPath=/"]);
let creds = core.run(creds_rx).unwrap();
Ok(creds)
Ok(DiscoveryStream {
credentials: creds_rx,
_svc: svc,
task: task,
})
}
impl Stream for DiscoveryStream {
type Item = Credentials;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.task.poll()? {
Async::Ready(()) => unreachable!(),
Async::NotReady => (),
}
Ok(self.credentials.poll().unwrap())
}
}

View file

@ -16,6 +16,8 @@ use std::path::Path;
use protocol::authentication::AuthenticationType;
pub mod discovery;
#[derive(Debug, Clone)]
#[derive(Serialize, Deserialize)]
pub struct Credentials {
@ -169,35 +171,28 @@ fn deserialize_base64<D>(de: D) -> Result<Vec<u8>, D::Error>
base64::decode(&v).map_err(|e| serde::de::Error::custom(e.to_string()))
}
mod discovery;
pub use self::discovery::discovery_login;
pub fn get_credentials(device_name: &str, device_id: &str,
username: Option<String>, password: Option<String>,
pub fn get_credentials(username: Option<String>, password: Option<String>,
cached_credentials: Option<Credentials>)
-> Credentials
-> Option<Credentials>
{
match (username, password, cached_credentials) {
(Some(username), Some(password), _)
=> Credentials::with_password(username, password),
=> Some(Credentials::with_password(username, password)),
(Some(ref username), _, Some(ref credentials))
if *username == credentials.username => credentials.clone(),
if *username == credentials.username => Some(credentials.clone()),
(Some(username), None, _) => {
write!(stderr(), "Password for {}: ", username).unwrap();
stderr().flush().unwrap();
let password = rpassword::read_password().unwrap();
Credentials::with_password(username.clone(), password)
Some(Credentials::with_password(username.clone(), password))
}
(None, _, Some(credentials))
=> credentials,
=> Some(credentials),
(None, _, None) => {
info!("No username provided and no stored credentials, starting discovery ...");
discovery_login(device_name, device_id).unwrap()
}
(None, _, None) => None,
}
}

View file

@ -5,6 +5,8 @@ macro_rules! component {
impl $name {
#[allow(dead_code)]
pub fn new(session: $crate::session::SessionWeak) -> $name {
debug!(target:"librespot::component", "new {}", stringify!($name));
$name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
$($key : $value,)*
}))))
@ -25,6 +27,12 @@ macro_rules! component {
struct $inner {
$($key : $ty,)*
}
impl Drop for $inner {
fn drop(&mut self) {
debug!(target:"librespot::component", "drop {}", stringify!($name));
}
}
}
}

View file

@ -1,23 +1,25 @@
#[macro_use] extern crate log;
extern crate ctrlc;
extern crate env_logger;
extern crate futures;
extern crate getopts;
extern crate librespot;
extern crate tokio_core;
extern crate tokio_signal;
use env_logger::LogBuilder;
use futures::Future;
use std::cell::{RefCell, Cell};
use futures::{Future, Async, Poll, Stream};
use std::env;
use std::io::{stderr, Write};
use std::io::{self, stderr, Write};
use std::path::PathBuf;
use std::process::exit;
use std::str::FromStr;
use tokio_core::reactor::Core;
use tokio_core::reactor::{Handle, Core};
use tokio_core::io::IoStream;
use std::mem;
use librespot::spirc::Spirc;
use librespot::spirc::{Spirc, SpircTask};
use librespot::authentication::{get_credentials, Credentials};
use librespot::authentication::discovery::{discovery, DiscoveryStream};
use librespot::audio_backend::{self, Sink, BACKENDS};
use librespot::cache::Cache;
use librespot::player::Player;
@ -33,7 +35,6 @@ fn usage(program: &str, opts: &getopts::Options) -> String {
fn setup_logging(verbose: bool) {
let mut builder = LogBuilder::new();
match env::var("RUST_LOG") {
Ok(config) => {
builder.parse(&config);
@ -65,13 +66,17 @@ fn list_backends() {
}
}
#[derive(Clone)]
struct Setup {
backend: fn(Option<String>) -> Box<Sink>,
mixer: Box<Mixer + Send>,
device: Option<String>,
mixer: fn() -> Box<Mixer>,
cache: Option<Cache>,
config: Config,
credentials: Credentials,
device: Option<String>,
credentials: Option<Credentials>,
enable_discovery: bool,
}
fn setup(args: &[String]) -> Setup {
@ -84,6 +89,7 @@ fn setup(args: &[String]) -> Setup {
.optflag("v", "verbose", "Enable verbose output")
.optopt("u", "username", "Username to sign in with", "USERNAME")
.optopt("p", "password", "Password", "PASSWORD")
.optflag("", "disable-discovery", "Disable discovery mode")
.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE")
.optopt("", "mixer", "Mixer to use", "MIXER");
@ -130,11 +136,12 @@ fn setup(args: &[String]) -> Setup {
let cached_credentials = cache.as_ref().and_then(Cache::credentials);
let credentials = get_credentials(&name, &device_id,
matches.opt_str("username"),
let credentials = get_credentials(matches.opt_str("username"),
matches.opt_str("password"),
cached_credentials);
let enable_discovery = !matches.opt_present("disable-discovery");
let config = Config {
user_agent: version::version_string(),
name: name,
@ -148,11 +155,143 @@ fn setup(args: &[String]) -> Setup {
Setup {
backend: backend,
mixer: mixer,
cache: cache,
config: config,
credentials: credentials,
device: device,
enable_discovery: enable_discovery,
mixer: mixer,
}
}
struct Main {
cache: Option<Cache>,
config: Config,
backend: fn(Option<String>) -> Box<Sink>,
device: Option<String>,
mixer: fn() -> Box<Mixer>,
handle: Handle,
discovery: Option<DiscoveryStream>,
signal: IoStream<()>,
spirc: Option<Spirc>,
spirc_task: Option<SpircTask>,
connect: Box<Future<Item=Session, Error=io::Error>>,
shutdown: bool,
}
impl Main {
fn new(handle: Handle,
config: Config,
backend: fn(Option<String>) -> Box<Sink>,
device: Option<String>,
mixer: fn() -> Box<Mixer>) -> Main
{
Main {
handle: handle.clone(),
config: config,
backend: backend,
device: device,
mixer: mixer,
cache: None,
connect: Box::new(futures::future::empty()),
discovery: None,
spirc: None,
spirc_task: None,
shutdown: false,
signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
}
}
fn discovery(&mut self) {
let name = self.config.name.clone();
let device_id = self.config.device_id.clone();
self.discovery = Some(discovery(&self.handle, name, device_id).unwrap());
}
fn credentials(&mut self, credentials: Credentials) {
let config = self.config.clone();
let handle = self.handle.clone();
let connection = Session::connect(config, credentials, self.cache.clone(), handle);
self.connect = connection;
self.spirc = None;
let task = mem::replace(&mut self.spirc_task, None);
if let Some(task) = task {
self.handle.spawn(task);
}
}
fn cache(&mut self, cache: Cache) {
self.cache = Some(cache);
}
}
impl Future for Main {
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<(), ()> {
loop {
let mut progress = false;
if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
if let Some(ref spirc) = self.spirc {
spirc.shutdown();
}
self.credentials(creds);
progress = true;
}
if let Async::Ready(session) = self.connect.poll().unwrap() {
self.connect = Box::new(futures::future::empty());
let device = self.device.clone();
let mixer = (self.mixer)();
let audio_filter = mixer.get_audio_filter();
let backend = self.backend;
let player = Player::new(session.clone(), audio_filter, move || {
(backend)(device)
});
let (spirc, spirc_task) = Spirc::new(session, player, mixer);
self.spirc = Some(spirc);
self.spirc_task = Some(spirc_task);
progress = true;
}
if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
if !self.shutdown {
if let Some(ref spirc) = self.spirc {
spirc.shutdown();
}
self.shutdown = true;
} else {
return Ok(Async::Ready(()));
}
progress = true;
}
if let Some(ref mut spirc_task) = self.spirc_task {
if let Async::Ready(()) = spirc_task.poll().unwrap() {
if self.shutdown {
return Ok(Async::Ready(()));
} else {
panic!("Spirc shut down unexpectedly");
}
}
}
if !progress {
return Ok(Async::NotReady);
}
}
}
}
@ -161,35 +300,18 @@ fn main() {
let handle = core.handle();
let args: Vec<String> = std::env::args().collect();
let Setup { backend, config, device, cache, enable_discovery, credentials, mixer } = setup(&args);
let Setup { backend, mixer, cache, config, credentials, device }
= setup(&args);
let connection = Session::connect(config, credentials, cache, handle);
let task = connection.and_then(move |session| {
let audio_filter = mixer.get_audio_filter();
let player = Player::new(session.clone(), audio_filter, move || {
(backend)(device)
});
let (spirc, task) = Spirc::new(session.clone(), player, mixer);
let spirc = RefCell::new(spirc);
let shutting_down = Cell::new(false);
ctrlc::set_handler(move || {
if shutting_down.get() {
warn!("Forced shutdown");
exit(1);
} else {
info!("Shutting down");
spirc.borrow_mut().shutdown();
shutting_down.set(true);
}
});
task.map_err(|()| panic!("spirc error"))
});
let mut task = Main::new(handle, config.clone(), backend, device, mixer);
if enable_discovery {
task.discovery();
}
if let Some(credentials) = credentials {
task.credentials(credentials);
}
if let Some(cache) = cache {
task.cache(cache);
}
core.run(task).unwrap()
}

View file

@ -186,8 +186,12 @@ impl MercuryManager {
if cmd == 0xb5 {
self.lock(|inner| {
if let Some(cb) = inner.subscriptions.get(&response.uri) {
cb.send(response).unwrap();
use std::collections::hash_map::Entry;
if let Entry::Occupied(entry) = inner.subscriptions.entry(response.uri.clone()) {
// TODO: send unsub message
if entry.get().send(response).is_err() {
entry.remove();
}
}
})
} else if let Some(cb) = pending.callback {

View file

@ -1,4 +1,5 @@
pub trait Mixer {
pub trait Mixer : Send {
fn open() -> Self where Self: Sized;
fn start(&self);
fn stop(&self);
fn set_volume(&self, volume: u16);
@ -15,9 +16,13 @@ pub trait AudioFilter {
pub mod softmixer;
use self::softmixer::SoftMixer;
pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<Box<Mixer + Send>> {
fn mk_sink<M: Mixer + 'static>() -> Box<Mixer> {
Box::new(M::open())
}
pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<fn() -> Box<Mixer>> {
match name.as_ref().map(AsRef::as_ref) {
None | Some("softvol") => Some(Box::new(SoftMixer::new())),
None | Some("softvol") => Some(mk_sink::<SoftMixer>),
_ => None,
}
}

View file

@ -4,19 +4,17 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use super::Mixer;
use super::AudioFilter;
#[derive(Clone)]
pub struct SoftMixer {
volume: Arc<AtomicUsize>
}
impl SoftMixer {
pub fn new() -> SoftMixer {
impl Mixer for SoftMixer {
fn open() -> SoftMixer {
SoftMixer {
volume: Arc::new(AtomicUsize::new(0xFFFF))
}
}
}
impl Mixer for SoftMixer {
fn start(&self) {
}
fn stop(&self) {
@ -45,4 +43,4 @@ impl AudioFilter for SoftVolumeApplier {
}
}
}
}
}

View file

@ -44,6 +44,8 @@ impl Player {
let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
thread::spawn(move || {
debug!("new Player[{}]", session.session_id());
let internal = PlayerInternal {
session: session,
commands: cmd_rx,
@ -383,6 +385,12 @@ impl PlayerInternal {
}
}
impl Drop for PlayerInternal {
fn drop(&mut self) {
debug!("drop Player[{}]", self.session.session_id());
}
}
#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
decoder.time_seek(ms as f64 / 1000f64)

View file

@ -1,14 +1,14 @@
use crypto::digest::Digest;
use crypto::sha1::Sha1;
use futures::Future;
use futures::sync::mpsc;
use futures::{Stream, BoxFuture, IntoFuture};
use futures::{Future, Stream, BoxFuture, IntoFuture, Poll, Async};
use std::io;
use std::result::Result;
use std::str::FromStr;
use std::sync::{RwLock, Arc, Weak};
use tokio_core::io::EasyBuf;
use tokio_core::reactor::{Handle, Remote};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use apresolve::apresolve_or_fallback;
use authentication::Credentials;
@ -69,14 +69,15 @@ pub struct SessionInternal {
cache: Option<Arc<Cache>>,
handle: Remote,
session_id: usize,
}
static SESSION_COUNTER : AtomicUsize = ATOMIC_USIZE_INIT;
#[derive(Clone)]
pub struct Session(pub Arc<SessionInternal>);
#[derive(Clone)]
pub struct SessionWeak(pub Weak<SessionInternal>);
pub fn device_id(name: &str) -> String {
let mut h = Sha1::new();
h.input_str(name);
@ -102,7 +103,7 @@ impl Session {
});
let result = authentication.map(move |(transport, reusable_credentials)| {
info!("Authenticated !");
info!("Authenticated as \"{}\" !", reusable_credentials.username);
if let Some(ref cache) = cache {
cache.save_credentials(&reusable_credentials);
}
@ -126,10 +127,9 @@ impl Session {
let (sink, stream) = transport.split();
let (sender_tx, sender_rx) = mpsc::unbounded();
let session_id = SESSION_COUNTER.fetch_add(1, Ordering::Relaxed);
let sender_task = sender_rx
.map_err(|e| -> io::Error { panic!(e) })
.forward(sink).map(|_| ());
debug!("new Session[{}]", session_id);
let session = Session(Arc::new(SessionInternal {
config: config,
@ -149,15 +149,14 @@ impl Session {
metadata: Lazy::new(),
handle: handle.remote().clone(),
session_id: session_id,
}));
let receiver_task = {
let session = session.clone();
stream.for_each(move |(cmd, data)| {
session.dispatch(cmd, data);
Ok(())
})
};
let sender_task = sender_rx
.map_err(|e| -> io::Error { panic!(e) })
.forward(sink).map(|_| ());
let receiver_task = DispatchTask(stream, session.weak());
let task = (receiver_task, sender_task).into_future()
.map(|((), ())| ()).boxed();
@ -193,10 +192,18 @@ impl Session {
self.0.handle.spawn(f)
}
fn debug_info(&self) {
debug!("Session[{}] strong={} weak={}",
self.0.session_id, Arc::strong_count(&self.0), Arc::weak_count(&self.0));
}
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
fn dispatch(&self, cmd: u8, data: EasyBuf) {
match cmd {
0x4 => self.send_packet(0x49, data.as_ref().to_owned()),
0x4 => {
self.debug_info();
self.send_packet(0x49, data.as_ref().to_owned());
},
0x4a => (),
0x1b => {
let country = String::from_utf8(data.as_ref().to_owned()).unwrap();
@ -237,10 +244,59 @@ impl Session {
pub fn weak(&self) -> SessionWeak {
SessionWeak(Arc::downgrade(&self.0))
}
}
impl SessionWeak {
pub fn upgrade(&self) -> Session {
Session(self.0.upgrade().expect("Session died"))
pub fn session_id(&self) -> usize {
self.0.session_id
}
}
#[derive(Clone)]
pub struct SessionWeak(pub Weak<SessionInternal>);
impl SessionWeak {
pub fn try_upgrade(&self) -> Option<Session> {
self.0.upgrade().map(Session)
}
pub fn upgrade(&self) -> Session {
self.try_upgrade().expect("Session died")
}
}
impl Drop for SessionInternal {
fn drop(&mut self) {
debug!("drop Session[{}]", self.session_id);
}
}
struct DispatchTask<S>(S, SessionWeak)
where S: Stream<Item = (u8, EasyBuf)>;
impl <S> Future for DispatchTask<S>
where S: Stream<Item = (u8, EasyBuf)>
{
type Item = ();
type Error = S::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let session = match self.1.try_upgrade() {
Some(session) => session,
None => {
return Ok(Async::Ready(()))
},
};
loop {
let (cmd, data) = try_ready!(self.0.poll()).expect("connection closed");
session.dispatch(cmd, data);
}
}
}
impl <S> Drop for DispatchTask<S>
where S: Stream<Item = (u8, EasyBuf)>
{
fn drop(&mut self) {
debug!("drop Dispatch");
}
}

View file

@ -17,7 +17,7 @@ use protocol::spirc::{PlayStatus, State, MessageType, Frame, DeviceState};
pub struct SpircTask {
player: Player,
mixer: Box<Mixer + Send>,
mixer: Box<Mixer>,
sequence: SeqGenerator<u32>,
@ -31,6 +31,7 @@ pub struct SpircTask {
end_of_track: BoxFuture<(), oneshot::Canceled>,
shutdown: bool,
session: Session,
}
pub enum SpircCommand {
@ -110,9 +111,11 @@ fn initial_device_state(name: String, volume: u16) -> DeviceState {
}
impl Spirc {
pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>)
pub fn new(session: Session, player: Player, mixer: Box<Mixer>)
-> (Spirc, SpircTask)
{
debug!("new Spirc[{}]", session.session_id());
let ident = session.device_id().to_owned();
let name = session.config().name.clone();
@ -152,6 +155,7 @@ impl Spirc {
end_of_track: future::empty().boxed(),
shutdown: false,
session: session.clone(),
};
let spirc = Spirc {
@ -431,6 +435,12 @@ impl SpircTask {
}
}
impl Drop for SpircTask {
fn drop(&mut self) {
debug!("drop Spirc[{}]", self.session.session_id());
}
}
struct CommandSender<'a> {
spirc: &'a mut SpircTask,
frame: protocol::spirc::Frame,