Browse Source

Move ap resolve and discovery to tokio.

Paul Lietar 8 years ago
parent
commit
9de55bb8cd
9 changed files with 312 additions and 192 deletions
  1. 89 74
      Cargo.lock
  2. 5 4
      Cargo.toml
  3. 44 15
      src/apresolve.rs
  4. 127 78
      src/authentication/discovery.rs
  5. 2 1
      src/authentication/mod.rs
  6. 24 2
      src/connection/adaptor.rs
  7. 0 1
      src/lib.in.rs
  8. 4 3
      src/lib.rs
  9. 17 14
      src/session.rs

+ 89 - 74
Cargo.lock

@@ -7,10 +7,11 @@ dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "eventual 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)",
  "json_macros 0.3.1 (git+https://github.com/plietar/json_macros)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libpulse-sys 0.0.0 (git+https://github.com/astro/libpulse-sys)",
@@ -29,14 +30,14 @@ dependencies = [
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)",
  "tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)",
- "url 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -81,6 +82,29 @@ dependencies = [
  "syntex_syntax 0.55.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "backtrace"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "bit-set"
 version = "0.4.0"
@@ -125,13 +149,9 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "cookie"
-version = "0.2.5"
+name = "crossbeam"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "ctrlc"
@@ -143,6 +163,15 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "dns-parser"
 version = "0.3.2"
