Browse Source

Rewrite connection layer to use tokio

Paul Lietar 8 years ago
parent
commit
9d5e2e9fed
14 changed files with 642 additions and 345 deletions
  1. 149 105
      Cargo.lock
  2. 4 0
      Cargo.toml
  3. 1 1
      src/album_cover.rs
  4. 1 1
      src/audio_file2.rs
  5. 1 1
      src/audio_key.rs
  6. 0 98
      src/connection.rs
  7. 85 0
      src/connection/adaptor.rs
  8. 94 0
      src/connection/codec.rs
  9. 193 0
      src/connection/handshake.rs
  10. 74 0
      src/connection/mod.rs
  11. 1 0
      src/lib.in.rs
  12. 4 1
      src/lib.rs
  13. 1 1
      src/mercury.rs
  14. 34 137
      src/session.rs

+ 149 - 105
Cargo.lock

@@ -8,6 +8,7 @@ dependencies = [
  "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)",
  "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)",
  "json_macros 0.3.1 (git+https://github.com/plietar/json_macros)",
@@ -20,18 +21,20 @@ dependencies = [
  "mdns 0.2.0 (git+https://github.com/plietar/rust-mdns)",
  "num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "portaudio 0.2.0 (git+https://github.com/mvdnes/portaudio-rs)",
- "protobuf 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "protobuf 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "protobuf_macros 0.6.0 (git+https://github.com/plietar/rust-protobuf-macros)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.21 (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_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)",
  "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -51,7 +54,7 @@ name = "alsa"
 version = "0.0.1"
 source = "git+https://github.com/plietar/rust-alsa#8c63543fa0ccd971cf15f5675293d19febd6f79e"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -72,10 +75,10 @@ dependencies = [
 
 [[package]]
 name = "aster"
-version = "0.36.0"
+version = "0.39.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -126,8 +129,8 @@ name = "cookie"
 version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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]]
@@ -136,7 +139,7 @@ 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.18 (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)",
 ]
 
@@ -171,12 +174,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "syncbox 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "futures"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -215,14 +218,14 @@ dependencies = [
  "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.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.2.1 (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.35 (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)",
  "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -278,7 +281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.18"
+version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -287,7 +290,7 @@ version = "0.2.1"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -295,14 +298,14 @@ name = "libpulse-sys"
 version = "0.0.0"
 source = "git+https://github.com/astro/libpulse-sys#3e167c0d75dae1ce3946eec7526f6afd92adda0f"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "librespot-protocol"
 version = "0.1.0"
 dependencies = [
- "protobuf 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "protobuf 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -316,7 +319,7 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "liblmdb-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -334,18 +337,18 @@ 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#2078310b61794994d727ed20ff315709937059a0"
+source = "git+https://github.com/plietar/rust-mdns#8ea956858dcd900b02d795f35f884034d15cf8e8"
 dependencies = [
- "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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)",
- "futures 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "multimap 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
- "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-core 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)",
 ]
 
 [[package]]
@@ -353,7 +356,7 @@ name = "memchr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -371,7 +374,7 @@ 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)",
  "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -393,7 +396,7 @@ dependencies = [
 
 [[package]]
 name = "multimap"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -403,20 +406,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.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.18 (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)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "nix"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "nix"
 version = "0.7.0"
@@ -424,7 +418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -498,10 +492,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num_cpus"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -510,7 +504,7 @@ version = "0.0.9"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -525,7 +519,7 @@ version = "0.2.0"
 source = "git+https://github.com/mvdnes/portaudio-rs#2e1630843551a229bfe6cae6291fd157349bad60"
 dependencies = [
  "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "portaudio_sys 0.1.1 (git+https://github.com/mvdnes/portaudio-rs)",
 ]
 
@@ -534,23 +528,23 @@ name = "portaudio_sys"
 version = "0.1.1"
 source = "git+https://github.com/mvdnes/portaudio-rs#2e1630843551a229bfe6cae6291fd157349bad60"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "protobuf"
-version = "1.0.24"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "protobuf_macros"
 version = "0.6.0"
-source = "git+https://github.com/plietar/rust-protobuf-macros#4f34371e4fdd5dca7db86e91ba8b902ae55c739c"
+source = "git+https://github.com/plietar/rust-protobuf-macros#09c079a96bd4b6b429abc74334215cfcb67e45dc"
 dependencies = [
- "aster 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntex 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aster 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -611,9 +605,14 @@ name = "rand"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "regex"
 version = "0.1.80"
@@ -637,7 +636,7 @@ version = "0.3.0"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -648,10 +647,10 @@ version = "0.2.36"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -679,7 +678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "0.8.21"
+version = "0.8.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -713,7 +712,7 @@ dependencies = [
  "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.1.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.8.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -730,7 +729,7 @@ version = "0.1.1"
 source = "git+https://github.com/plietar/rust-shannon#613aa1e752b3247a30d2c866bb45f0170e9df8d6"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "shannon-sys 0.1.0 (git+https://github.com/plietar/rust-shannon)",
 ]
 
@@ -740,7 +739,7 @@ version = "0.1.0"
 source = "git+https://github.com/plietar/rust-shannon#613aa1e752b3247a30d2c866bb45f0170e9df8d6"
 dependencies = [
  "gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -748,6 +747,11 @@ name = "slab"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "smallvec"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "solicit"
 version = "0.4.4"
@@ -763,7 +767,7 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -786,11 +790,11 @@ dependencies = [
 
 [[package]]
 name = "syntex"
-version = "0.52.0"
+version = "0.55.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -798,7 +802,7 @@ name = "syntex_errors"
 version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -811,7 +815,7 @@ name = "syntex_errors"
 version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -821,15 +825,15 @@ dependencies = [
 
 [[package]]
 name = "syntex_errors"
-version = "0.52.0"
+version = "0.55.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -850,7 +854,7 @@ dependencies = [
 
 [[package]]
 name = "syntex_pos"
-version = "0.52.0"
+version = "0.55.0"
 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)",
@@ -862,7 +866,7 @@ version = "0.44.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)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -877,7 +881,7 @@ version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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.50.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -888,26 +892,31 @@ dependencies = [
 
 [[package]]
 name = "syntex_syntax"
-version = "0.52.0"
+version = "0.55.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (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.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (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 = "take"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "tempfile"
 version = "2.1.4"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -927,7 +936,7 @@ name = "termios"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -936,7 +945,7 @@ version = "2.0.0"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -949,26 +958,51 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.1.35"
+version = "0.1.36"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tokio-core"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "futures 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)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "tokio-proto"
+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)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-service"
+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 = "traitobject"
 version = "0.0.1"
@@ -979,7 +1013,7 @@ name = "tremor"
 version = "0.1.0"
 source = "git+https://github.com/plietar/rust-tremor#5958cc302e78f535dad90e9665da981ddff4000a"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)",
 ]
 
@@ -989,7 +1023,7 @@ version = "0.1.0"
 source = "git+https://github.com/plietar/rust-tremor#5958cc302e78f535dad90e9665da981ddff4000a"
 dependencies = [
  "gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1025,6 +1059,11 @@ name = "unicode-xid"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "url"
 version = "0.5.10"
@@ -1039,7 +1078,7 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "1.2.4"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1065,7 +1104,7 @@ version = "0.1.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)",
- "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1078,7 +1117,7 @@ name = "vorbis"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis-encoder 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1092,7 +1131,7 @@ version = "0.1.4"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis-sys 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1104,7 +1143,7 @@ version = "0.0.8"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1115,7 +1154,7 @@ version = "0.0.8"
 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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis-sys 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1145,7 +1184,7 @@ dependencies = [
 "checksum alsa 0.0.1 (git+https://github.com/plietar/rust-alsa)" = "<none>"
 "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.36.0 (registry+https://github.com/rust-lang/crates.io-index)" = "365684a2d8153bde2ca60826e54c8d3df76e06578ed868f8baaf91ae811af07b"
+"checksum aster 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "022822e5621c840afed9d4fbdf52104bfc2ff6f0f64016a6bbe4e10d7ec70535"
 "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"
@@ -1160,7 +1199,7 @@ dependencies = [
 "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 eventual 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b9bda6d089b434ca50f3d6feb5fca421309b8bac97b8be9af51cff879fa3f54b"
-"checksum futures 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "177a82a61dd7e528022ce97f24e54b499dd2fee4d4646a0f283c5fb500dbfe20"
+"checksum futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3e0b237aed5d8b61bc7d6ee1b8ebd719d0a934a38d363c5e56daf34bb634d9b2"
 "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"
@@ -1173,7 +1212,7 @@ dependencies = [
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
-"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
+"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
 "checksum liblmdb-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b56d07dcf983f9b6679f768df73c72671d0087bd66329baabb63325f4f592677"
 "checksum libpulse-sys 0.0.0 (git+https://github.com/astro/libpulse-sys)" = "<none>"
 "checksum linear-map 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f947d2a0ca958037e42a430bc7ea4369f97b60a2002bd927b84404509cc64cf"
@@ -1185,9 +1224,8 @@ dependencies = [
 "checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
 "checksum mio 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5b493dc9fd96bd2077f2117f178172b0765db4dfda3ea4d8000401e6d65d3e80"
 "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1"
-"checksum multimap 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e85cb6b79f81830421066428f1f8f47032d77843dc569040a7d056b80f95d5d4"
+"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"
-"checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79"
 "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b"
 "checksum num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "bde7c03b09e7c6a301ee81f6ddf66d7a28ec305699e3d3b056d2fc56470e3120"
 "checksum num-bigint 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "88b14378471f7c2adc5262f05b4701ef53e8da376453a8d8fee48e51db745e49"
@@ -1196,12 +1234,12 @@ dependencies = [
 "checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c"
 "checksum num-rational 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "54ff603b8334a72fbb27fe66948aac0abaaa40231b3cecd189e76162f6f38aaf"
 "checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
-"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3"
+"checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
 "checksum ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a95b8c172e17df1a41bf8d666301d3b2c4efeb90d9d0415e2a4dc0668b35fdb2"
 "checksum pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8cee804ecc7eaf201a4a207241472cc870e825206f6c031e3ee2a72fa425f2fa"
 "checksum portaudio 0.2.0 (git+https://github.com/mvdnes/portaudio-rs)" = "<none>"
 "checksum portaudio_sys 0.1.1 (git+https://github.com/mvdnes/portaudio-rs)" = "<none>"
-"checksum protobuf 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec4c2fe04370298218a09ab53a534febf54c160c5554e4de987b6d73c916d5d"
+"checksum protobuf 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229112a9213bf62a59f0702871a6e4872fe928161fc7a08f17cdd6c8c7988bf7"
 "checksum protobuf_macros 0.6.0 (git+https://github.com/plietar/rust-protobuf-macros)" = "<none>"
 "checksum quasi 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94a532453b931a4483a5b2e40f0fe04aee35b6bc2c0eeec876f1bd2358a134d3"
 "checksum quasi 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab7992920bf5bc5f1ed6fdc49090bf665cd00b3aa4b78c16ac3465286257db1"
@@ -1210,6 +1248,7 @@ dependencies = [
 "checksum quasi_macros 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc2b36285ea5e54e4e267f83896267ff8c5aba4f66b2e7d186ed6d968f3715f"
 "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
 "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.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 rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6e42be826e215f30ff830904f8f4a0933c6e2ae890e1af8b408f5bae60081e"
@@ -1218,7 +1257,7 @@ 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.8.21 (registry+https://github.com/rust-lang/crates.io-index)" = "7b7c6bf11cf766473ea1d53eb4e3bc4e80f31f50082fc24077cf06f600279a66"
+"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"
@@ -1226,27 +1265,31 @@ dependencies = [
 "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 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"
-"checksum syntex 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1b66e8c1e25a6c4007a38a225411b776a06e8c3030d6fc4d200a038bf02065"
+"checksum syntex 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b186e277908427269816c542c912b45253ed11808a09780bd224679770ce351"
 "checksum syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0d95d2141ae79f312a01c6934d9984f9d7f5cfaf0c74aae5fbbc234a6dcb77a"
 "checksum syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1"
-"checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b"
+"checksum syntex_errors 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c050df675f9be2acbc2082c1d9cf1d3014837ad5f5302b7d4697e4ad031984"
 "checksum syntex_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2cbf0598c5970f2dca122a4e6f7e93bf42f2d0b2dd88c3ea112413152864df"
 "checksum syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db"
-"checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac"
+"checksum syntex_pos 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60b7ba34c8017f1972f23f926aae82d66901978bd724ca1372671f67329ee0ee"
 "checksum syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5a89ee386d492cdd3855becec489c25797bb91bcbb3c2478c41969b24cb318a2"
 "checksum syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5"
-"checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
+"checksum syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58b199e4f76605987ba81d9c949f2274e236388fa1b476fd00f4b72bb7bd9dfc"
+"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
 "checksum tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9270837a93bad1b1dac18fe67e786b3c960513af86231f6f4f57fddd594ff0c8"
 "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
 "checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
-"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
-"checksum tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "52416b3e937abac22a543a7f1c66bd37feb60137ff1ab42390fa02df85347e58"
+"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
+"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)" = "<none>"
 "checksum tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
@@ -1255,8 +1298,9 @@ dependencies = [
 "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.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f024e241a55f5c88401595adc1d4af0c9649e91da82d0e190fe55950231ae575"
+"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"

+ 4 - 0
Cargo.toml

@@ -57,6 +57,10 @@ protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
 
 mdns            = { git = "https://github.com/plietar/rust-mdns" }
 
+futures = "0.1.8"
+tokio-proto = "0.1.0"
+tokio-core = "0.1.2"
+
 [build-dependencies]
 vergen          = "0.1.0"
 protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }

+ 1 - 1
src/album_cover.rs

@@ -18,7 +18,7 @@ impl stream::Handler for AlbumCover {
         req.write_u16::<BigEndian>(channel_id).unwrap();
         req.write_u16::<BigEndian>(0).unwrap();
         req.write(&self.file_id.0).unwrap();
-        session.send_packet(0x19, &req).unwrap();
+        session.send_packet(0x19, req);
 
         stream::Response::Continue(self)
     }

+ 1 - 1
src/audio_file2.rs

@@ -55,7 +55,7 @@ impl <H: Handler> stream::Handler for AudioFile<H> {
         data.write_u32::<BigEndian>(self.offset as u32 / 4).unwrap();
         data.write_u32::<BigEndian>((self.offset + CHUNK_SIZE) as u32 / 4).unwrap();
 
-        session.send_packet(0x8, &data).unwrap();
+        session.send_packet(0x8, data);
 
         stream::Response::Continue(self)
     }

+ 1 - 1
src/audio_key.rs

@@ -38,7 +38,7 @@ impl AudioKeyManager {
         data.write_u32::<BigEndian>(seq).unwrap();
         data.write_u16::<BigEndian>(0x0000).unwrap();
 
-        session.send_packet(0xc, &data).unwrap();
+        session.send_packet(0xc, data);
 
         seq
     }

+ 0 - 98
src/connection.rs

@@ -1,98 +0,0 @@
-use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
-use shannon::ShannonStream;
-use std::convert;
-use std::io;
-use std::io::{Read, Write};
-use std::net::TcpStream;
-use std::result;
-
-#[derive(Debug)]
-pub enum Error {
-    IoError(io::Error),
-    Other,
-}
-
-pub type Result<T> = result::Result<T, Error>;
-
-impl convert::From<io::Error> for Error {
-    fn from(err: io::Error) -> Error {
-        Error::IoError(err)
-    }
-}
-
-pub struct PlainConnection {
-    stream: TcpStream,
-}
-
-#[derive(Clone)]
-pub struct CipherConnection {
-    stream: ShannonStream<TcpStream>,
-}
-
-impl PlainConnection {
-    pub fn connect(ap: &str) -> Result<PlainConnection> {
-        Ok(PlainConnection {
-            stream: try!(TcpStream::connect(ap)),
-        })
-    }
-
-    pub fn send_packet(&mut self, data: &[u8]) -> Result<Vec<u8>> {
-        self.send_packet_prefix(&[], data)
-    }
-
-    pub fn send_packet_prefix(&mut self, prefix: &[u8], data: &[u8]) -> Result<Vec<u8>> {
-        let size = prefix.len() + 4 + data.len();
-        let mut buf = Vec::with_capacity(size);
-
-        try!(buf.write(prefix));
-        try!(buf.write_u32::<BigEndian>(size as u32));
-        try!(buf.write(data));
-        try!(self.stream.write(&buf));
-        try!(self.stream.flush());
-
-        Ok(buf)
-    }
-
-    pub fn recv_packet(&mut self) -> Result<Vec<u8>> {
-        let size = try!(self.stream.read_u32::<BigEndian>()) as usize;
-        let mut buffer = vec![0u8; size];
-
-        BigEndian::write_u32(&mut buffer, size as u32);
-        try!(self.stream.read_exact(&mut buffer[4..]));
-
-        Ok(buffer)
-    }
-
-    pub fn into_stream(self) -> TcpStream {
-        self.stream
-    }
-}
-
-impl CipherConnection {
-    pub fn new(stream: TcpStream, recv_key: &[u8], send_key: &[u8]) -> CipherConnection {
-        CipherConnection { stream: ShannonStream::new(stream, recv_key, send_key) }
-    }
-
-    pub fn send_packet(&mut self, cmd: u8, data: &[u8]) -> Result<()> {
-        try!(self.stream.write_u8(cmd));
-        try!(self.stream.write_u16::<BigEndian>(data.len() as u16));
-        try!(self.stream.write(data));
-
-        try!(self.stream.finish_send());
-        try!(self.stream.flush());
-
-        Ok(())
-    }
-
-    pub fn recv_packet(&mut self) -> Result<(u8, Vec<u8>)> {
-        let cmd = try!(self.stream.read_u8());
-        let size = try!(self.stream.read_u16::<BigEndian>()) as usize;
-
-        let mut data = vec![0; size];
-        try!(self.stream.read_exact(&mut data));
-
-        try!(self.stream.finish_recv());
-
-        Ok((cmd, data))
-    }
-}

+ 85 - 0
src/connection/adaptor.rs

@@ -0,0 +1,85 @@
+use futures::future::ok;
+use futures::sync::mpsc;
+use futures::{Future, Sink, Stream, BoxFuture, IntoFuture};
+use std::thread;
+use tokio_core::reactor::Core;
+use tokio_core::reactor::Handle;
+
+pub struct SinkAdaptor<T>(Option<mpsc::Sender<T>>);
+pub struct StreamAdaptor<T, E>(Option<mpsc::Receiver<Result<T, E>>>);
+
+impl <T> SinkAdaptor<T> {
+    pub fn send(&mut self, item: T) {
+        let sender = self.0.take().unwrap();
+        let sending = sender.send(item);
+        self.0 = Some(sending.wait().unwrap());
+    }
+}
+
+impl <T, E> StreamAdaptor<T, E> {
+    pub fn recv(&mut self) -> Result<T, E> {
+        let receiver = self.0.take().unwrap();
+        let receiving = receiver.into_future();
+
+        let (packet, receiver) = receiving.wait().map_err(|(e, _)| e).unwrap();
+
+        self.0 = Some(receiver);
+
+        packet.unwrap()
+    }
+}
+
+fn adapt_sink<S>(sink: S, rx: mpsc::Receiver<S::SinkItem>) -> BoxFuture<(), ()>
+    where S: Sink + Send + 'static,
+          S::SinkItem: Send,
+          S::SinkError: Send,
+{
+    rx.map_err(|_| -> S::SinkError { panic!("") })
+      .forward(sink)
+      .map(|_| ()).map_err(|_| ())
+      .boxed()
+}
+
+fn adapt_stream<S>(stream: S, tx: mpsc::Sender<Result<S::Item, S::Error>>) -> BoxFuture<(), ()>
+    where S: Stream + Send + 'static,
+          S::Item: Send,
+          S::Error: Send,
+{
+    stream.then(ok::<_, mpsc::SendError<_>>)
+        .forward(tx)
+        .map(|_| ()).map_err(|_| ())
+        .boxed()
+}
+
+pub fn adapt<F, U, S>(f: F) -> (SinkAdaptor<S::SinkItem>, StreamAdaptor<S::Item, S::Error>)
+    where F: FnOnce(&Handle) -> U + Send + 'static,
+          U: IntoFuture<Item=S>,
+          S: Sink + Stream + Send + 'static,
+          S::Item: Send + 'static,
+          S::Error: Send + 'static,
+          S::SinkItem: Send + 'static,
+          S::SinkError: Send + 'static,
+{
+
+    let (receiver_tx, receiver_rx) = mpsc::channel(0);
+    let (sender_tx, sender_rx) = mpsc::channel(0);
+
+
+    thread::spawn(move || {
+        let mut core = Core::new().unwrap();
+        let handle = core.handle();
+        let task =
+            f(&handle).into_future()
+            .map(|connection| connection.split())
+            .map_err(|_| ())
+            .and_then(|(sink, stream)| {
+                (adapt_sink(sink, sender_rx),
+                 adapt_stream(stream, receiver_tx))
+            });
+
+        core.run(task).unwrap();
+    });
+
+    (SinkAdaptor(Some(sender_tx)),
+     StreamAdaptor(Some(receiver_rx)))
+}

+ 94 - 0
src/connection/codec.rs

@@ -0,0 +1,94 @@
+use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
+use shannon::Shannon;
+use std::io;
+use tokio_core::io::{Codec, EasyBuf};
+
+const HEADER_SIZE: usize = 3;
+const MAC_SIZE: usize = 4;
+
+#[derive(Debug)]
+enum DecodeState {
+    Header,
+    Payload(u8, usize),
+}
+
+pub struct APCodec {
+    encode_nonce: u32,
+    encode_cipher: Shannon,
+
+    decode_nonce: u32,
+    decode_cipher: Shannon,
+    decode_state: DecodeState,
+}
+
+impl APCodec {
+    pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
+        APCodec {
+            encode_nonce: 0,
+            encode_cipher: Shannon::new(send_key),
+
+            decode_nonce: 0,
+            decode_cipher: Shannon::new(recv_key),
+            decode_state: DecodeState::Header,
+        }
+    }
+}
+
+impl Codec for APCodec {
+    type Out = (u8, Vec<u8>);
+    type In = (u8, EasyBuf);
+
+    fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut Vec<u8>) -> io::Result<()> {
+        let (cmd, payload) = item;
+        let offset = buf.len();
+
+        buf.write_u8(cmd).unwrap();
+        buf.write_u16::<BigEndian>(payload.len() as u16).unwrap();
+        buf.extend_from_slice(&payload);
+
+        self.encode_cipher.nonce_u32(self.encode_nonce);
+        self.encode_nonce += 1;
+
+        self.encode_cipher.encrypt(&mut buf[offset..]);
+
+        let mac = self.encode_cipher.finish(MAC_SIZE as u32);
+        buf.extend_from_slice(&mac);
+
+        Ok(())
+    }
+
+    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<(u8, EasyBuf)>> {
+        if let DecodeState::Header = self.decode_state {
+            if buf.len() >= HEADER_SIZE {
+                let mut header = [0u8; HEADER_SIZE];
+                header.copy_from_slice(buf.drain_to(HEADER_SIZE).as_slice());
+
+                self.decode_cipher.nonce_u32(self.decode_nonce);
+                self.decode_nonce += 1;
+
+                self.decode_cipher.decrypt(&mut header);
+
+                let cmd = header[0];
+                let size = BigEndian::read_u16(&header[1..]) as usize;
+                self.decode_state = DecodeState::Payload(cmd, size);
+            }
+        }
+
+        if let DecodeState::Payload(cmd, size) = self.decode_state {
+            if buf.len() >= size + MAC_SIZE {
+                self.decode_state = DecodeState::Header;
+
+                let mut payload = buf.drain_to(size + MAC_SIZE);
+
+                self.decode_cipher.decrypt(&mut payload.get_mut()[..size]);
+                let mac = payload.split_off(size);
+                self.decode_cipher.check_mac(mac.as_slice())?;
+
+                return Ok(Some((cmd, payload)));
+            }
+        }
+
+
+        Ok(None)
+    }
+}

+ 193 - 0
src/connection/handshake.rs

@@ -0,0 +1,193 @@
+use crypto::sha1::Sha1;
+use crypto::hmac::Hmac;
+use crypto::mac::Mac;use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
+use protobuf::{self, Message, MessageStatic};
+use rand::thread_rng;
+use std::io::{self, Read, Write};
+use std::marker::PhantomData;
+use tokio_core::io::{Io, Framed, write_all, WriteAll, read_exact, ReadExact, Window};
+use futures::{Poll, Async, Future};
+
+use diffie_hellman::DHLocalKeys;
+use protocol;
+use protocol::keyexchange::{ClientHello, APResponseMessage, ClientResponsePlaintext};
+use util;
+use super::codec::APCodec;
+
+pub struct Handshake<T> {
+    keys: DHLocalKeys,
+    state: HandshakeState<T>,
+}
+
+enum HandshakeState<T> {
+    ClientHello(WriteAll<T, Vec<u8>>),
+    APResponse(RecvPacket<T, APResponseMessage>),
+    ClientResponse(Option<APCodec>, WriteAll<T, Vec<u8>>),
+}
+
+pub fn handshake<T: Io>(connection: T) -> Handshake<T> {
+    let local_keys = DHLocalKeys::random(&mut thread_rng());
+    let client_hello = client_hello(connection, local_keys.public_key());
+
+    Handshake {
+        keys: local_keys,
+        state: HandshakeState::ClientHello(client_hello),
+    }
+}
+
+impl <T: Io> Future for Handshake<T> {
+    type Item = Framed<T, APCodec>;
+    type Error = io::Error;
+
+    fn poll(&mut self) -> Poll<Self::Item, io::Error> {
+        use self::HandshakeState::*;
+        loop {
+            self.state = match self.state {
+                ClientHello(ref mut write) => {
+                    let (connection, accumulator) = try_ready!(write.poll());
+                    
+                    let read = recv_packet(connection, accumulator);
+                    APResponse(read)
+                }
+
+                APResponse(ref mut read) => {
+                    let (connection, message, accumulator) = try_ready!(read.poll());
+                    let remote_key = message.get_challenge()
+                        .get_login_crypto_challenge()
+                        .get_diffie_hellman()
+                        .get_gs()
+                        .to_owned();
+
+                    let shared_secret = self.keys.shared_secret(&remote_key);
+                    let (challenge, send_key, recv_key) = compute_keys(&shared_secret,
+                                                                       &accumulator);
+                    let codec = APCodec::new(&send_key, &recv_key);
+
+                    let write = client_response(connection, challenge);
+                    ClientResponse(Some(codec), write)
+                }
+
+                ClientResponse(ref mut codec, ref mut write) => {
+                    let (connection, _) = try_ready!(write.poll());
+                    let codec = codec.take().unwrap();
+                    let framed = connection.framed(codec);
+                    return Ok(Async::Ready(framed));
+                }
+            }
+        }
+    }
+}
+
+fn client_hello<T: Write>(connection: T, gc: Vec<u8>) -> WriteAll<T, Vec<u8>> {
+    let packet = protobuf_init!(ClientHello::new(), {
+        build_info => {
+            product: protocol::keyexchange::Product::PRODUCT_PARTNER,
+            platform: protocol::keyexchange::Platform::PLATFORM_LINUX_X86,
+            version: 0x10800000000,
+        },
+        cryptosuites_supported => [
+            protocol::keyexchange::Cryptosuite::CRYPTO_SUITE_SHANNON,
+        ],
+        login_crypto_hello.diffie_hellman => {
+            gc: gc,
+            server_keys_known: 1,
+        },
+        client_nonce: util::rand_vec(&mut thread_rng(), 0x10),
+        padding: vec![0x1e],
+    });
+
+    let mut buffer = vec![0, 4];
+    let size = 2 + 4 + packet.compute_size();
+    buffer.write_u32::<BigEndian>(size).unwrap();
+    packet.write_to_vec(&mut buffer).unwrap();
+
+    write_all(connection, buffer)
+}
+
+fn client_response<T: Write>(connection: T, challenge: Vec<u8>) -> WriteAll<T, Vec<u8>> {
+    let packet = protobuf_init!(ClientResponsePlaintext::new(), {
+        login_crypto_response.diffie_hellman => {
+            hmac: challenge
+        },
+        pow_response => {},
+        crypto_response => {},
+    });
+
+    let mut buffer = vec![];
+    let size = 4 + packet.compute_size();
+    buffer.write_u32::<BigEndian>(size).unwrap();
+    packet.write_to_vec(&mut buffer).unwrap();
+
+    write_all(connection, buffer)
+}
+
+enum RecvPacket<T, M: MessageStatic> {
+    Header(ReadExact<T, Window<Vec<u8>>>, PhantomData<M>),
+    Body(ReadExact<T, Window<Vec<u8>>>, PhantomData<M>),
+}
+
+fn recv_packet<T, M>(connection: T, acc: Vec<u8>) -> RecvPacket<T, M>
+    where T: Read,
+          M: MessageStatic
+{
+    RecvPacket::Header(read_into_accumulator(connection, 4, acc), PhantomData)
+}
+
+impl <T, M> Future for RecvPacket<T, M>
+    where T: Read,
+          M: MessageStatic
+{
+    type Item = (T, M, Vec<u8>);
+    type Error = io::Error;
+
+    fn poll(&mut self) -> Poll<Self::Item, io::Error> {
+        use self::RecvPacket::*;
+        loop {
+            *self = match *self {
+                Header(ref mut read, _) => {
+                    let (connection, header) = try_ready!(read.poll());
+                    let size = BigEndian::read_u32(header.as_ref()) as usize;
+
+                    let acc = header.into_inner();
+                    let read = read_into_accumulator(connection, size - 4, acc);
+                    RecvPacket::Body(read, PhantomData)
+                }
+
+                Body(ref mut read, _) => {
+                    let (connection, data) = try_ready!(read.poll());
+                    let message = protobuf::parse_from_bytes(data.as_ref()).unwrap();
+
+                    let acc = data.into_inner();
+                    return Ok(Async::Ready((connection, message, acc)));
+                }
+            }
+        }
+    }
+}
+
+fn read_into_accumulator<T: Read>(connection: T, size: usize, mut acc: Vec<u8>) -> ReadExact<T, Window<Vec<u8>>> {
+    let offset = acc.len();
+    acc.resize(offset + size, 0);
+
+    let mut window = Window::new(acc);
+    window.set_start(offset);
+
+    read_exact(connection, window)
+}
+
+fn compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
+    let mut data = Vec::with_capacity(0x64);
+    let mut mac = Hmac::new(Sha1::new(), &shared_secret);
+
+    for i in 1..6 {
+        mac.input(packets);
+        mac.input(&[i]);
+        data.extend_from_slice(&mac.result().code());
+        mac.reset();
+    }
+
+    mac = Hmac::new(Sha1::new(), &data[..0x14]);
+    mac.input(packets);
+
+    (mac.result().code().to_vec(), data[0x14..0x34].to_vec(), data[0x34..0x54].to_vec())
+}

+ 74 - 0
src/connection/mod.rs

@@ -0,0 +1,74 @@
+mod codec;
+mod handshake;
+pub mod adaptor;
+
+pub use self::codec::APCodec;
+pub use self::handshake::handshake;
+
+use futures::{Future, Sink, Stream, BoxFuture};
+use std::io;
+use std::net::ToSocketAddrs;
+use tokio_core::net::TcpStream;
+use tokio_core::reactor::Handle;
+use tokio_core::io::Framed;
+use protobuf::{self, Message};
+
+use authentication::Credentials;
+use version;
+
+pub type Transport = Framed<TcpStream, APCodec>;
+
+pub fn connect<A: ToSocketAddrs>(addr: A, handle: &Handle) -> BoxFuture<Transport, io::Error> {
+    let addr = addr.to_socket_addrs().unwrap().next().unwrap();
+    let socket = TcpStream::connect(&addr, handle);
+    let connection = socket.and_then(|socket| {
+        handshake(socket)
+    });
+
+    connection.boxed()
+}
+
+pub fn authenticate(transport: Transport, credentials: Credentials, device_id: String) -> BoxFuture<(Transport, Credentials), io::Error> {
+    use protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
+
+    let packet = protobuf_init!(ClientResponseEncrypted::new(), {
+        login_credentials => {
+            username: credentials.username,
+            typ: credentials.auth_type,
+            auth_data: credentials.auth_data,
+        },
+        system_info => {
+            cpu_family: CpuFamily::CPU_UNKNOWN,
+            os: Os::OS_UNKNOWN,
+            system_information_string: "librespot".to_owned(),
+            device_id: device_id,
+        },
+        version_string: version::version_string(),
+    });
+
+    let cmd = 0xab;
+    let data = packet.write_to_bytes().unwrap();
+
+    transport.send((cmd, data)).and_then(|transport| {
+        transport.into_future().map_err(|(err, _stream)| err)
+    }).and_then(|(packet, transport)| {
+        match packet {
+            Some((0xac, data)) => {
+                let welcome_data: APWelcome =
+                    protobuf::parse_from_bytes(data.as_ref()).unwrap();
+
+                let reusable_credentials = Credentials {
+                    username: welcome_data.get_canonical_username().to_owned(),
+                    auth_type: welcome_data.get_reusable_auth_credentials_type(),
+                    auth_data: welcome_data.get_reusable_auth_credentials().to_owned(),
+                };
+
+                Ok((transport, reusable_credentials))
+            }
+
+            Some((0xad, _)) => panic!("Authentication failed"),
+            Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),
+            None => panic!("EOF"),
+        }
+    }).boxed()
+}

+ 1 - 0
src/lib.in.rs

@@ -1,5 +1,6 @@
 pub mod apresolve;
 pub mod authentication;
+pub mod connection;
 pub mod mercury;
 pub mod session;
 pub mod spirc;

+ 4 - 1
src/lib.rs

@@ -31,6 +31,10 @@ extern crate shannon;
 extern crate tempfile;
 extern crate url;
 
+#[macro_use] extern crate futures;
+extern crate tokio_core;
+extern crate tokio_proto;
+
 extern crate librespot_protocol as protocol;
 
 #[cfg(not(feature = "with-tremor"))]
@@ -52,7 +56,6 @@ pub mod audio_file2;
 pub mod audio_file;
 pub mod audio_key;
 pub mod cache;
-pub mod connection;
 pub mod diffie_hellman;
 pub mod link;
 pub mod metadata;

+ 1 - 1
src/mercury.rs

@@ -84,7 +84,7 @@ impl MercuryManager {
             _ => 0xb2,
         };
 
-        session.send_packet(cmd, &data).unwrap();
+        session.send_packet(cmd, data);
 
         self.pending.insert(seq.to_vec(),
                             MercuryPending {

+ 34 - 137
src/session.rs

@@ -1,31 +1,27 @@
 use crypto::digest::Digest;
 use crypto::sha1::Sha1;
-use crypto::hmac::Hmac;
-use crypto::mac::Mac;
 use eventual;
 use eventual::Future;
 use eventual::Async;
-use protobuf::{self, Message};
-use rand::thread_rng;
-use std::io::{Read, Write, Cursor};
+use std::io::{self, Read, Cursor};
 use std::result::Result;
 use std::sync::{Mutex, RwLock, Arc, mpsc};
 use std::str::FromStr;
+use futures::Future as Future_;
+use futures::Stream;
+use futures::sync::oneshot;
 
 use album_cover::AlbumCover;
 use apresolve::apresolve;
-use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
 use audio_file::AudioFile;
+use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
 use authentication::Credentials;
 use cache::Cache;
-use connection::{self, PlainConnection, CipherConnection};
-use diffie_hellman::DHLocalKeys;
+use connection::{self, adaptor};
 use mercury::{MercuryManager, MercuryRequest, MercuryResponse};
 use metadata::{MetadataManager, MetadataRef, MetadataTrait};
-use protocol;
 use stream::StreamManager;
-use util::{self, SpotifyId, FileId, ReadSeek};
-use version;
+use util::{SpotifyId, FileId, ReadSeek};
 
 use stream;
 
@@ -70,8 +66,8 @@ pub struct SessionInternal {
     metadata: Mutex<MetadataManager>,
     stream: Mutex<StreamManager>,
     audio_key: Mutex<AudioKeyManager>,
-    rx_connection: Mutex<Option<CipherConnection>>,
-    tx_connection: Mutex<Option<CipherConnection>>,
+    rx_connection: Mutex<Option<adaptor::StreamAdaptor<(u8, Vec<u8>), io::Error>>>,
+    tx_connection: Mutex<Option<adaptor::SinkAdaptor<(u8, Vec<u8>)>>>,
 }
 
 #[derive(Clone)]
@@ -104,143 +100,44 @@ impl Session {
         }))
     }
 
-    fn connect(&self) -> CipherConnection {
-        let local_keys = DHLocalKeys::random(&mut thread_rng());
-
-        let ap = apresolve();
-
-        info!("Connecting to AP {}", ap);
-        let mut connection = PlainConnection::connect(&ap).unwrap();
-
-        let request = protobuf_init!(protocol::keyexchange::ClientHello::new(), {
-            build_info => {
-                product: protocol::keyexchange::Product::PRODUCT_PARTNER,
-                platform: protocol::keyexchange::Platform::PLATFORM_LINUX_X86,
-                version: 0x10800000000,
-            },
-            cryptosuites_supported => [
-                protocol::keyexchange::Cryptosuite::CRYPTO_SUITE_SHANNON,
-            ],
-            login_crypto_hello.diffie_hellman => {
-                gc: local_keys.public_key(),
-                server_keys_known: 1,
-            },
-            client_nonce: util::rand_vec(&mut thread_rng(), 0x10),
-            padding: vec![0x1e],
-        });
+    pub fn login(&self, credentials: Credentials) -> Result<Credentials, ()> {
+        let addr = apresolve();
+        let device_id = self.device_id().to_owned();
 
-        let init_client_packet = connection.send_packet_prefix(&[0, 4],
-                                                               &request.write_to_bytes().unwrap())
-                                           .unwrap();
-        let init_server_packet = connection.recv_packet().unwrap();
-
-        let response: protocol::keyexchange::APResponseMessage =
-            protobuf::parse_from_bytes(&init_server_packet[4..]).unwrap();
-
-        let remote_key = response.get_challenge()
-                                 .get_login_crypto_challenge()
-                                 .get_diffie_hellman()
-                                 .get_gs();
-
-        let shared_secret = local_keys.shared_secret(remote_key);
-        let (challenge, send_key, recv_key) = {
-            let mut data = Vec::with_capacity(0x64);
-            let mut mac = Hmac::new(Sha1::new(), &shared_secret);
-
-            for i in 1..6 {
-                mac.input(&init_client_packet);
-                mac.input(&init_server_packet);
-                mac.input(&[i]);
-                data.write(&mac.result().code()).unwrap();
-                mac.reset();
-            }
+        let (creds_tx, creds_rx) = oneshot::channel();
 
-            mac = Hmac::new(Sha1::new(), &data[..0x14]);
-            mac.input(&init_client_packet);
-            mac.input(&init_server_packet);
+        info!("Connecting to AP {}", addr);
 
-            (mac.result().code().to_vec(),
-             data[0x14..0x34].to_vec(),
-             data[0x34..0x54].to_vec())
-        };
+        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 packet = protobuf_init!(protocol::keyexchange::ClientResponsePlaintext::new(), {
-            login_crypto_response.diffie_hellman => {
-                hmac: challenge
-            },
-            pow_response => {},
-            crypto_response => {},
+             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();
 
-        connection.send_packet(&packet.write_to_bytes().unwrap()).unwrap();
+        self.0.data.write().unwrap().canonical_username = reusable_credentials.username.clone();
+        *self.0.rx_connection.lock().unwrap() = Some(rx);
+        *self.0.tx_connection.lock().unwrap() = Some(tx);
 
-        CipherConnection::new(connection.into_stream(),
-                              &send_key,
-                              &recv_key)
-    }
+        info!("Authenticated !");
 
-    pub fn login(&self, credentials: Credentials) -> Result<Credentials, ()> {
-        let packet = protobuf_init!(protocol::authentication::ClientResponseEncrypted::new(), {
-            login_credentials => {
-                username: credentials.username,
-                typ: credentials.auth_type,
-                auth_data: credentials.auth_data,
-            },
-            system_info => {
-                cpu_family: protocol::authentication::CpuFamily::CPU_UNKNOWN,
-                os: protocol::authentication::Os::OS_UNKNOWN,
-                system_information_string: "librespot".to_owned(),
-                device_id: self.device_id().to_owned(),
-            },
-            version_string: version::version_string(),
-        });
+        self.0.cache.put_credentials(&reusable_credentials);
 
-        let mut connection = self.connect();
-        connection.send_packet(0xab, &packet.write_to_bytes().unwrap()).unwrap();
-        let (cmd, data) = connection.recv_packet().unwrap();
-
-        match cmd {
-            0xac => {
-                let welcome_data: protocol::authentication::APWelcome =
-                    protobuf::parse_from_bytes(&data).unwrap();
-
-                let username = welcome_data.get_canonical_username().to_owned();
-                self.0.data.write().unwrap().canonical_username = username.clone();
-                *self.0.rx_connection.lock().unwrap() = Some(connection.clone());
-                *self.0.tx_connection.lock().unwrap() = Some(connection);
-
-                info!("Authenticated !");
-
-                let reusable_credentials = Credentials {
-                    username: username,
-                    auth_type: welcome_data.get_reusable_auth_credentials_type(),
-                    auth_data: welcome_data.get_reusable_auth_credentials().to_owned(),
-                };
-
-                self.0.cache.put_credentials(&reusable_credentials);
-
-                Ok(reusable_credentials)
-            }
-
-            0xad => {
-                let msg: protocol::keyexchange::APLoginFailed =
-                    protobuf::parse_from_bytes(&data).unwrap();
-                error!("Authentication failed, {:?}", msg);
-                Err(())
-            }
-            _ => {
-                error!("Unexpected message {:x}", cmd);
-                Err(())
-            }
-        }
+        Ok(reusable_credentials)
     }
 
     pub fn poll(&self) {
         let (cmd, data) = self.recv();
 
         match cmd {
-            0x4 => self.send_packet(0x49, &data).unwrap(),
+            0x4 => self.send_packet(0x49, data),
             0x4a => (),
             0x9 | 0xa => self.0.stream.lock().unwrap().handle(cmd, data, self),
             0xd | 0xe => self.0.audio_key.lock().unwrap().handle(cmd, data, self),
@@ -253,11 +150,11 @@ impl Session {
     }
 
     pub fn recv(&self) -> (u8, Vec<u8>) {
-        self.0.rx_connection.lock().unwrap().as_mut().unwrap().recv_packet().unwrap()
+        self.0.rx_connection.lock().unwrap().as_mut().unwrap().recv().unwrap()
     }
 
-    pub fn send_packet(&self, cmd: u8, data: &[u8]) -> connection::Result<()> {
-        self.0.tx_connection.lock().unwrap().as_mut().unwrap().send_packet(cmd, data)
+    pub fn send_packet(&self, cmd: u8, data: Vec<u8>) {
+        self.0.tx_connection.lock().unwrap().as_mut().unwrap().send((cmd, data))
     }
 
     pub fn audio_key(&self, track: SpotifyId, file_id: FileId) -> Future<AudioKey, AudioKeyError> {