From e4933ef9db8199d7f7a388615876c1549099b8ec Mon Sep 17 00:00:00 2001 From: James Kominick Date: Sun, 23 Dec 2018 00:30:36 -0500 Subject: [PATCH] convert server to use warp --- Cargo.lock | 972 ++++++++++++++++++++++++++++++++++++------------ Cargo.toml | 11 +- src/admin.rs | 4 +- src/auth.rs | 19 +- src/db.rs | 12 +- src/error.rs | 226 +++++++++++ src/errors.rs | 86 ----- src/handlers.rs | 627 ++++++++++++++++++------------- src/lib.rs | 97 +---- src/macros.rs | 52 +-- src/main.rs | 24 +- src/models.rs | 33 +- src/service.rs | 300 ++++++++++----- src/sweep.rs | 2 +- 14 files changed, 1627 insertions(+), 838 deletions(-) create mode 100644 src/error.rs delete mode 100644 src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index a1f66f9..59e5d89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,8 +1,3 @@ -[[package]] -name = "adler32" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "aho-corasick" version = "0.6.9" @@ -30,9 +25,12 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "ascii" -version = "0.8.7" +name = "arrayvec" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "atty" @@ -89,6 +87,14 @@ dependencies = [ "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.0.4" @@ -104,40 +110,32 @@ dependencies = [ ] [[package]] -name = "brotli-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "brotli2" -version = "0.3.2" +name = "block-buffer" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "buf_redux" -version = "0.6.3" +name = "block-padding" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "build_const" -version = "0.2.1" +name = "byte-tools" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byte-tools" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -174,11 +172,6 @@ dependencies = [ "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "chunked_transfer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "clap" version = "2.32.0" @@ -207,100 +200,63 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "crc" -version = "1.8.1" +name = "crossbeam-deque" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crypto-mac" -version = "0.5.2" +name = "crossbeam-epoch" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "deflate" -version = "0.7.19" +name = "crossbeam-utils" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "digest" -version = "0.7.6" +name = "crypto-mac" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "dtoa" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" +name = "digest" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" +name = "digest" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "encoding_index_tests" -version = "0.1.4" +name = "dtoa" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -334,14 +290,9 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "filetime" -version = "0.2.4" +name = "fnv" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "fuchsia-zircon" @@ -357,6 +308,30 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-fs" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.55" @@ -371,11 +346,63 @@ dependencies = [ ] [[package]] -name = "gzip-header" -version = "0.2.0" +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "h2" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "headers-core" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "headers-derive" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "headers-ext" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-core 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-derive 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -397,6 +424,16 @@ dependencies = [ "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -410,6 +447,32 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.12.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.5" @@ -420,6 +483,19 @@ dependencies = [ "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "input_buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.2" @@ -434,22 +510,37 @@ name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +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 = "lazy_static" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "log" -version = "0.3.9" +name = "lock_api" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -488,6 +579,11 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "migrant_lib" version = "0.21.0" @@ -510,39 +606,77 @@ dependencies = [ [[package]] name = "mime" -version = "0.2.6" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime_guess" -version = "1.8.6" +version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "multipart" -version = "0.13.6" +name = "mio" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.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)", + "net2 0.2.33 (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 = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num-integer" version = "0.1.39" @@ -564,6 +698,40 @@ dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -722,11 +890,38 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.2.2" +name = "rand" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -734,6 +929,39 @@ name = "rand_core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.44" @@ -767,14 +995,6 @@ dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "remove_dir_all" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ring" version = "0.13.5" @@ -796,30 +1016,6 @@ dependencies = [ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rouille" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rust-crypto" version = "0.2.36" @@ -842,6 +1038,14 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "0.2.7" @@ -873,6 +1077,29 @@ dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.82" @@ -913,9 +1140,15 @@ dependencies = [ ] [[package]] -name = "sha1" -version = "0.6.0" +name = "sha-1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "sha2" @@ -933,6 +1166,19 @@ name = "siphasher" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slab" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "socket2" version = "0.3.8" @@ -944,6 +1190,16 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "stable_deref_trait" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "string" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stringprep" version = "0.1.2" @@ -968,24 +1224,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "term" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "termcolor" version = "1.0.4" @@ -1021,34 +1259,168 @@ dependencies = [ ] [[package]] -name = "threadpool" -version = "1.7.1" +name = "time" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "time" -version = "0.1.41" +name = "tokio-codec" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tiny_http" -version = "0.6.0" +name = "tokio-current-thread" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1061,37 +1433,56 @@ dependencies = [ [[package]] name = "transfer" -version = "0.4.6" +version = "0.5.0" dependencies = [ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-fs 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "migrant_lib 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "postgres 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2_postgres 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "warp 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "twoway" -version = "0.1.8" +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tungstenite" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "utf-8 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1112,6 +1503,14 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicase" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1135,6 +1534,14 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "untrusted" version = "0.6.2" @@ -1150,6 +1557,16 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "urlencoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf-8" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "utf8-ranges" version = "1.0.2" @@ -1173,6 +1590,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.7" @@ -1183,6 +1605,40 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "warp" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "headers-ext 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tungstenite 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -1197,6 +1653,11 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1224,85 +1685,109 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +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 = "xdg" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcce89e5ad5c8949caa9434501f7b55415b3e7ad5270cb88c75a8d35e8f1279" +"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" -"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" -"checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" +"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" +"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" +"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" "checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958" -"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7217124812dc5672b7476d0c2d20cfe9f7c0f1ba0904b674a9762a0212f72e" -"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-fs 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9b9f2aeb603383051bab2898cb253a0efed9b590582d0b7baaa0b25de2a536d5" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" +"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" +"checksum headers-core 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b177de757c6a8cec695531203fb9007f2e2a5682d7f2da3f244b489d8f1d9b63" +"checksum headers-derive 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edde4fd70cf0afd2b24f3e6ef97274145895a34259ac8f746c30080663417bf8" +"checksum headers-ext 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "de71c9c9a0741c7fa09bd93efd8790ae7fb9105263892606b4edb2545524f90e" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e" +"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum migrant_lib 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d8bbce892feca34a6994b03a1e500541b02bedf46b9afc81e10f570b56b955" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" -"checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" +"checksum mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0a907b83e7b9e987032439a387e187119cddafc92d5c2aaeb1d92580a793f630" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" +"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6" "checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" @@ -1319,64 +1804,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" +"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" +"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f" -"checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" +"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" "checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d" "checksum stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" -"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" +"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" +"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75" +"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" +"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" +"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912" +"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f" +"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" -"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum tungstenite 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9573852f935883137b7f0824832493ce7418bf290c8cf164b7aafc9b0a99aa0" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3df3561629a8bb4c57e5a2e4c43348d9e29c7c29d9b1c4c1f47166deca8f37ed" +"checksum utf-8 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bab35f71693630bb1953dce0f2bcd780e7cde025027124a202ac08a45ba25141" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum warp 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "54f339bbe4877bce5709e6af3ffa579006c3688abe18d0a083d3b570fb870d29" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" diff --git a/Cargo.toml b/Cargo.toml index cbe16ec..b63303a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,12 @@ [package] name = "transfer" -version = "0.4.6" +version = "0.5.0" authors = ["James Kominick "] [dependencies] clap = "2" log = "0.4" env_logger = "0.6" -error-chain = "0.12" ron = "0.4" lazy_static = "1" @@ -28,5 +27,11 @@ r2d2_postgres = "0.14" xdg = "2" migrant_lib = { version = "0.21", features = ["d-postgres"] } -rouille = "2" +warp = "0.1" +hyper = "0.12" +futures = "0.1" +futures-cpupool = "0.1" +futures-fs = "0.0.5" +num_cpus = "1" +tokio = "0.1" diff --git a/src/admin.rs b/src/admin.rs index 866ea71..e3c14f8 100644 --- a/src/admin.rs +++ b/src/admin.rs @@ -3,7 +3,7 @@ General Admin commands */ use sweep; use models::CONFIG; -use errors::*; +use error::{self, Result}; /// Cleanup files that no longer have an associated record in the database @@ -13,7 +13,7 @@ pub fn sweep_files() -> Result<()> { let n = sweep::sweep_fs(&upload_dir)?; info!("** Cleaned up {} orphaned files **", n); } else { - bail!("Provided upload dir is invalid: {:?}", upload_dir); + return Err(error::helpers::internal(format!("Provided upload dir is invalid: {:?}", upload_dir))); } Ok(()) } diff --git a/src/auth.rs b/src/auth.rs index 1499d63..68f679c 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -2,14 +2,14 @@ Authorization/crypto things */ -use errors::*; +use error; use ring::rand::{self, SecureRandom}; use ring::{digest, constant_time}; use crypto::bcrypt; /// Generate a new 16-byte salt for use with `bcrypt` -pub fn new_salt() -> Result> { +pub fn new_salt() -> error::Result> { const SALT_SIZE: usize = 16; let mut salt = vec![0u8; SALT_SIZE]; let rng = rand::SystemRandom::new(); @@ -27,13 +27,16 @@ pub fn sha256(bytes: &[u8]) -> Vec { /// Calculate the `bcrypt` hash of `bytes` and `salt` -pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> Result> { +pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> error::Result> { let slen = salt.len(); let blen = bytes.len(); if !(slen == 16 && (0 < blen && blen <= 72)) { - bail_fmt!(ErrorKind::InvalidHashArgs, - "Expected salt size (16) and bytes size (1-72), got: salt({}), bytes({})", - salt.len(), bytes.len()) + return Err(error::helpers::internal( + format!( + "Expected salt size (16) and bytes size (1-72), got: salt({}), bytes({})", + salt.len(), bytes.len(), + ) + )); } const COST: u32 = 10; const OUTPUT_SIZE: usize = 24; @@ -44,9 +47,9 @@ pub fn bcrypt_hash(bytes: &[u8], salt: &[u8]) -> Result> { /// Constant time slice equality comparison -pub fn eq(a: &[u8], b: &[u8]) -> Result<()> { +pub fn eq(a: &[u8], b: &[u8]) -> error::Result<()> { constant_time::verify_slices_are_equal(a, b) - .map_err(|_| format_err!(ErrorKind::UnequalBytes, "Bytes differ"))?; + .map_err(|_| "Bytes differ")?; debug!("Auth OK"); Ok(()) } diff --git a/src/db.rs b/src/db.rs index 3d5131a..f170166 100644 --- a/src/db.rs +++ b/src/db.rs @@ -7,7 +7,7 @@ use postgres; use migrant_lib; use {config_dir}; -use super::errors::*; +use error::Result; /// Postgres r2d2 pool @@ -22,21 +22,21 @@ pub type DbConn = r2d2::PooledConnection; pub fn connect_str() -> Result { let config_dir_ = config_dir()?; let config_path = migrant_lib::search_for_settings_file(&config_dir_) - .chain_err(|| "Unable to find `Migrant.toml` config file")?; + .ok_or_else(|| "Unable to find `Migrant.toml` config file")?; let config = migrant_lib::Config::from_settings_file(&config_path) - .chain_err(|| "Failed loading `Migrant.toml`")?; - Ok(config.connect_string().chain_err(|| "Failed creating a connection string")?) + .map_err(|_| "Failed loading `Migrant.toml`")?; + Ok(config.connect_string().map_err(|_| "Failed creating a connection string")?) } /// Initialize a new r2d2 postgres connection pool -pub fn init_pool() -> Pool { +pub fn init_pool(n: u32) -> Pool { // let config = r2d2::Config::default(); let conn_str = connect_str().expect("Failed to build connection string"); let manager = PostgresConnectionManager::new(conn_str, TlsMode::None) .expect("Failed to connect to db"); r2d2::Pool::builder() - .min_idle(Some(3)) + .min_idle(Some(n)) .build(manager) .expect("Failed to create db pool") } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..9515dda --- /dev/null +++ b/src/error.rs @@ -0,0 +1,226 @@ +use std::io; +use std::net; +use warp; +use hex; +use uuid; +use serde_json; +use postgres; +use r2d2; +use ring; +use xdg; + + +pub mod helpers { + use super::*; + + pub fn reject>(e: T) -> warp::Rejection { + warp::reject::custom(e.into()) + } + + pub fn internal>(s: T) -> self::Error { + Error::from_kind(ErrorKind::Internal(s.as_ref().to_string())) + } + + pub fn bad_request>(s: T) -> self::Error { + Error::from_kind(ErrorKind::BadRequest(s.as_ref().to_string())) + } + + pub fn invalid_auth>(s: T) -> self::Error { + Error::from_kind(ErrorKind::InvalidAuth(s.as_ref().to_string())) + } + + pub fn too_large>(s: T) -> self::Error { + Error::from_kind(ErrorKind::UploadTooLarge(s.as_ref().to_string())) + } + + pub fn out_of_space>(s: T) -> self::Error { + Error::from_kind(ErrorKind::OutOfSpace(s.as_ref().to_string())) + } + + pub fn does_not_exist>(s: T) -> self::Error { + Error::from_kind(ErrorKind::DoesNotExist(s.as_ref().to_string())) + } + + pub fn multiple_records>(s: T) -> self::Error { + Error::from_kind(ErrorKind::MultipleRecords(s.as_ref().to_string())) + } +} + + +pub type Result = std::result::Result; + + +pub trait Rejectable { + fn reject(self) -> std::result::Result; + fn reject_with(self, impl Fn(E) -> warp::Rejection) -> std::result::Result; +} + +impl> Rejectable for std::result::Result { + fn reject(self) -> std::result::Result { + self.map_err(|e| warp::reject::custom(e.into())) + } + + fn reject_with(self, convert: impl Fn(E) -> warp::Rejection) -> std::result::Result { + self.map_err(convert) + } +} + + +#[derive(Debug)] +pub struct Error { + kind: Box, +} +impl Error { + pub fn kind(&self) -> &ErrorKind { + self.kind.as_ref() + } + + pub fn from_kind(kind: ErrorKind) -> Self { + Self { kind: Box::new(kind) } + } + + pub fn is_does_not_exist(&self) -> bool { + if let self::ErrorKind::DoesNotExist(_) = self.kind() { true } else { false } + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use self::ErrorKind::*; + match *self.kind() { + S(ref s) => write!(f, "{}", s), + Internal(ref s) => write!(f, "InternalError: {}", s), + BadRequest(ref s) => write!(f, "BadRequest: {}", s), + UploadTooLarge(ref s) => write!(f, "UploadTooLarge: {}", s), + OutOfSpace(ref s) => write!(f, "OutOfSpace: {}", s), + DoesNotExist(ref s) => write!(f, "DoesNotExist: {}", s), + MultipleRecords(ref s) => write!(f, "MultipleRecords: {}", s), + InvalidAuth(ref s) => write!(f, "InvalidAuth: {}", s), + + Io(ref e) => write!(f, "IoError: {}", e), + Warp(ref e) => write!(f, "WarpError: {}", e), + Json(ref e) => write!(f, "JsonError: {}", e), + Uuid(ref e) => write!(f, "UuidError: {}", e), + Hex(ref e) => write!(f, "HexError: {}", e), + Postgres(ref e) => write!(f, "PostgresError: {}", e), + ConnError(ref e) => write!(f, "ConnError: {}", e), + RingUnspecified(ref e) => write!(f, "RingUnspecified: {}", e), + Xdg(ref e) => write!(f, "Xdg: {}", e), + ParseAddr(ref e) => write!(f, "ParseAddr: {}", e), + } + } +} + +impl std::error::Error for Error { + fn description(&self) -> &str { + "transfer error" + } + + fn cause(&self) -> Option<&std::error::Error> { + use self::ErrorKind::*; + Some(match *self.kind() { + Warp(ref e) => e, + Json(ref e) => e, + Io(ref e) => e, + Uuid(ref e) => e, + Hex(ref e) => e, + Postgres(ref e) => e, + ConnError(ref e) => e, + RingUnspecified(ref e) => e, + Xdg(ref e) => e, + ParseAddr(ref e) => e, + _ => return None, + }) + } +} + + +#[derive(Debug)] +pub enum ErrorKind { + S(String), + Internal(String), + BadRequest(String), + UploadTooLarge(String), + OutOfSpace(String), + DoesNotExist(String), + MultipleRecords(String), + InvalidAuth(String), + + Io(io::Error), + Warp(warp::Error), + Json(serde_json::Error), + Uuid(uuid::ParseError), + Hex(hex::FromHexError), + Postgres(postgres::error::Error), + ConnError(r2d2::Error), + RingUnspecified(ring::error::Unspecified), + Xdg(xdg::BaseDirectoriesError), + ParseAddr(net::AddrParseError), +} + +impl From<&str> for Error { + fn from(s: &str) -> Error { + Error { kind: Box::new(ErrorKind::S(s.into())) } + } +} + +impl From for Error { + fn from(e: io::Error) -> Error { + Error { kind: Box::new(ErrorKind::Io(e)) } + } +} + + +impl From for Error { + fn from(e: warp::Error) -> Error { + Error { kind: Box::new(ErrorKind::Warp(e)) } + } +} + +impl From for Error { + fn from(e: serde_json::Error) -> Error { + Error { kind: Box::new(ErrorKind::Json(e)) } + } +} + +impl From for Error { + fn from(e: uuid::ParseError) -> Error { + Error { kind: Box::new(ErrorKind::Uuid(e)) } + } +} + +impl From for Error { + fn from(e: hex::FromHexError) -> Error { + Error { kind: Box::new(ErrorKind::Hex(e)) } + } +} + +impl From for Error { + fn from(e: postgres::error::Error) -> Error { + Error { kind: Box::new(ErrorKind::Postgres(e)) } + } +} + +impl From for Error { + fn from(e: r2d2::Error) -> Error { + Error { kind: Box::new(ErrorKind::ConnError(e)) } + } +} + +impl From for Error { + fn from(e: ring::error::Unspecified) -> Error { + Error { kind: Box::new(ErrorKind::RingUnspecified(e)) } + } +} + +impl From for Error { + fn from(e: xdg::BaseDirectoriesError) -> Error { + Error { kind: Box::new(ErrorKind::Xdg(e)) } + } +} + +impl From for Error { + fn from(e: net::AddrParseError) -> Error { + Error { kind: Box::new(ErrorKind::ParseAddr(e)) } + } +} diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index aebf759..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,86 +0,0 @@ -/*! -Project Error type and conversions -*/ -use std; -use log; -use uuid; -use hex; -use serde_json; -use postgres; -use r2d2; -use ring; -use migrant_lib; -use xdg; - - -error_chain! { - foreign_links { - Io(std::io::Error); - LogInit(log::SetLoggerError) #[doc = "Error initializing env_logger"]; - ConnError(r2d2::Error); - ParseInt(std::num::ParseIntError); - Json(serde_json::Error); - Uuid(uuid::ParseError); - InvalidHex(hex::FromHexError); - Postgres(postgres::error::Error); - RingUnspecified(ring::error::Unspecified); - MigrantLib(migrant_lib::Error); - Xdg(xdg::BaseDirectoriesError); - } - errors { - DoesNotExist(s: String) { - description("Query result does not exist") - display("DoesNotExist Error: {}", s) - } - MultipleRecords(s: String) { - description("Query returned multiple records, expected one") - display("MultipleRecords Error: {}", s) - } - InvalidHashArgs(s: String) { - description("Hash arguments have invalid number of bytes") - display("InvalidHashArgs Error: {}", s) - } - PathRepr(p: std::path::PathBuf) { - description("Unable to convert Path to String") - display("PathRepr Error: Unable to convert Path to String: {:?}", p) - } - BadRequest(s: String) { - description("Bad request") - display("BadRequest: {}", s) - } - UploadTooLarge(s: String) { - description("Upload too large") - display("UploadTooLarge: {}", s) - } - OutOfSpace(s: String) { - description("Out of storage space") - display("OutOfSpace: {}", s) - } - UnequalBytes(s: String) { - description("Unequal bytes") - display("UnequalBytes Error: {}", s) - } - InvalidAuth(s: String) { - description("Invalid auth") - display("InvalidAuth Error: {}", s) - } - InvalidDateTimeMathOffset(s: String) { - description("Invalid DateTime Math") - display("InvalidDateTimeMathOffset Error: {}", s) - } - ConfirmationError(s: String) { - description("Confirmation error") - display("ConfirmationError: {}", s) - } - } -} - -impl Error { - pub fn does_not_exist(&self) -> bool { - match *self.kind() { - ErrorKind::DoesNotExist(_) => true, - _ => false, - } - } -} - diff --git a/src/handlers.rs b/src/handlers.rs index cda241f..bb5e597 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,44 +1,36 @@ /*! Route handlers */ -use std::io::{self, BufRead, Write}; use std::str::FromStr; -use std::path; -use std::fs; -use rouille::{Request, Response}; use hex::FromHex; use uuid::Uuid; use chrono::{Utc, Duration, DateTime}; +use warp; +use futures::{self, Future}; +use tokio; +use hyper; -use db; use auth; use models::{self, CONFIG}; -use {FromRequestBody, FromRequestQuery, ToResponse}; -use errors::*; - - -/// Return a `rouille::Response` for a given file -pub fn serve_file>(mime: &'static str, path: T) -> Result { - let file = fs::File::open(path.as_ref())?; - Ok(Response::from_file(mime, file)) -} +use service::Ctx; +use error; /// Return the default configurable upload constraints -pub fn api_upload_defaults(_: &Request) -> Result { +pub fn api_upload_defaults() -> impl warp::Reply { let defaults = json!({ "upload_limit_bytes": CONFIG.upload_limit_bytes, "upload_lifespan_secs_default": CONFIG.upload_lifespan_secs_default, "download_limit_default": CONFIG.download_limit_default, - }).to_resp()?; - Ok(defaults) + }); + warp::reply::json(&defaults) } /// Upload Initialize post info (in transport formatting) #[derive(Deserialize)] -struct UploadInitPost { +pub struct UploadInitPost { nonce: String, file_name_hash: String, size: u64, @@ -49,10 +41,10 @@ struct UploadInitPost { lifespan: Option, } impl UploadInitPost { - fn decode_hex(&self) -> Result { + fn decode_hex(&self) -> error::Result { let lifespan = Duration::seconds(self.lifespan.unwrap_or(models::CONFIG.upload_lifespan_secs_default)); let expire_date = Utc::now().checked_add_signed(lifespan) - .ok_or_else(|| format_err!(ErrorKind::BadRequest, "Lifespan (seconds) too large"))?; + .ok_or_else(|| "lifespan too large")?; let deletion_password = match self.deletion_password { Some(ref hex) => Some(Vec::from_hex(hex)?), None => None, @@ -84,61 +76,73 @@ struct UploadInit { } - /// Initialize a new upload /// /// Supply all meta-data about an upload. Returning a unique key /// e.g.) /// format!("{}/api/upload?key={}", "http://localhost:3000", "...long-key...") /// -pub fn api_upload_init(request: &Request, pool: &db::Pool) -> Result { - let info = request.parse_json_body::()?; - let info = info.decode_hex() - .map_err(|_| format_err!(ErrorKind::BadRequest, "malformed info"))?; - if info.size > models::CONFIG.upload_limit_bytes { - bail_fmt!(ErrorKind::UploadTooLarge, "Upload too large, max bytes: {}", models::CONFIG.upload_limit_bytes) - } - let uuid = Uuid::new_v4(); - let uuid_hex = hex::encode(uuid.as_bytes()); +pub fn api_upload_init(ctx: Ctx, info: UploadInitPost) -> impl Future { + let info = futures::future::result::(|| -> error::Result { + let info = info.decode_hex() + .map_err(|_| error::helpers::bad_request("malformed info"))?; + if info.size > models::CONFIG.upload_limit_bytes { + return Err( + error::helpers::too_large( + format!("Upload too large, max bytes: {}", models::CONFIG.upload_limit_bytes))); + } + Ok(info) + }()); - { - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); - if ! models::Status::can_fit(&trans, info.size)? { - bail_fmt!(ErrorKind::OutOfSpace, "Server out of storage space"); - } - let access_auth = models::NewAuth::from_pass_bytes(&info.access_password)?.insert(&trans)?; - let deletion_auth = match info.deletion_password { - Some(ref bytes) => { - let auth = models::NewAuth::from_pass_bytes(bytes)?.insert(&trans)?; - Some(auth.id) - } - None => None, - }; - let new_init_upload = models::NewInitUpload { - uuid: uuid, - file_name_hash: info.file_name_hash, - content_hash: info.content_hash, - size: info.size, - nonce: info.nonce, - access_password: access_auth.id, - deletion_password: deletion_auth, - download_limit: info.download_limit, - expire_date: info.expire_date, - }; - new_init_upload.insert(&trans)?; - } + let db = ctx.db; + let cpu = ctx.cpu; + info.and_then(move |info: UploadInit| { + cpu.spawn_fn(move || -> error::Result { + let uuid = Uuid::new_v4(); + let uuid_hex = hex::encode(uuid.as_bytes()); + + let conn = db.get()?; + let trans = conn.transaction()?; + trans.set_commit(); - let resp = json!({"key": &uuid_hex}).to_resp()?; - Ok(resp) + if ! models::Status::can_fit(&trans, info.size)? { + return Err(error::helpers::out_of_space("Server out of storage space")); + } + let access_auth = models::NewAuth::from_pass_bytes(&info.access_password)? + .insert(&trans)?; + let deletion_auth = match info.deletion_password { + Some(ref bytes) => { + let auth = models::NewAuth::from_pass_bytes(bytes)? + .insert(&trans)?; + Some(auth.id) + } + None => None, + }; + let new_init_upload = models::NewInitUpload { + uuid: uuid, + file_name_hash: info.file_name_hash, + content_hash: info.content_hash, + size: info.size, + nonce: info.nonce, + access_password: access_auth.id, + deletion_password: deletion_auth, + download_limit: info.download_limit, + expire_date: info.expire_date, + }; + new_init_upload.insert(&trans)?; + Ok(uuid_hex) + }) + }).map(move |uuid_hex| { + let resp = json!({"key": &uuid_hex}); + warp::reply::json(&resp) + }).map_err(|e| error::helpers::reject(e)) } /// Upload identifier #[derive(Deserialize, Debug)] -struct UploadKey{ +pub struct UploadKey{ key: String, } @@ -149,90 +153,133 @@ struct UploadKey{ /// - Make sure the server has enough space available (using the previously reported file size). /// - Make sure the upload came within the upload time-out /// - While reading the uploaded bytes, keep count and make sure the number of bytes <= state size -pub fn api_upload_file(request: &Request, pool: &db::Pool) -> Result { - let upload_key = request.parse_query_params::()?; - let upload = { +pub fn api_upload_file(ctx: Ctx, upload_key: UploadKey, body: warp::body::BodyStream) -> impl Future { + struct Info { + uuid: Uuid, + now: DateTime, + upload: Option, + } + + let info = futures::future::result::(move || -> error::Result { let now = Utc::now(); let uuid = Uuid::from_str(&upload_key.key) - .map_err(|_| format_err!(ErrorKind::DoesNotExist, "upload not found"))?; - - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); + .map_err(|_| error::helpers::does_not_exist("upload not found"))?; + Ok(Info { + uuid: uuid, + now: now, + upload: None, + }) + }()); + + let db_create = ctx.db.clone(); + let cpu_create = ctx.cpu.clone(); + let db_delete = ctx.db.clone(); + let cpu_delete = ctx.cpu.clone(); + + info.and_then(move |mut info: Info| { + cpu_create.spawn_fn(move || -> error::Result { + let conn = db_create.get()?; + let trans = conn.transaction()?; + trans.set_commit(); + + let init_upload = models::InitUpload::find(&trans, &info.uuid)?; + if ! models::Status::can_fit(&trans, init_upload.size)? { + return Err( + error::helpers::out_of_space("Server out of storage space") + ); + } - let init_upload = models::InitUpload::find(&trans, &uuid)?; - if ! models::Status::can_fit(&trans, init_upload.size)? { - bail_fmt!(ErrorKind::OutOfSpace, "Server out of storage space"); - } - models::Status::inc_upload(&trans, init_upload.size)?; - let file_path = models::Upload::new_file_path(&init_upload.uuid)?; - init_upload.delete(&trans)?; - if ! init_upload.still_valid(&now) { - bail_fmt!(ErrorKind::BadRequest, "Upload request came to late"); - } - let new_upload = init_upload.into_upload(&file_path)?; - let upload = new_upload.insert(&trans)?; - upload - }; - - // In case they lied about the upload size... - // Note: when living behind a proxy, nginx will deal with rejecting - // requests larger than `client_max_body_size` - let mut byte_count = 0; - let mut file = fs::File::create(&upload.file_path)?; - let mut stream = io::BufReader::new(request.data().expect("body already read")); - let stated_upload_size = upload.size as usize; // db stores i64 - loop { - let n = { - let buf = stream.fill_buf()?; - file.write_all(&buf)?; - buf.len() - }; - stream.consume(n); - if n == 0 { break; } - - byte_count += n; - if byte_count > stated_upload_size { - error!("Upload larger than previously stated"); - // delete the entry we just made - { - let conn = pool.get()?; - upload.delete(&*conn)?; + models::Status::inc_upload(&trans, init_upload.size)?; + let file_path = models::Upload::new_file_path(&init_upload.uuid)?; + init_upload.delete(&trans)?; + if ! init_upload.still_valid(&info.now) { + return Err( + error::helpers::bad_request("Upload request came too late") + ); } - // if the file deletion fails, the file will eventually be cleaned up - // by the `admin sweep-files` command - fs::remove_file(&upload.file_path).ok(); - // See if we can drain the rest of the stream and send a real response - // before we kill the connection - let mut over = 0; - loop { - let n = { - let buf = stream.fill_buf()?; - buf.len() - }; - stream.consume(n); - over += n; - if n == 0 || over >= 10_000 { break; } + let new_upload = init_upload.into_upload(&file_path)?; + let upload = new_upload.insert(&trans)?; + info.upload = Some(upload); + Ok(info) + }) + }) + // Convert error to match the next future's unnameable return type. + // The tuple Error is required so the error branch can cleanup oversized uploads + .map_err(|e| (e, None)) + .and_then(move |info: Info| { // -> `impl Future)>` + use warp::Stream; + use warp::Buf; + + let max_bytes = models::CONFIG.upload_limit_bytes as usize; + let upload = info.upload.expect("No upload present"); + + tokio::fs::File::create(upload.file_path.clone()) + .map_err(|e| (error::Error::from(e), None)) + .and_then(move |file| { + body + .map_err(|e| (error::Error::from(e), None)) + .fold((file, 0), move |(file, byte_count), buf| { + futures::future::result::, (error::Error, Option)>({ + let bytes = buf.bytes(); + let size = byte_count + bytes.len(); + if size > max_bytes { + Err((error::helpers::too_large("upload too large"), + Some(upload.clone()))) + } else { + Ok(bytes.to_vec()) + } + }).and_then(move |bytes| { + tokio::io::write_all(file, bytes) + .map(move |(file, bytes_written)| (file, byte_count + bytes_written.len())) + .map_err(|e| (error::Error::from(e), None)) + }) + }).map(|(_file, size)| size) + }) + }).map(move |size| { + let resp = json!({"ok": "ok", "bytes": size}); + warp::reply::json(&resp) + }).or_else(move |(err, maybe_upload)| { + // mark the upload deleted and pass along the upload-file_path to delete + cpu_delete.spawn_fn(move || -> error::Result { + match err.kind() { + error::ErrorKind::UploadTooLarge(_) => { + match maybe_upload { + Some(upload) => { + let conn = db_delete.get()?; + upload.delete(&*conn)?; + return Ok(upload.file_path) + }, + _ => unreachable!("Found UploadTooLarge error, but no Upload"), + } + } + _ => (), } - bail_fmt!(ErrorKind::UploadTooLarge, "Upload larger than previously stated: {}", stated_upload_size) - } - } - - let resp = json!({"ok": "ok"}).to_resp()?; - Ok(resp) + Err(err) + }).and_then(|path| { + // delete the file we just created and then convert this to an error-future + tokio::fs::remove_file(path) + .map_err(|e| error::Error::from(e)) + .and_then(|_| futures::future::err(error::helpers::too_large("upload too large"))) + }) + // this future chain should only consist of errors at this point + .map(|()| unreachable!("Future chain should contain only errors")) + .map_err(|e| error::helpers::reject(e)) + }) } #[derive(Deserialize)] -struct DeleteKeyAccessPost { +pub struct DeleteKeyAccessPost { key: String, deletion_password: String, } impl DeleteKeyAccessPost { - fn decode_hex(&self) -> Result { + fn decode_hex(&self) -> error::Result { Ok(DeleteKeyAccess { - uuid: Uuid::from_str(&self.key).map_err(|_| format_err!(ErrorKind::DoesNotExist, "upload not found"))?, - deletion_password: Vec::from_hex(&self.deletion_password).map_err(|_| format_err!(ErrorKind::BadRequest, "malformed info"))?, + uuid: Uuid::from_str(&self.key) + .map_err(|_| error::helpers::does_not_exist("upload not found"))?, + deletion_password: Vec::from_hex(&self.deletion_password) + .map_err(|_| error::helpers::bad_request("malformed info"))?, }) } } @@ -245,49 +292,65 @@ struct DeleteKeyAccess { /// Deletes an upload by key. Only uploads that were created with a deletion password can be deleted. /// Deletion password must be present. -pub fn api_upload_delete(request: &Request, pool: &db::Pool) -> Result { - let delete_key = request.parse_json_body::()?; - let delete_key = delete_key.decode_hex()?; - { - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); - - let upload = models::Upload::find(&trans, &delete_key.uuid)?; - let deletion_auth = upload.get_deletion_auth(&trans)?; - match deletion_auth { - None => bail_fmt!(ErrorKind::BadRequest, "cannot delete"), - Some(auth) => { - auth.verify(&delete_key.deletion_password)?; - match fs::remove_file(&upload.file_path) { - Ok(_) => (), - Err(e) => error!("Error deleting {}, {}, continuing...", upload.file_path, e), - } - let id = upload.id; - match upload.delete(&trans) { - Ok(_) => { - models::Status::dec_upload(&trans, upload.size)?; +pub fn api_upload_delete(ctx: Ctx, delete_key: DeleteKeyAccessPost) -> impl Future { + let cpu = ctx.cpu; + let db = ctx.db; + futures::future::result::(delete_key.decode_hex()) + .and_then(move |delete_key| { + cpu.spawn_fn(move || -> error::Result { + let conn = db.get()?; + let trans = conn.transaction()?; + trans.set_commit(); + + let upload = models::Upload::find(&trans, &delete_key.uuid)?; + let deletion_auth = upload.get_deletion_auth(&trans)?; + match deletion_auth { + None => Err(error::helpers::bad_request("cannot delete")), + Some(auth) => { + auth.verify(&delete_key.deletion_password)?; + let id = upload.id; + match upload.delete(&trans) { + Ok(_) => { + models::Status::dec_upload(&trans, upload.size)?; + } + Err(e) => { + error!("Error deleting upload with id={}, {}", id, e); + return Err(error::Error::from(e)) + }, + } + Ok(upload.file_path) } - Err(e) => error!("Error deleting upload with id={}, {}, continuing...", id, e), } - } - } - } - Ok(json!({"ok": "ok"}).to_resp()?) + }) + }) + .and_then(|file_path| { + tokio::fs::remove_file(file_path.clone()) + .or_else(move |e| { + error!("Error deleting upload file {}, {} continuing...", file_path, e); + futures::future::ok(()) + }) + }) + .map(|_| { + let resp = json!({"ok": "ok"}); + warp::reply::json(&resp) + }) + .map_err(|e| error::helpers::reject(e)) } /// Download identifier and access/auth password #[derive(Deserialize)] -struct DownloadKeyAccessPost { +pub struct DownloadKeyAccessPost { key: String, access_password: String, } impl DownloadKeyAccessPost { - fn decode_hex(&self) -> Result { + fn decode_hex(&self) -> error::Result { Ok(DownloadKeyAccess{ - uuid: Uuid::from_str(&self.key).map_err(|_| format_err!(ErrorKind::DoesNotExist, "upload not found"))?, - access_password: Vec::from_hex(&self.access_password).map_err(|_| format_err!(ErrorKind::BadRequest, "malformed info"))?, + uuid: Uuid::from_str(&self.key) + .map_err(|_| error::helpers::does_not_exist("upload not found"))?, + access_password: Vec::from_hex(&self.access_password) + .map_err(|_| error::helpers::bad_request("malformed info"))?, }) } } @@ -302,94 +365,130 @@ struct DownloadKeyAccess { /// /// Using a key and access-password, obtain the download meta-data (stuff /// needed for decryption). -pub fn api_download_init(request: &Request, pool: &db::Pool) -> Result { - let now = Utc::now(); - let download_key = request.parse_json_body::()?; - let download_key = download_key.decode_hex()?; - - let (upload, init_download_content, init_download_confirm) = { - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); - - let upload = models::Upload::find(&trans, &download_key.uuid)?; - let access_auth = upload.get_access_auth(&trans)?; - access_auth.verify(&download_key.access_password)?; - let n_downloads = upload.download_count(&trans)? as i32; - if let Some(limit) = upload.download_limit { - if n_downloads >= limit { - bail_fmt!(ErrorKind::DoesNotExist, "upload not found"); +pub fn api_download_init(ctx: Ctx, download_key: DownloadKeyAccessPost) -> impl Future { + struct Info { + now: DateTime, + download_key: DownloadKeyAccess, + } + + struct Data { + upload: models::Upload, + init_download_content: models::InitDownload, + init_download_confirm: models::InitDownload, + } + + let cpu = ctx.cpu; + let db = ctx.db; + futures::future::result::((|| { + let now = Utc::now(); + let download_key = download_key.decode_hex()?; + Ok(Info { now, download_key }) + })()).and_then(move |info: Info| { + cpu.spawn_fn(move || -> error::Result { + let conn = db.get()?; + let trans = conn.transaction()?; + trans.set_commit(); + + let upload = models::Upload::find(&trans, &info.download_key.uuid)?; + let access_auth = upload.get_access_auth(&trans)?; + access_auth.verify(&info.download_key.access_password)?; + let n_downloads = upload.download_count(&trans)? as i32; + if let Some(limit) = upload.download_limit { + if n_downloads >= limit { + return Err(error::helpers::does_not_exist("upload not found")); + } } - } - if now >= upload.expire_date { - bail_fmt!(ErrorKind::DoesNotExist, "upload not found"); - } - let init_download_content = models::NewInitDownload { - uuid: Uuid::new_v4(), - usage: String::from("content"), - upload: upload.id, - }.insert(&trans)?; - let init_download_confirm = models::NewInitDownload { - uuid: Uuid::new_v4(), - usage: String::from("confirm"), - upload: upload.id, - }.insert(&trans)?; - (upload, init_download_content, init_download_confirm) - }; - let resp = json!({ - "nonce": hex::encode(&upload.nonce), - "size": upload.size, - "download_key": hex::encode(init_download_content.uuid.as_bytes()), - "confirm_key": hex::encode(init_download_confirm.uuid.as_bytes()), - }).to_resp()?; - Ok(resp) + if info.now >= upload.expire_date { + return Err(error::helpers::does_not_exist("upload not found")); + } + let init_download_content = models::NewInitDownload { + uuid: Uuid::new_v4(), + usage: String::from("content"), + upload: upload.id, + }.insert(&trans)?; + let init_download_confirm = models::NewInitDownload { + uuid: Uuid::new_v4(), + usage: String::from("confirm"), + upload: upload.id, + }.insert(&trans)?; + Ok(Data { + upload: upload, init_download_content, init_download_confirm + }) + }) + }) + .map(|data| { + let resp = json!({ + "nonce": hex::encode(&data.upload.nonce), + "size": data.upload.size, + "download_key": hex::encode(data.init_download_content.uuid.as_bytes()), + "confirm_key": hex::encode(data.init_download_confirm.uuid.as_bytes()), + }); + warp::reply::json(&resp) + }) + .map_err(|e| error::helpers::reject(e)) } /// Download encrypted bytes -pub fn api_download(request: &Request, pool: &db::Pool) -> Result { - let now = Utc::now(); - let download_key = request.parse_json_body::()?; - let download_key = download_key.decode_hex()?; - let upload = { - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); - - let init_download = models::InitDownload::find(&trans, &download_key.uuid, models::DownloadType::Content)?; - let upload = init_download.get_upload(&trans)?; - let access_auth = upload.get_access_auth(&trans)?; - access_auth.verify(&download_key.access_password)?; - let n_downloads = upload.download_count(&trans)? as i32; - if let Some(limit) = upload.download_limit { - if n_downloads >= limit { - bail_fmt!(ErrorKind::DoesNotExist, "upload not found"); - } - } - if now >= upload.expire_date { - bail_fmt!(ErrorKind::DoesNotExist, "upload not found"); - } - let new_download = models::NewDownload { upload: upload.id }; - new_download.insert(&trans)?; - init_download.delete(&trans)?; - upload - }; - if request.header("x-proxy-nginx").unwrap_or("") == "true" { - let upload_path = format!("/private/{}", hex::encode(upload.uuid.as_bytes())); - let resp = Response::empty_400() - .with_status_code(200) - .with_additional_header("x-accel-redirect", upload_path) - .with_additional_header("content-type", "application/octet-stream"); - Ok(resp) - } else { - serve_file("application/octet-stream", upload.file_path) +pub fn api_download(ctx: Ctx, download_key: DownloadKeyAccessPost) -> impl Future { + struct Info { + now: DateTime, + download_key: DownloadKeyAccess, } + + let cpu = ctx.cpu; + let db = ctx.db; + let fs_pool = ctx.fs; + futures::future::result::((|| { + let now = Utc::now(); + let download_key = download_key.decode_hex()?; + Ok(Info { now, download_key }) + })()).and_then(move |info: Info| { + cpu.spawn_fn(move || -> error::Result { + let conn = db.get()?; + let trans = conn.transaction()?; + trans.set_commit(); + + let init_download = models::InitDownload::find(&trans, &info.download_key.uuid, models::DownloadType::Content)?; + let upload = init_download.get_upload(&trans)?; + let access_auth = upload.get_access_auth(&trans)?; + access_auth.verify(&info.download_key.access_password)?; + let n_downloads = upload.download_count(&trans)? as i32; + if let Some(limit) = upload.download_limit { + if n_downloads >= limit { + return Err(error::helpers::does_not_exist("upload not found")) + } + } + if info.now >= upload.expire_date { + return Err(error::helpers::does_not_exist("upload not found")) + } + let new_download = models::NewDownload { upload: upload.id }; + new_download.insert(&trans)?; + init_download.delete(&trans)?; + Ok(upload) + }) + }) + .map(move |upload| { + let stream = fs_pool.read(upload.file_path, Default::default()); + let body = hyper::Body::wrap_stream(stream); + warp::http::Response::builder() + .body(body) + }) + .map_err(|e| error::helpers::reject(e)) + // if request.header("x-proxy-nginx").unwrap_or("") == "true" { + // let upload_path = format!("/private/{}", hex::encode(upload.uuid.as_bytes())); + // let resp = Response::empty_400() + // .with_status_code(200) + // .with_additional_header("x-accel-redirect", upload_path) + // .with_additional_header("content-type", "application/octet-stream"); + // Ok(resp) + // } } /// Download identifier and corresponding decrypted content hash #[derive(Deserialize)] -struct DownloadKeyHash { +pub struct DownloadKeyHash { key: String, hash: String, } @@ -398,24 +497,36 @@ struct DownloadKeyHash { /// Obtain the decrypted file's name /// /// Upload identifier and a matching hash of the decrypted content are required -pub fn api_download_confirm(request: &Request, pool: &db::Pool) -> Result { - let download_key = request.parse_json_body::()?; - let hash_bytes = Vec::from_hex(&download_key.hash) - .map_err(|_| format_err!(ErrorKind::BadRequest, "malformed info"))?; - let uuid_bytes = Vec::from_hex(&download_key.key)?; - let uuid = Uuid::from_bytes(&uuid_bytes) - .map_err(|_| format_err!(ErrorKind::DoesNotExist, "upload not found"))?; - let upload = { - let conn = pool.get()?; - let trans = conn.transaction()?; - trans.set_commit(); - - let init_download = models::InitDownload::find(&*conn, &uuid, models::DownloadType::Confirm)?; - let upload = init_download.get_upload(&trans)?; - auth::eq(&hash_bytes, &upload.content_hash)?; - init_download.delete(&trans)?; - upload - }; - Ok(json!({"file_name_hash": hex::encode(&upload.file_name_hash)}).to_resp()?) +pub fn api_download_confirm(ctx: Ctx, download_key: DownloadKeyHash) -> impl Future { + struct Info { + hash_bytes: Vec, + uuid: Uuid, + } + + let cpu = ctx.cpu; + let db = ctx.db; + futures::future::result::((|| { + let hash_bytes = Vec::from_hex(&download_key.hash) + .map_err(|_| error::helpers::bad_request("malformed info"))?; + let uuid_bytes = Vec::from_hex(&download_key.key)?; + let uuid = Uuid::from_bytes(&uuid_bytes) + .map_err(|_| error::helpers::does_not_exist("upload not found"))?; + Ok(Info { hash_bytes, uuid }) + })()).and_then(move |info| { + cpu.spawn_fn(move || -> error::Result { + let conn = db.get()?; + let trans = conn.transaction()?; + trans.set_commit(); + + let init_download = models::InitDownload::find(&*conn, &info.uuid, models::DownloadType::Confirm)?; + let upload = init_download.get_upload(&trans)?; + auth::eq(&info.hash_bytes, &upload.content_hash)?; + init_download.delete(&trans)?; + Ok(upload) + }) + }).map(|upload| { + let resp = json!({"file_name_hash": hex::encode(&upload.file_name_hash)}); + warp::reply::json(&resp) + }).map_err(|e| error::helpers::reject(e)) } diff --git a/src/lib.rs b/src/lib.rs index 67acd2b..4d8c94a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![recursion_limit = "1024"] -#[macro_use] extern crate error_chain; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; extern crate env_logger; @@ -18,8 +17,14 @@ extern crate serde; #[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_json; extern crate serde_urlencoded; -#[macro_use] extern crate rouille; extern crate xdg; +extern crate warp; +extern crate futures; +extern crate futures_cpupool; +extern crate futures_fs; +extern crate num_cpus; +extern crate tokio; +extern crate hyper; #[macro_use] pub mod macros; pub mod service; @@ -28,12 +33,11 @@ pub mod handlers; pub mod db; pub mod models; pub mod auth; -pub mod errors; +pub mod error; pub mod admin; -use std::io::Read; -use errors::*; +use error::{Result}; pub use models::CONFIG; pub static APPNAME: &'static str = "Transfer"; @@ -44,86 +48,3 @@ pub fn config_dir() -> Result { let config_dir = xdg_dirs.create_config_directory("")?; Ok(config_dir) } - - -// ------------------------------------------------ -// Traits for augmenting `rouille` -// ------------------------------------------------ - -/// Trait for parsing `json` from `rouille::Request` bodies into some type `T` -/// -/// # Example -/// -/// ```rust,ignore -/// #[derive(Deserialize)] -/// struct PostData { -/// name: String, -/// age: u32, -/// } -///``` -/// -/// For a request with a body containing `json` -/// -/// ```rust,ignore -/// let post_data = request.parse_json_body::()?; -/// println!("{}", post_data.name); -/// ``` -pub trait FromRequestBody { - fn parse_json_body(&self) -> Result; -} - -impl FromRequestBody for rouille::Request { - fn parse_json_body(&self) -> Result { - let mut body = self.data().expect("Can't read request body twice"); - let mut s = String::new(); - body.read_to_string(&mut s)?; - let data = serde_json::from_str::(&s) - .map_err(|_| format_err!(ErrorKind::BadRequest, "malformed data"))?; - Ok(data) - } -} - - -/// Trait for parsing query string parameters from `rouille::Request` urls into some type `T` -/// -/// # Example -/// -/// ```rust,ignore -/// #[derive(Deserialize)] -/// struct PostData { -/// name: String, -/// age: u32, -/// } -///``` -/// -/// For a request with url query parameters -/// -/// ```rust,ignore -/// let param_data = request.parse_query_params::()?; -/// println!("{}", post_data.name); -/// ``` -pub trait FromRequestQuery { - fn parse_query_params(&self) -> Result; -} -impl FromRequestQuery for rouille::Request { - fn parse_query_params(&self) -> Result { - let qs = self.raw_query_string(); - let params = serde_urlencoded::from_str::(qs) - .map_err(|_| format_err!(ErrorKind::BadRequest, "malformed data"))?; - Ok(params) - } -} - - -/// Trait for constructing `rouille::Response`s from other types -pub trait ToResponse { - fn to_resp(&self) -> Result; -} -impl ToResponse for serde_json::Value { - fn to_resp(&self) -> Result { - let s = serde_json::to_string(self)?; - let resp = rouille::Response::from_data("application/json", s.as_bytes()); - Ok(resp) - } -} - diff --git a/src/macros.rs b/src/macros.rs index 0dad660..f2c933c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -2,37 +2,9 @@ Macros For working with - - `error_chain` - `postgres` */ - -// ------------- -// error-chain -// ------------- - -/// Helper for formatting Errors that wrap strings -macro_rules! format_err { - ($error:expr, $str:expr) => { - $error(format!($str)) - }; - ($error:expr, $str:expr, $($arg:expr),*) => { - $error(format!($str, $($arg),*)) - } -} - - -/// Helper for formatting strings with error-chain's `bail!` macro -macro_rules! bail_fmt { - ($error:expr, $str:expr) => { - bail!(format_err!($error, $str)) - }; - ($error:expr, $str:expr, $($arg:expr),*) => { - bail!(format_err!($error, $str, $($arg),*)) - } -} - - // ------------- // postgres // ------------- @@ -83,17 +55,23 @@ macro_rules! try_query_to_model { $var : $arg, )* }), - None => bail_fmt!(ErrorKind::DoesNotExist, "{} not found", $model::table_name()), + None => + return Err( + error::helpers::does_not_exist( + format!("{} not found", $model::table_name()) + ) + ) } } Err(e) => { - Err(Error::from(e)) + Err(error::Error::from(e)) } } } } + /// Convert all rows returned into the associated model type /// and collect them in a `Vec` /// @@ -143,17 +121,23 @@ macro_rules! try_query_one { ($query:expr, $model:ident) => { match $query { Err(e) => { - Err(Error::from(e)) + Err(error::Error::from(e)) } Ok(rows) => { let mut rows = rows.iter(); let record = match rows.next() { - None => bail_fmt!(ErrorKind::DoesNotExist, "{} not found", $model::table_name()), + None => return Err( + error::helpers::does_not_exist(format!("{} not found", $model::table_name()))), Some(row) => Ok($model::from_row(row)), }; match rows.next() { None => record, - Some(_) => bail_fmt!(ErrorKind::MultipleRecords, "Multiple rows returned from table: {}, expected one", $model::table_name()), + Some(_) => return Err( + error::helpers::multiple_records( + format!("Multiple rows returned from table: {}, expected one", + $model::table_name()) + ) + ) } } } @@ -180,7 +164,7 @@ macro_rules! try_query_aggregate { } Ok(rows) => { match rows.iter().next() { - None => bail_fmt!(ErrorKind::DoesNotExist, "Record not found"), + None => Err(error::helpers::does_not_exist("Record not found")), Some(row) => { let val: $row_type = row.get(0); Ok(val) diff --git a/src/main.rs b/src/main.rs index a06fb60..78105f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ #![recursion_limit = "1024"] -#[macro_use] extern crate error_chain; #[macro_use] extern crate clap; extern crate migrant_lib; extern crate transfer; @@ -9,16 +8,17 @@ use migrant_lib::Config; use migrant_lib::config::PostgresSettingsBuilder; use std::env; -error_chain! { - foreign_links { - Io(std::io::Error); - Migrant(migrant_lib::Error); - Transfer(transfer::errors::Error); - } -} + +type Error = Box; +type Result = std::result::Result; -quick_main!(run); +pub fn main() { + if let Err(e) = run() { + eprintln!("Error: {}", e); + std::process::exit(1); + } +} fn run() -> Result<()> { @@ -65,8 +65,8 @@ fn run() -> Result<()> { let port = serve_matches.value_of("port") .expect("default port should be set by clap") .parse::() - .chain_err(|| "`--port` expects an integer")?; - let host = if serve_matches.is_present("public") { "0.0.0.0" } else { "localhost" }; + .map_err(|_| "`--port` expects an integer")?; + let host = if serve_matches.is_present("public") { "0.0.0.0" } else { "127.0.0.1" }; transfer::service::start(&host, port)?; } _ => { @@ -98,7 +98,7 @@ pub fn admin(matches: &ArgMatches) -> Result<()> { .migration_location(proj_dir.join("migrations"))?) .initialize()?; match migrant_lib::search_for_settings_file(&config_dir) { - None => bail!("Unable to find `Migrant.toml` even though it was just saved."), + None => Err("Unable to find `Migrant.toml` even though it was just saved.")?, Some(p) => p, } } diff --git a/src/models.rs b/src/models.rs index 4625272..d30f611 100644 --- a/src/models.rs +++ b/src/models.rs @@ -11,7 +11,7 @@ use uuid::Uuid; use ron; use auth; -use errors::*; +use error::{self, Result, Error}; use {config_dir}; @@ -66,7 +66,7 @@ pub struct NewAuth { pub hash: Vec, } impl NewAuth { - pub fn from_pass_bytes(pass: &[u8]) -> Result { + pub fn from_pass_bytes(pass: &[u8]) -> error::Result { let salt = auth::new_salt()?; let sha = auth::sha256(pass); let hash = auth::bcrypt_hash(&sha, &salt)?; @@ -75,7 +75,7 @@ impl NewAuth { }) } - pub fn insert(self, conn: &T) -> Result { + pub fn insert(self, conn: &T) -> error::Result { let stmt = "insert into auth (salt, hash) values ($1, $2) \ returning id, date_created"; try_query_to_model!(conn.query(stmt, &[&self.salt, &self.hash]); @@ -116,11 +116,11 @@ impl Auth { /// Try verifying the current `auth` record against a set of bytes, returning /// `Ok` if verification passes or `ErrorKind::InvalidAuth` - pub fn verify(&self, other_pass_bytes: &[u8]) -> Result<()> { + pub fn verify(&self, other_pass_bytes: &[u8]) -> error::Result<()> { let other_sha = auth::sha256(other_pass_bytes); let other_hash = auth::bcrypt_hash(&other_sha, &self.salt)?; auth::eq(&self.hash, &other_hash) - .map_err(|_| format_err!(ErrorKind::InvalidAuth, "Invalid authentication"))?; + .map_err(|_| error::helpers::invalid_auth("Invalid authentication"))?; Ok(()) } } @@ -139,7 +139,7 @@ pub struct NewInitUpload { pub expire_date: DateTime, } impl NewInitUpload { - pub fn insert(self, conn: &T) -> Result { + pub fn insert(self, conn: &T) -> error::Result { let stmt = "insert into init_upload \ (uuid_, file_name_hash, content_hash, size_, nonce, access_password, deletion_password, download_limit, expire_date) \ values ($1, $2, $3, $4, $5, $6, $7, $8, $9) \ @@ -216,7 +216,7 @@ impl InitUpload { .map(str::to_string) .ok_or_else(|| { let pb = Path::to_owned(file_path.as_ref()); - ErrorKind::PathRepr(pb) + error::helpers::internal(format!("invalid path: {:?}", pb)) })?; Ok(NewUpload { uuid: self.uuid, @@ -243,8 +243,10 @@ impl InitUpload { let timeout = Duration::seconds(CONFIG.upload_timeout_secs); let now = Utc::now(); let cutoff = now.checked_sub_signed(timeout) - .ok_or_else(|| format_err!(ErrorKind::InvalidDateTimeMathOffset, "Error subtracting {} secs from {:?}", - CONFIG.upload_timeout_secs, now))?; + .ok_or_else(|| error::helpers::internal( + format!("Error subtracting {} secs from {:?}", + CONFIG.upload_timeout_secs, now) + ))?; try_query_aggregate!(conn.query(stmt, &[&cutoff]), i64) } } @@ -282,6 +284,7 @@ impl NewUpload { /// Maps to db table `upload` +#[derive(Clone)] pub struct Upload { pub id: i32, pub uuid: Uuid, @@ -477,8 +480,10 @@ impl InitDownload { let timeout = Duration::seconds(CONFIG.download_timeout_secs); let now = Utc::now(); let cutoff = now.checked_sub_signed(timeout) - .ok_or_else(|| format_err!(ErrorKind::InvalidDateTimeMathOffset, "Error subtracting {} secs from {:?}", - CONFIG.download_timeout_secs, now))?; + .ok_or_else(|| error::helpers::internal( + format!("Error subtracting {} secs from {:?}", + CONFIG.download_timeout_secs, now) + ))?; try_query_aggregate!(conn.query(stmt, &[&cutoff]), i64) } } @@ -547,14 +552,14 @@ impl Status { let trans = conn.transaction()?; let status = Self::load(&trans); let status = match status { - Err(ref e) if e.does_not_exist() => Self::init(&trans), + Err(ref e) if e.is_does_not_exist() => Self::init(&trans), status => status, }; trans.commit()?; status } - pub fn load(conn: &T) -> Result { + pub fn load(conn: &T) -> error::Result { let stmt = "select id, upload_count, total_bytes, date_modified from status"; try_query_one!(conn.query(stmt, &[]), Status) } @@ -571,7 +576,7 @@ impl Status { } /// Check if we can hold `n` more bytes, staying under `CONFIG.max_combined_upload_bytes` - pub fn can_fit(conn: &T, n_bytes: i64) -> Result { + pub fn can_fit(conn: &T, n_bytes: i64) -> error::Result { let status = Self::load(conn)?; Ok((status.total_bytes + n_bytes) < CONFIG.max_combined_upload_bytes) } diff --git a/src/service.rs b/src/service.rs index 55c5c81..d0b1d99 100644 --- a/src/service.rs +++ b/src/service.rs @@ -2,19 +2,30 @@ Service initialization */ use std::thread; -use std::time; use std::io::Write; use env_logger; use chrono::Local; -use rouille; +use warp::{self, Filter}; +use warp::http::StatusCode; +use num_cpus; +use futures_cpupool::CpuPool; +use futures_fs::FsPool; use handlers; use sweep; use db; use models; -use {ToResponse}; -use errors::*; +use error::{self, Result}; +use std::net::SocketAddr; + + +#[derive(Clone)] +pub struct Ctx { + pub cpu: CpuPool, + pub db: db::Pool, + pub fs: FsPool, +} /// Initialize the `status` database table if it doesn't already exist @@ -37,13 +48,13 @@ pub fn start(host: &str, port: u16) -> Result<()> { // e.g. LOG=info chatbot serve let mut logger = env_logger::Builder::from_env("LOG"); logger.format(|buf, record| { - writeln!(buf, "{} [{}] - [{}] -> {}", - Local::now().format("%Y-%m-%d_%H:%M:%S"), - record.level(), - record.target(), - record.args() - ) - }) + writeln!(buf, "{} [{}] - [{}] -> {}", + Local::now().format("%Y-%m-%d_%H:%M:%S"), + record.level(), + record.target(), + record.args() + ) + }) .init(); // force a config load @@ -55,98 +66,191 @@ pub fn start(host: &str, port: u16) -> Result<()> { // spawn our cleaning thread let _ = thread::spawn(sweep::db_sweeper); - let db_pool = db::init_pool(); - - let addr = format!("{}:{}", host, port); - info!("** Listening on {} **", addr); - - rouille::start_server(&addr, move |request| { - let db_pool = db_pool.clone(); - - let now = Local::now().format("%Y-%m-%d %H:%M%S"); - let log_ok = |req: &rouille::Request, resp: &rouille::Response, elap: time::Duration| { - let ms = (elap.as_secs() * 1_000) as f32 + (elap.subsec_nanos() as f32 / 1_000_000.); - info!("[{}] {} {} -> {} ({}ms)", now, req.method(), req.raw_url(), resp.status_code, ms) - }; - let log_err = |req: &rouille::Request, elap: time::Duration| { - let ms = (elap.as_secs() * 1_000) as f32 + (elap.subsec_nanos() as f32 / 1_000_000.); - info!("[{}] Handler Panicked: {} {} ({}ms)", now, req.method(), req.raw_url(), ms) - }; - // dispatch and handle errors - rouille::log_custom(request, log_ok, log_err, move || { - // dispatch and handle errors - match route_request(request, db_pool) { - Ok(resp) => resp, - Err(e) => { - use self::ErrorKind::*; - error!("Handler Error: {}", e); - match e.kind() { - BadRequest(ref s) => { - // bad request - let body = json!({"error": s}); - body.to_resp().unwrap().with_status_code(400) - } - InvalidAuth(ref s) => { - // unauthorized - let body = json!({"error": s}); - body.to_resp().unwrap().with_status_code(401) - } - DoesNotExist(ref s) => { - // not found - let body = json!({"error": s}); - body.to_resp().unwrap().with_status_code(404) - } - UploadTooLarge(ref s) => { - // payload too large / request entity to large - let body = json!({"error": s}); - body.to_resp().unwrap().with_status_code(413) - } - OutOfSpace(ref s) => { - // service unavailable - let body = json!({"error": s}); - body.to_resp().unwrap().with_status_code(503) - } - _ => rouille::Response::text("Something went wrong").with_status_code(500), - } - } - } - }) - }); + let cpus = num_cpus::get(); + let db_pool = db::init_pool(cpus as u32); + let cpu_pool = CpuPool::new(cpus * 2); + let fs_pool = FsPool::new(cpus); + let ctx = Ctx { cpu: cpu_pool, db: db_pool, fs: fs_pool }; + + let addr = format!("{}:{}", host, port).parse::()?; + route_and_serve(addr, ctx); + Ok(()) } -/// Route the request to appropriate handler -fn route_request(request: &rouille::Request, db_pool: db::Pool) -> Result { - Ok(router!(request, - (GET) (/) => { - handlers::serve_file("text/html", "assets/main.html")? - }, +fn route_and_serve(addr: SocketAddr, ctx: Ctx) { + // `/api` + let api_root = warp::path("api"); - (GET) (/status) => { - json!({"status": "ok", "version": env!("CARGO_PKG_VERSION")}).to_resp()? - }, + // `/api/upload` + let api_upload = api_root.and(warp::path("upload")); + + // `/api/download` + let api_download = api_root.and(warp::path("download")); + + let with_ctx = warp::any().map(move || ctx.clone()); + let with_body_stream = warp::body::content_length_limit(models::CONFIG.upload_limit_bytes as u64) + .and(warp::body::stream()); + let with_body_limit = warp::body::content_length_limit(1_000_000); + + // `/` + let index = warp::get2() + .and(warp::path::end()) + .and(warp::fs::file("assets/main.html")); + + // `/status` + let status = warp::get2() + .and(warp::path("status").and(warp::path::end())) + .map(|| { + let body = json!({"status": "ok", "version": env!("CARGO_PKG_VERSION")}); + warp::reply::json(&body) + }); + + // `/api/hello` + let api_hello = warp::get2() + .and(api_root) + .and(warp::path("hello")) + .and(warp::path::end()) + .map(|| warp::reply::json(&json!({"message": "hello!"}))); + + // `/api/upload/defaults` + let api_defaults = warp::get2() + .and(api_upload) + .and(warp::path("defaults")) + .and(warp::path::end()) + .map(handlers::api_upload_defaults); + + let api_upload_init = warp::post2() + .and(api_upload) + .and(warp::path("init")) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(with_body_limit) + .and(warp::body::json()) + .and_then(handlers::api_upload_init); + + let api_upload_file = warp::post2() + .and(api_upload) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(warp::query()) + .and(with_body_stream) + .and_then(handlers::api_upload_file); + + let api_upload_delete = warp::post2() + .and(api_upload) + .and(warp::path("delete")) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(with_body_limit) + .and(warp::body::json()) + .and_then(handlers::api_upload_delete); - (GET) (/api/hello) => { json!({"message": "hey!"}).to_resp()? }, - (POST) (/api/bye) => { json!({"message": "bye!"}).to_resp()? }, - - (GET) (/api/upload/defaults) => { handlers::api_upload_defaults(request)? }, - (POST) (/api/upload/init) => { handlers::api_upload_init(request, &db_pool)? }, - (POST) (/api/upload) => { handlers::api_upload_file(request, &db_pool)? }, - (POST) (/api/upload/delete) => { handlers::api_upload_delete(request, &db_pool)? }, - - (POST) (/api/download/init) => { handlers::api_download_init(request, &db_pool)? }, - (POST) (/api/download) => { handlers::api_download(request, &db_pool)? }, - (POST) (/api/download/confirm) => { handlers::api_download_confirm(request, &db_pool)? }, - - _ => { - // static files - let static_resp = rouille::match_assets(&request, "assets"); - if static_resp.is_success() { - static_resp - } else { - bail_fmt!(ErrorKind::DoesNotExist, "nothing here") - } + let api_download_init = warp::post2() + .and(api_download) + .and(warp::path("init")) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(with_body_limit) + .and(warp::body::json()) + .and_then(handlers::api_download_init); + + let api_download_file = warp::post2() + .and(api_download) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(with_body_limit) + .and(warp::body::json()) + .and_then(handlers::api_download); + + let api_download_confirm = warp::post2() + .and(api_download) + .and(warp::path("confirm")) + .and(warp::path::end()) + .and(with_ctx.clone()) + .and(with_body_limit) + .and(warp::body::json()) + .and_then(handlers::api_download_confirm); + + // match everything else as a static file + let static_file = warp::get2() + .and(warp::fs::dir("assets")); + + let api = index + .or(status) + .or(api_hello) + .or(api_defaults) + .or(api_upload_init) + .or(api_upload_file) + .or(api_upload_delete) + .or(api_download_init) + .or(api_download_file) + .or(api_download_confirm) + .or(static_file); + + let routes = api + .with(warp::log("transfer")) + .recover(handle_error); + + warp::serve(routes) + .run(addr); +} + + +fn handle_error(err: warp::Rejection) -> std::result::Result { + { + let inner = err.find_cause::(); + if inner.is_some() { + let inner = inner.unwrap(); + use error::ErrorKind::*; + type S = StatusCode; + error!("Handler error: {}", inner); + return Ok(match inner.kind() { + BadRequest(ref s) => { + // 400 + let body = json!({"error": s}); + warp::reply::with_status(warp::reply::json(&body), S::BAD_REQUEST) + } + InvalidAuth(ref s) => { + // 401 + let body = json!({"error": s}); + warp::reply::with_status(warp::reply::json(&body), S::UNAUTHORIZED) + } + DoesNotExist(ref s) => { + // 404 + let body = json!({"error": s}); + warp::reply::with_status(warp::reply::json(&body), S::NOT_FOUND) + } + UploadTooLarge(ref s) => { + // 413 + let body = json!({"error": s}); + warp::reply::with_status(warp::reply::json(&body), S::PAYLOAD_TOO_LARGE) + } + OutOfSpace(ref s) => { + // 503 + let body = json!({"error": s}); + warp::reply::with_status(warp::reply::json(&body), S::SERVICE_UNAVAILABLE) + } + _ => { + // 500 + let body = json!({"error": "something went wrong"}); + warp::reply::with_status(warp::reply::json(&body), S::INTERNAL_SERVER_ERROR) + }, + }) } - )) + } + + error!("Handler error: {:?}", err.cause()); + match err.status() { + StatusCode::NOT_FOUND | StatusCode::METHOD_NOT_ALLOWED => { + Ok(warp::reply::with_status(warp::reply::json(&json!({"error": "not found"})), StatusCode::NOT_FOUND)) + }, + StatusCode::INTERNAL_SERVER_ERROR => { + Ok(warp::reply::with_status(warp::reply::json(&json!({"error": "internal error"})), StatusCode::INTERNAL_SERVER_ERROR)) + }, + _ => Err(err), + } } + + diff --git a/src/sweep.rs b/src/sweep.rs index 26f5a7c..4831dc4 100644 --- a/src/sweep.rs +++ b/src/sweep.rs @@ -11,7 +11,7 @@ use uuid::Uuid; use db; use models; -use errors::*; +use error::Result; /// Cleanup `init_upload` table, deleting expired items