@@ -167,6 +196,14 @@ dependencies = [
  "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "error-chain"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "eventual"
 version = "0.1.7"
@@ -185,6 +222,16 @@ dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "futures-cpupool"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "gcc"
 version = "0.3.41"
@@ -195,14 +242,6 @@ name = "getopts"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "hpack"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "httparse"
 version = "1.2.1"
@@ -210,20 +249,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "hyper"
-version = "0.9.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.11.0-a.0"
+source = "git+https://github.com/hyperium/hyper#39a53fcd3364634125dafcf4d7a1d191241a7ff0"
 dependencies = [
- "cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -337,7 +377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "mdns"
 version = "0.2.0"
-source = "git+https://github.com/plietar/rust-mdns#8ea956858dcd900b02d795f35f884034d15cf8e8"
+source = "git+https://github.com/plietar/rust-mdns#51f0ffded504a576350fc5a8b4bdfe7144db3f6e"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)",
@@ -630,6 +670,14 @@ name = "regex-syntax"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "relay"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rpassword"
 version = "0.3.0"
@@ -653,6 +701,11 @@ dependencies = [
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-demangle"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustc-serialize"
 version = "0.3.22"
@@ -706,7 +759,7 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "0.8.4"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -752,15 +805,6 @@ name = "smallvec"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "solicit"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "syncbox"
 version = "0.2.4"
@@ -1003,11 +1047,6 @@ dependencies = [
  "futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "traitobject"
-version = "0.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "tremor"
 version = "0.1.0"
@@ -1028,11 +1067,6 @@ dependencies = [
  "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "typeable"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "unicase"
 version = "1.4.0"
@@ -1064,18 +1098,6 @@ name = "unicode-xid"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "url"
-version = "0.5.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "uuid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "url"
 version = "1.3.0"
@@ -1090,14 +1112,6 @@ name = "utf8-ranges"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "uuid"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "vergen"
 version = "0.1.1"
@@ -1185,6 +1199,8 @@ dependencies = [
 "checksum aster 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258989846dd255a1e0eeef92d425d345477c9999433cecc9f0879f4549d5e5c9"
 "checksum aster 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88bb8ecdf6a7eaddb7bfd872ebf5e085d343ca42ce98c582dba8046e3450b524"
 "checksum aster 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "022822e5621c840afed9d4fbdf52104bfc2ff6f0f64016a6bbe4e10d7ec70535"
+"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
+"checksum backtrace-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3602e8d8c43336088a8505fa55cae2b3884a9be29440863a11528a42f46f6bb7"
 "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
 "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
 "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
@@ -1193,18 +1209,20 @@ dependencies = [
 "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
 "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
-"checksum cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e3d6405328b6edb412158b3b7710e2634e23f3614b9bb1c412df7952489a626"
+"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
 "checksum ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77f98bb69e3fefadcc5ca80a1368a55251f70295168203e01165bcaecb270891"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)" = "<none>"
 "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
+"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
 "checksum eventual 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b9bda6d089b434ca50f3d6feb5fca421309b8bac97b8be9af51cff879fa3f54b"
 "checksum futures 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3e0b237aed5d8b61bc7d6ee1b8ebd719d0a934a38d363c5e56daf34bb634d9b2"
+"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
 "checksum gcc 0.3.41 (registry+https://github.com/rust-lang/crates.io-index)" = "3689e1982a563af74960ae3a4758aa632bb8fd984cfc3cc3b60ee6109477ab6e"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
 "checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
-"checksum hyper 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb3fc65554155980167fb821d05c7c66177f92464976c0b676a19d9e03387a7"
+"checksum hyper 0.11.0-a.0 (git+https://github.com/hyperium/hyper)" = "<none>"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
 "checksum json_macros 0.3.1 (git+https://github.com/plietar/json_macros)" = "<none>"
@@ -1251,8 +1269,10 @@ dependencies = [
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
+"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5"
 "checksum rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6e42be826e215f30ff830904f8f4a0933c6e2ae890e1af8b408f5bae60081e"
 "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
+"checksum rustc-demangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1430d286cadb237c17c885e25447c982c97113926bb579f4379c0eca8d9586dc"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
@@ -1260,13 +1280,12 @@ dependencies = [
 "checksum serde 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e4aab5b62fb90ac9c99d5a55caa7c37e06a15d1b189ccc2b117782655fd11f"
 "checksum serde_codegen 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da68810d845f8e33a80243c28794650397056cbe7aea4c9c7516f55d1061c94e"
 "checksum serde_codegen_internals 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0115c5c602e81c61b787fb0f0fa76a614f8dbe9100b2b59b7d590155672c80"
-"checksum serde_json 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7d3c184d35801fb8b32b46a7d58d57dbcc150b0eb2b46a1eb79645e8ecfd5b"
+"checksum serde_json 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6555a29b090ddb20dbb00226dede6b824149b4c32d6034af6040e22424939311"
 "checksum serde_macros 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c3cf1c01933271e1e72bb788e0499d1bca8af2c09efcc3ddc0b04ff22d080b83"
 "checksum shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)" = "<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"
@@ -1290,19 +1309,15 @@ dependencies = [
 "checksum tokio-core 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0800e9475303171ffbc79394079ef503b6d00949649799208f4fc8f1eca20892"
 "checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808"
 "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
-"checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
 "checksum tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
 "checksum tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
-"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
 "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
 "checksum unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b61814f3e7fd0e0f15370f767c7c943e08bc2e3214233ae8f88522b334ceb778"
 "checksum unicode-normalization 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5e94e9f6961090fcc75180629c4ef33e5310d6ed2c0dd173f4ca63c9043b669e"
 "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
-"checksum url 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3440c1ed62af4a2aee71c6fb78ef32ddcb75cfa24bf42f45e07c02b6d6a2f6"
 "checksum url 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbcb1997952b5a73b438a90940834621a8002e59640a8d92a1c05ef8fa58a1da"
 "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
-"checksum uuid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "885acc3b17fdef6230d1f7765dff1106dfd5e75a93c2f26459fbf600ed6dcc14"
 "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum vorbis 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "760993e54524128b88d4d7aff09c773c2f16a9f18db3c8ae1ccca5afd1287656"

+ 5 - 4
Cargo.toml

@@ -27,13 +27,13 @@ ctrlc           = { version = "2.0", features = ["termination"] }
 env_logger      = "0.3.2"
 eventual        = "0.1.6"
 getopts         = "0.2.14"
-hyper           = { version = "0.9.1", default-features = false }
+hyper           = { git = "https://github.com/hyperium/hyper" }
 lazy_static     = "0.2.0"
 linear-map      = "1.0"
 lmdb-rs         = "0.7.2"
 log             = "0.3.5"
 num             = "0.1.30"
-protobuf        = "1.0.15"
+protobuf        = "1.1"
 rand            = "0.3.13"
 rpassword       = "0.3.0"
 rust-crypto     = "0.2.34"
@@ -43,7 +43,7 @@ serde_json      = "0.8"
 serde_macros    = { version = "0.8", optional = true }
 shannon         = { git = "https://github.com/plietar/rust-shannon" }
 tempfile        = "2.1"
-url             = "0.5.0"
+url             = "1.3"
 
 vorbis          = "0.1.0"
 tremor          = { git = "https://github.com/plietar/rust-tremor", optional = true }
@@ -57,9 +57,10 @@ protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
 
 mdns            = { git = "https://github.com/plietar/rust-mdns" }
 
+error-chain = "0.7.0"
 futures = "0.1.8"
-tokio-proto = "0.1.0"
 tokio-core = "0.1.2"
+tokio-proto = "0.1.0"
 
 [build-dependencies]
 vergen          = "0.1.0"

+ 44 - 15
src/apresolve.rs

@@ -1,27 +1,56 @@
-const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/";
 const AP_FALLBACK : &'static str = "ap.spotify.com:80";
+const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/";
 
-use hyper;
-use std::io::Read;
+use futures::{Future, Stream};
+use hyper::{self, Url, Client};
 use serde_json;
+use tokio_core::reactor::Handle;
 
+error_chain! { }
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct APResolveData {
     ap_list: Vec<String>
 }
 
-pub fn apresolve() -> String {
-    let client = hyper::Client::new();
+pub fn apresolve(handle: &Handle) -> Box<Future<Item=String, Error=Error>> {
+    let url = Url::parse(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL");
+
+    let client = Client::new(&handle);
+    let response = client.get(url);
+
+    let body = response.and_then(|response| {
+        response.body().fold(Vec::new(), |mut acc, chunk| {
+            acc.extend_from_slice(chunk.as_ref());
+            Ok::<_, hyper::Error>(acc)
+        })
+    });
+    let body = body.then(|result| result.chain_err(|| "HTTP error"));
+    let body = body.and_then(|body| {
+        String::from_utf8(body).chain_err(|| "invalid UTF8 in response")
+    });
+
+    let data = body.and_then(|body| {
+        serde_json::from_str::<APResolveData>(&body)
+            .chain_err(|| "invalid JSON")
+    });
+
+    let ap = data.and_then(|data| {
+        let ap = data.ap_list.first().ok_or("empty AP List")?;
+        Ok(ap.clone())
+    });
+
+    Box::new(ap)
+}
 
-    (|| {
-        let mut response = client.get(APRESOLVE_ENDPOINT).send().map_err(|_| ())?;
-        let mut data = String::new();
-        response.read_to_string(&mut data).map_err(|_| ())?;
+pub fn apresolve_or_fallback<E>(handle: &Handle)
+    -> Box<Future<Item=String, Error=E>>
+    where E: 'static
+{
+    let ap = apresolve(handle).or_else(|e| {
+        warn!("Failed to resolve Access Point: {}", e.description());
+        warn!("Using fallback \"{}\"", AP_FALLBACK);
+        Ok(AP_FALLBACK.into())
+    });
 
-        let data : APResolveData = serde_json::from_str(&data).map_err(|_| ())?;
-        data.ap_list.first().map(Clone::clone).ok_or(())
-    })().unwrap_or_else(|_| {
-        warn!("failed to resolve AP, using fallback");
-        AP_FALLBACK.into()
-    })
+    Box::new(ap)
 }

+ 127 - 78
src/authentication/discovery.rs

@@ -1,34 +1,70 @@
-use crypto;
-use crypto::mac::Mac;
 use crypto::digest::Digest;
-use hyper;
-use hyper::net::NetworkListener;
+use crypto::mac::Mac;
+use crypto;
+use diffie_hellman::{DH_GENERATOR, DH_PRIME};
+use futures::{Future, Stream, BoxFuture};
+use futures::sync::mpsc;
+use hyper::{self, Get, Post, StatusCode};
+use hyper::server::{Server, Service, NewService, Request, Response};
+use mdns;
 use num::BigUint;
-use url;
 use rand;
 use rustc_serialize::base64::{self, ToBase64, FromBase64};
+use std::io;
 use std::collections::BTreeMap;
-use std::io::{Read, Write};
-use std::sync::{mpsc, Mutex};
-use mdns;
+use std::sync::Arc;
+use url;
+use tokio_core::reactor::Handle;
+use std::net::SocketAddr;
 
 use authentication::Credentials;
-use diffie_hellman::{DH_GENERATOR, DH_PRIME};
+use connection::adaptor::adapt_future;
 use util;
 
-struct ServerHandler {
-    credentials_tx: Mutex<mpsc::Sender<Credentials>>,
+#[derive(Clone)]
+struct Discovery(Arc<DiscoveryInner>);
+struct DiscoveryInner {
     private_key: BigUint,
     public_key: BigUint,
     device_id: String,
     device_name: String,
+    tx: mpsc::UnboundedSender<Credentials>,
 }
 
-impl ServerHandler {
-    fn handle_get_info(&self, _params: &BTreeMap<String, String>,
-                       mut response: hyper::server::Response<hyper::net::Fresh>) {
+impl Discovery {
+    pub fn new(device_name: String, device_id: String)
+        -> (Discovery, mpsc::UnboundedReceiver<Credentials>)
+    {
+        let (tx, rx) = mpsc::unbounded();
+
+        let key_data = util::rand_vec(&mut rand::thread_rng(), 95);
+        let private_key = BigUint::from_bytes_be(&key_data);
+        let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
+
+        let discovery = Discovery(Arc::new(DiscoveryInner {
+            device_name: device_name.to_owned(),
+            device_id: device_id.to_owned(),
+            private_key: private_key,
+            public_key: public_key,
+            tx: tx,
+        }));
+
+        (discovery, rx)
+    }
+
+    pub fn serve(&self, addr: &SocketAddr, handle: &Handle)
+        -> hyper::Result<SocketAddr>
+    {
+        let server = Server::http(&addr, handle)?;
+        server.handle(self.clone(), handle)
+    }
+}
 
-        let public_key = self.public_key.to_bytes_be()
+impl Discovery {
+    fn handle_get_info(&self, _params: &BTreeMap<String, String>)
+        -> ::futures::Finished<Response, hyper::Error>
+    {
+        let public_key = self.0.public_key.to_bytes_be()
                                         .to_base64(base64::STANDARD);
 
         let result = json!({
@@ -36,8 +72,8 @@ impl ServerHandler {
             "statusString": "ERROR-OK",
             "spotifyError": 0,
             "version": "2.1.0",
-            "deviceID": (self.device_id),
-            "remoteName": (self.device_name),
+            "deviceID": (self.0.device_id),
+            "remoteName": (self.0.device_name),
             "activeUser": "",
             "publicKey": (public_key),
             "deviceType": "UNKNOWN",
@@ -47,13 +83,13 @@ impl ServerHandler {
             "modelDisplayName": "librespot",
         });
 
-        *response.status_mut() = hyper::status::StatusCode::Ok;
-        response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap();
+        let body = result.to_string();
+        ::futures::finished(Response::new().with_body(body))
     }
 
-    fn handle_add_user(&self, params: &BTreeMap<String, String>,
-                       mut response: hyper::server::Response<hyper::net::Fresh>) {
-
+    fn handle_add_user(&self, params: &BTreeMap<String, String>)
+        -> ::futures::Finished<Response, hyper::Error>
+    {
         let username = params.get("userName").unwrap();
         let encrypted_blob = params.get("blob").unwrap();
         let client_key = params.get("clientKey").unwrap();
@@ -63,7 +99,7 @@ impl ServerHandler {
         let client_key = client_key.from_base64().unwrap();
         let client_key = BigUint::from_bytes_be(&client_key);
 
-        let shared_key = util::powm(&client_key, &self.private_key, &DH_PRIME);
+        let shared_key = util::powm(&client_key, &self.0.private_key, &DH_PRIME);
 
         let iv = &encrypted_blob[0..16];
         let encrypted = &encrypted_blob[16..encrypted_blob.len() - 20];
@@ -106,9 +142,9 @@ impl ServerHandler {
             String::from_utf8(data).unwrap()
         };
 
-        let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.device_id);
+        let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.0.device_id);
 
-        self.credentials_tx.lock().unwrap().send(credentials).unwrap();
+        self.0.tx.send(credentials).unwrap();
 
         let result = json!({
             "status": 101,
@@ -116,74 +152,87 @@ impl ServerHandler {
             "statusString": "ERROR-OK"
         });
 
-        *response.status_mut() = hyper::status::StatusCode::Ok;
-        response.start().unwrap().write_all(result.to_string().as_bytes()).unwrap();
+        let body = result.to_string();
+        ::futures::finished(Response::new().with_body(body))
     }
 
-    fn not_found(&self, mut response: hyper::server::Response<hyper::net::Fresh>) {
-
-        *response.status_mut() = hyper::status::StatusCode::NotFound
+    fn not_found(&self)
+        -> ::futures::Finished<Response, hyper::Error>
+    {
+        ::futures::finished(Response::new().with_status(StatusCode::NotFound))
     }
 }
 
-impl hyper::server::Handler for ServerHandler {
-    fn handle<'a, 'k>(&'a self,
-                      mut request: hyper::server::Request<'a, 'k>,
-                      response: hyper::server::Response<'a, hyper::net::Fresh>) {
-
-        if let hyper::uri::RequestUri::AbsolutePath(path) = request.uri.clone() {
-            let (_, query, _) = url::parse_path(&path).unwrap();
-            let mut params = query.map_or(vec![], |q| url::form_urlencoded::parse(q.as_bytes()))
-                                  .into_iter().collect::<BTreeMap<_,_>>();
-
-            if request.method == hyper::method::Method::Post {
-                let mut body = Vec::new();
-                request.read_to_end(&mut body).unwrap();
-                let form = url::form_urlencoded::parse(&body);
-                params.extend(form);
-            }
+impl Service for Discovery {
+    type Request = Request;
+    type Response = Response;
+    type Error = hyper::Error;
+    type Future = BoxFuture<Response, hyper::Error>;
 
-            debug!("{:?} {:?} {:?}", request.method, path, params);
+    fn call(&self, request: Request) -> Self::Future {
+        let mut params = BTreeMap::new();
 
-            match params.get("action").map(AsRef::as_ref) {
-                Some("getInfo") => self.handle_get_info(&params, response),
-                Some("addUser") => self.handle_add_user(&params, response),
-                _ => self.not_found(response),
-            }
-        } else {
-            self.not_found(response)
+        let (method, uri, _, _, body) = request.deconstruct();
+        if let Some(query) = uri.query() {
+            params.extend(url::form_urlencoded::parse(query.as_bytes()).into_owned());
         }
+
+        debug!("{:?} {:?} {:?}", method, uri.path(), params);
+
+        let this = self.clone();
+        body.fold(Vec::new(), |mut acc, chunk| {
+            acc.extend_from_slice(chunk.as_ref());
+            Ok::<_, hyper::Error>(acc)
+        }).map(move |body| {
+            params.extend(url::form_urlencoded::parse(&body).into_owned());
+            params
+        }).and_then(move |params| {
+            match (method, params.get("action").map(AsRef::as_ref)) {
+                (Get, Some("getInfo")) => this.handle_get_info(&params),
+                (Post, Some("addUser")) => this.handle_add_user(&params),
+                _ => this.not_found(),
+            }
+        }).boxed()
+    }
+}
+
+impl NewService for Discovery {
+    type Request = Request;
+    type Response = Response;
+    type Error = hyper::Error;
+    type Instance = Self;
+
+    fn new_service(&self) -> io::Result<Self::Instance> {
+        Ok(self.clone())
     }
 }
 
-pub fn discovery_login(device_name: &str, device_id: &str) -> Result<Credentials, ()> {
-    let (tx, rx) = mpsc::channel();
+pub fn discovery_login<A,B>(device_name: A, device_id: B) -> Result<Credentials, ()>
+    where A: Into<String>,
+          B: Into<String>
+{
+    let device_name = device_name.into();
+    let device_id = device_id.into();
 
-    let key_data = util::rand_vec(&mut rand::thread_rng(), 95);
-    let private_key = BigUint::from_bytes_be(&key_data);
-    let public_key = util::powm(&DH_GENERATOR, &private_key, &DH_PRIME);
+    let (discovery, rx) = Discovery::new(device_name.clone(), device_id);
 
-    let handler = ServerHandler {
-        device_name: device_name.to_owned(),
-        device_id: device_id.to_owned(),
-        private_key: private_key,
-        public_key: public_key,
-        credentials_tx: Mutex::new(tx),
-    };
+    let addr = "0.0.0.0:0".parse().unwrap();
+    let cred = adapt_future(move |handle| {
+        let addr = discovery.serve(&addr, &handle).unwrap();
 
-    let mut listener = hyper::net::HttpListener::new("0.0.0.0:0").unwrap();
-    let port = listener.local_addr().unwrap().port();
+        let responder = mdns::Responder::spawn(&handle).unwrap();
+        let svc = responder.register(
+            "_spotify-connect._tcp".to_owned(),
+            device_name,
+            addr.port(),
+            &["VERSION=1.0", "CPath=/"]);
 
-    let mut server = hyper::Server::new(listener).handle(handler).unwrap();
+        rx.into_future()
+            .map(move |(creds, _)| (creds, svc))
+            .map_err(|(e, _)| e)
+    });
 
-    let responder = mdns::Responder::new().unwrap();
-    let _svc = responder.register(
-        "_spotify-connect._tcp".to_owned(),
-        device_name.to_owned(),
-        port,
-        &["VERSION=1.0", "CPath=/"]);
 
-    let cred = rx.recv().unwrap();
-    server.close().unwrap();
-    Ok(cred)
+    let (creds, _svc) = cred.wait().unwrap().unwrap();
+    Ok(creds.unwrap())
 }

+ 2 - 1
src/authentication/mod.rs

@@ -197,7 +197,8 @@ pub fn get_credentials(session: &Session, username: Option<String>, password: Op
 
         (None, _, None) => {
             info!("No username provided and no stored credentials, starting discovery ...");
-            discovery_login(&session.config().device_name, session.device_id()).unwrap()
+            discovery_login(session.config().device_name.clone(),
+                            session.device_id()).unwrap()
         }
     }
 }

+ 24 - 2
src/connection/adaptor.rs

@@ -1,5 +1,6 @@
 use futures::future::ok;
 use futures::sync::mpsc;
+use futures::sync::oneshot;
 use futures::{Future, Sink, Stream, BoxFuture, IntoFuture};
 use std::thread;
 use tokio_core::reactor::Core;
@@ -52,7 +53,7 @@ fn adapt_stream<S>(stream: S, tx: mpsc::Sender<Result<S::Item, S::Error>>) -> Bo
 }
 
 pub fn adapt<F, U, S>(f: F) -> (SinkAdaptor<S::SinkItem>, StreamAdaptor<S::Item, S::Error>)
-    where F: FnOnce(&Handle) -> U + Send + 'static,
+    where F: FnOnce(Handle) -> U + Send + 'static,
           U: IntoFuture<Item=S>,
           S: Sink + Stream + Send + 'static,
           S::Item: Send + 'static,
@@ -69,7 +70,7 @@ pub fn adapt<F, U, S>(f: F) -> (SinkAdaptor<S::SinkItem>, StreamAdaptor<S::Item,
         let mut core = Core::new().unwrap();
         let handle = core.handle();
         let task =
-            f(&handle).into_future()
+            f(handle).into_future()
             .map(|connection| connection.split())
             .map_err(|_| ())
             .and_then(|(sink, stream)| {
@@ -83,3 +84,24 @@ pub fn adapt<F, U, S>(f: F) -> (SinkAdaptor<S::SinkItem>, StreamAdaptor<S::Item,
     (SinkAdaptor(Some(sender_tx)),
      StreamAdaptor(Some(receiver_rx)))
 }
+
+pub fn adapt_future<F, U>(f: F) -> oneshot::Receiver<Result<U::Item, U::Error>>
+    where F: FnOnce(Handle) -> U + Send + 'static,
+          U: IntoFuture,
+          U::Item: Send + 'static,
+          U::Error: Send + 'static,
+{
+    let (tx, rx) = oneshot::channel();
+
+    thread::spawn(move || {
+        let mut core = Core::new().unwrap();
+        let handle = core.handle();
+
+        let task = f(handle).into_future();
+        let result = core.run(task);
+
+        tx.complete(result);
+    });
+
+    rx
+}

+ 0 - 1
src/lib.in.rs

@@ -2,5 +2,4 @@ pub mod apresolve;
 pub mod authentication;
 pub mod connection;
 pub mod mercury;
-pub mod session;
 pub mod spirc;

+ 4 - 3
src/lib.rs

@@ -8,6 +8,8 @@
 #![cfg_attr(feature="clippy", feature(plugin))]
 #![cfg_attr(feature="clippy", plugin(clippy))]
 
+#[macro_use] extern crate error_chain;
+#[macro_use] extern crate futures;
 #[macro_use] extern crate lazy_static;
 #[macro_use] extern crate log;
 
@@ -29,11 +31,9 @@ extern crate serde;
 extern crate serde_json;
 extern crate shannon;
 extern crate tempfile;
-extern crate url;
-
-#[macro_use] extern crate futures;
 extern crate tokio_core;
 extern crate tokio_proto;
+extern crate url;
 
 extern crate librespot_protocol as protocol;
 
@@ -60,6 +60,7 @@ pub mod diffie_hellman;
 pub mod link;
 pub mod metadata;
 pub mod player;
+pub mod session;
 pub mod stream;
 pub mod util;
 pub mod version;

+ 17 - 14
src/session.rs

@@ -12,7 +12,7 @@ use futures::Stream;
 use futures::sync::oneshot;
 
 use album_cover::AlbumCover;
-use apresolve::apresolve;
+use apresolve::apresolve_or_fallback;
 use audio_file::AudioFile;
 use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
 use authentication::Credentials;
@@ -101,26 +101,29 @@ impl Session {
     }
 
     pub fn login(&self, credentials: Credentials) -> Result<Credentials, ()> {
-        let addr = apresolve();
         let device_id = self.device_id().to_owned();
 
         let (creds_tx, creds_rx) = oneshot::channel();
 
-        info!("Connecting to AP {}", addr);
-
         let (tx, rx) = adaptor::adapt(move |handle| {
-             let connection = connection::connect(&addr as &str, &handle);
-             let authentication = connection.and_then(|connection| {
-                 connection::authenticate(connection, credentials, device_id)
-             });
-
-             authentication.map(|(transport, creds)| {
-                 creds_tx.complete(creds);
-                 transport.map(|(cmd, data)| (cmd, data.as_ref().to_owned()))
-             })
+            let access_point = apresolve_or_fallback::<io::Error>(&handle);
+
+            let connection = access_point.and_then(move |addr| {
+                info!("Connecting to AP \"{}\"", addr);
+                connection::connect::<&str>(&addr, &handle)
+            });
+
+            let authentication = connection.and_then(move |connection| {
+                connection::authenticate(connection, credentials, device_id)
+            });
+
+            authentication.map(|(transport, creds)| {
+                creds_tx.complete(creds);
+                transport.map(|(cmd, data)| (cmd, data.as_ref().to_owned()))
+            })
         });
 
-        let reusable_credentials = creds_rx.wait().unwrap();
+        let reusable_credentials: Credentials = creds_rx.wait().unwrap();
 
         self.0.data.write().unwrap().canonical_username = reusable_credentials.username.clone();
         *self.0.rx_connection.lock().unwrap() = Some(rx);