New version of jsonrpc.

This commit is contained in:
Tomasz Drwięga 2017-03-13 15:49:52 +01:00
parent be87151f1c
commit 8bf5be0cc4
No known key found for this signature in database
GPG Key ID: D066F497E62CAF66
28 changed files with 469 additions and 480 deletions

132
Cargo.lock generated
View File

@ -29,7 +29,7 @@ dependencies = [
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -447,8 +447,9 @@ dependencies = [
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-http-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -621,10 +622,10 @@ dependencies = [
"ethsync 1.7.0", "ethsync 1.7.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-http-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-ipc-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-ipc-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-macros 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-macros 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
@ -667,7 +668,8 @@ dependencies = [
"ethcore-io 1.7.0", "ethcore-io 1.7.0",
"ethcore-rpc 1.7.0", "ethcore-rpc 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-ui 1.7.0", "parity-ui 1.7.0",
@ -687,9 +689,9 @@ dependencies = [
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-macros 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-macros 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-tcp-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-tcp-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
@ -1083,38 +1085,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "jsonrpc-core" name = "jsonrpc-core"
version = "6.0.0" version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#86d7a89c85f324b5f6671315d9b71010ca995300" source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [ dependencies = [
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "jsonrpc-http-server" name = "jsonrpc-http-server"
version = "6.0.0" version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#86d7a89c85f324b5f6671315d9b71010ca995300" source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [ dependencies = [
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "jsonrpc-ipc-server" name = "jsonrpc-ipc-server"
version = "6.0.0" version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#86d7a89c85f324b5f6671315d9b71010ca995300" source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [ dependencies = [
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1124,26 +1125,44 @@ dependencies = [
[[package]] [[package]]
name = "jsonrpc-macros" name = "jsonrpc-macros"
version = "6.0.0" version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#86d7a89c85f324b5f6671315d9b71010ca995300" source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [ dependencies = [
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "jsonrpc-tcp-server" name = "jsonrpc-pubsub"
version = "6.0.0" version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#86d7a89c85f324b5f6671315d9b71010ca995300" source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [ dependencies = [
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-server-utils"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-tcp-server"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#b36a57c4bf449c431dc59f0e88236026eda62ea7"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1640,7 +1659,7 @@ dependencies = [
"ethcore 1.7.0", "ethcore 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"jsonrpc-http-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
@ -1677,7 +1696,7 @@ dependencies = [
"ethcore-signer 1.7.0", "ethcore-signer 1.7.0",
"ethcore-util 1.7.0", "ethcore-util 1.7.0",
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2198,11 +2217,6 @@ name = "smallvec"
version = "0.1.8" version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "0.3.1" version = "0.3.1"
@ -2273,11 +2287,6 @@ dependencies = [
name = "table" name = "table"
version = "0.1.0" version = "0.1.0"
[[package]]
name = "take"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "target_info" name = "target_info"
version = "0.1.0" version = "0.1.0"
@ -2352,22 +2361,6 @@ dependencies = [
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "tokio-proto"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "tokio-service" name = "tokio-service"
version = "0.1.0" version = "0.1.0"
@ -2626,11 +2619,13 @@ dependencies = [
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
"checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a" "checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a"
"checksum itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5" "checksum itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5"
"checksum jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-http-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-ipc-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-ipc-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-macros 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-macros 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-tcp-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>" "checksum jsonrpc-pubsub 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-tcp-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
@ -2737,7 +2732,6 @@ dependencies = [
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" "checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410" "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
"checksum smallvec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3c84984c278afe61a46e19868e8b23e2ee3be5b3cc6dea6edad4893bc6c841" "checksum smallvec 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3c84984c278afe61a46e19868e8b23e2ee3be5b3cc6dea6edad4893bc6c841"
"checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2" "checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2"
"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf" "checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf"
@ -2746,7 +2740,6 @@ dependencies = [
"checksum syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f94368aae82bb29656c98443a7026ca931a659e8d19dcdc41d6e273054e820" "checksum syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f94368aae82bb29656c98443a7026ca931a659e8d19dcdc41d6e273054e820"
"checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af" "checksum syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393b6dd0889df2b064beeea954cfda6bc2571604ac460deeae0fed55a53988af"
"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e" "checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e"
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
"checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281"
@ -2756,7 +2749,6 @@ dependencies = [
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
"checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270" "checksum tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aef43048292ca0bae4ab32180e85f6202cf2816c2a210c396a84b99dab9270"
"checksum tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "52416b3e937abac22a543a7f1c66bd37feb60137ff1ab42390fa02df85347e58" "checksum tokio-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "52416b3e937abac22a543a7f1c66bd37feb60137ff1ab42390fa02df85347e58"
"checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808"
"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6" "checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6"
"checksum toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442dfc13508e603c3f763274361db7f79d7469a0e95c411cde53662ab30fc72" "checksum toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442dfc13508e603c3f763274361db7f79d7469a0e95c411cde53662ab30fc72"

View File

@ -8,33 +8,37 @@ authors = ["Parity Technologies <admin@parity.io>"]
[lib] [lib]
[dependencies] [dependencies]
rand = "0.3" base32 = "0.3"
log = "0.3"
env_logger = "0.3" env_logger = "0.3"
futures = "0.1" futures = "0.1"
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
unicase = "1.3"
url = "1.0"
rustc-serialize = "0.3"
serde = "0.9"
serde_json = "0.9"
serde_derive = "0.9"
linked-hash-map = "0.3" linked-hash-map = "0.3"
parity-dapps-glue = "1.4" log = "0.3"
base32 = "0.3"
mime = "0.2" mime = "0.2"
mime_guess = "1.6.1" mime_guess = "1.6.1"
rand = "0.3"
rustc-serialize = "0.3"
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9"
time = "0.1.35" time = "0.1.35"
unicase = "1.3"
url = "1.0"
zip = { version = "0.1", default-features = false } zip = { version = "0.1", default-features = false }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
# TODO [ToDr] Temporary solution, server should be merged with RPC.
jsonrpc-server-utils = { git = "https://github.com/ethcore/jsonrpc.git" }
ethcore-devtools = { path = "../devtools" } ethcore-devtools = { path = "../devtools" }
ethcore-rpc = { path = "../rpc" } ethcore-rpc = { path = "../rpc" }
ethcore-util = { path = "../util" } ethcore-util = { path = "../util" }
fetch = { path = "../util/fetch" } fetch = { path = "../util/fetch" }
parity-ui = { path = "./ui" } parity-dapps-glue = "1.4"
parity-hash-fetch = { path = "../hash-fetch" } parity-hash-fetch = { path = "../hash-fetch" }
parity-reactor = { path = "../util/reactor" } parity-reactor = { path = "../util/reactor" }
parity-ui = { path = "./ui" }
clippy = { version = "0.0.103", optional = true} clippy = { version = "0.0.103", optional = true}

View File

@ -19,7 +19,6 @@ use unicase::UniCase;
use hyper::{server, net, Decoder, Encoder, Next, Control}; use hyper::{server, net, Decoder, Encoder, Next, Control};
use hyper::header; use hyper::header;
use hyper::method::Method; use hyper::method::Method;
use hyper::header::AccessControlAllowOrigin;
use api::types::{App, ApiError}; use api::types::{App, ApiError};
use api::response; use api::response;
@ -27,23 +26,20 @@ use apps::fetcher::Fetcher;
use handlers::extract_url; use handlers::extract_url;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath}; use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
use jsonrpc_http_server::cors; use jsonrpc_http_server;
use jsonrpc_server_utils::cors;
#[derive(Clone)] #[derive(Clone)]
pub struct RestApi { pub struct RestApi {
cors_domains: Option<Vec<AccessControlAllowOrigin>>, cors_domains: Option<Vec<cors::AccessControlAllowOrigin>>,
endpoints: Arc<Endpoints>, endpoints: Arc<Endpoints>,
fetcher: Arc<Fetcher>, fetcher: Arc<Fetcher>,
} }
impl RestApi { impl RestApi {
pub fn new(cors_domains: Vec<String>, endpoints: Arc<Endpoints>, fetcher: Arc<Fetcher>) -> Box<Endpoint> { pub fn new(cors_domains: Vec<cors::AccessControlAllowOrigin>, endpoints: Arc<Endpoints>, fetcher: Arc<Fetcher>) -> Box<Endpoint> {
Box::new(RestApi { Box::new(RestApi {
cors_domains: Some(cors_domains.into_iter().map(|domain| match domain.as_ref() { cors_domains: Some(cors_domains),
"all" | "*" | "any" => AccessControlAllowOrigin::Any,
"null" => AccessControlAllowOrigin::Null,
other => AccessControlAllowOrigin::Value(other.into()),
}).collect()),
endpoints: endpoints, endpoints: endpoints,
fetcher: fetcher, fetcher: fetcher,
}) })
@ -64,7 +60,7 @@ impl Endpoint for RestApi {
struct RestApiRouter { struct RestApiRouter {
api: RestApi, api: RestApi,
origin: Option<String>, cors_header: Option<header::AccessControlAllowOrigin>,
path: Option<EndpointPath>, path: Option<EndpointPath>,
control: Option<Control>, control: Option<Control>,
handler: Box<Handler>, handler: Box<Handler>,
@ -74,7 +70,7 @@ impl RestApiRouter {
fn new(api: RestApi, path: EndpointPath, control: Control) -> Self { fn new(api: RestApi, path: EndpointPath, control: Control) -> Self {
RestApiRouter { RestApiRouter {
path: Some(path), path: Some(path),
origin: None, cors_header: None,
control: Some(control), control: Some(control),
api: api, api: api,
handler: response::as_json_error(&ApiError { handler: response::as_json_error(&ApiError {
@ -95,21 +91,22 @@ impl RestApiRouter {
} }
/// Returns basic headers for a response (it may be overwritten by the handler) /// Returns basic headers for a response (it may be overwritten by the handler)
fn response_headers(&self) -> header::Headers { fn response_headers(cors_header: Option<header::AccessControlAllowOrigin>) -> header::Headers {
let mut headers = header::Headers::new(); let mut headers = header::Headers::new();
headers.set(header::AccessControlAllowCredentials);
headers.set(header::AccessControlAllowMethods(vec![
Method::Options,
Method::Post,
Method::Get,
]));
headers.set(header::AccessControlAllowHeaders(vec![
UniCase("origin".to_owned()),
UniCase("content-type".to_owned()),
UniCase("accept".to_owned()),
]));
if let Some(cors_header) = cors::get_cors_header(&self.api.cors_domains, &self.origin) { if let Some(cors_header) = cors_header {
headers.set(header::AccessControlAllowCredentials);
headers.set(header::AccessControlAllowMethods(vec![
Method::Options,
Method::Post,
Method::Get,
]));
headers.set(header::AccessControlAllowHeaders(vec![
UniCase("origin".to_owned()),
UniCase("content-type".to_owned()),
UniCase("accept".to_owned()),
]));
headers.set(cors_header); headers.set(cors_header);
} }
@ -120,7 +117,7 @@ impl RestApiRouter {
impl server::Handler<net::HttpStream> for RestApiRouter { impl server::Handler<net::HttpStream> for RestApiRouter {
fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next { fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next {
self.origin = cors::read_origin(&request); self.cors_header = jsonrpc_http_server::cors_header(&request, &self.api.cors_domains);
if let Method::Options = *request.method() { if let Method::Options = *request.method() {
self.handler = response::empty(); self.handler = response::empty();
@ -164,7 +161,7 @@ impl server::Handler<net::HttpStream> for RestApiRouter {
} }
fn on_response(&mut self, res: &mut server::Response) -> Next { fn on_response(&mut self, res: &mut server::Response) -> Next {
*res.headers_mut() = self.response_headers(); *res.headers_mut() = Self::response_headers(self.cors_header.take());
self.handler.on_response(res) self.handler.on_response(res)
} }

View File

@ -20,25 +20,28 @@
#![cfg_attr(feature="nightly", plugin(clippy))] #![cfg_attr(feature="nightly", plugin(clippy))]
extern crate base32; extern crate base32;
extern crate futures;
extern crate hyper; extern crate hyper;
extern crate time; extern crate linked_hash_map;
extern crate url as url_lib; extern crate mime_guess;
extern crate unicase; extern crate rand;
extern crate rustc_serialize;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate time;
extern crate unicase;
extern crate url as url_lib;
extern crate zip; extern crate zip;
extern crate rand;
extern crate jsonrpc_core; extern crate jsonrpc_core;
extern crate jsonrpc_http_server; extern crate jsonrpc_http_server;
extern crate mime_guess; extern crate jsonrpc_server_utils;
extern crate rustc_serialize;
extern crate ethcore_rpc; extern crate ethcore_rpc;
extern crate ethcore_util as util; extern crate ethcore_util as util;
extern crate parity_hash_fetch as hash_fetch;
extern crate linked_hash_map;
extern crate fetch; extern crate fetch;
extern crate parity_dapps_glue as parity_dapps; extern crate parity_dapps_glue as parity_dapps;
extern crate futures; extern crate parity_hash_fetch as hash_fetch;
extern crate parity_reactor; extern crate parity_reactor;
#[macro_use] #[macro_use]
@ -68,17 +71,19 @@ mod web;
mod tests; mod tests;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex}; use std::sync::Arc;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::collections::HashMap; use std::collections::HashMap;
use ethcore_rpc::{Metadata}; use jsonrpc_core::{Middleware, MetaIoHandler};
use jsonrpc_http_server::tokio_core::reactor::Remote as TokioRemote;
pub use jsonrpc_http_server::{DomainsValidation, Host, AccessControlAllowOrigin};
use ethcore_rpc::Metadata;
use fetch::{Fetch, Client as FetchClient}; use fetch::{Fetch, Client as FetchClient};
use hash_fetch::urlhint::ContractClient; use hash_fetch::urlhint::ContractClient;
use jsonrpc_core::Middleware;
use jsonrpc_core::reactor::RpcHandler;
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
use parity_reactor::Remote; use parity_reactor::Remote;
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
use self::apps::{HOME_PAGE, DAPPS_DOMAIN}; use self::apps::{HOME_PAGE, DAPPS_DOMAIN};
@ -110,8 +115,8 @@ pub struct ServerBuilder<T: Fetch = FetchClient> {
sync_status: Arc<SyncStatus>, sync_status: Arc<SyncStatus>,
web_proxy_tokens: Arc<WebProxyTokens>, web_proxy_tokens: Arc<WebProxyTokens>,
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<Host>>,
extra_cors: Option<Vec<String>>, extra_cors: Option<Vec<AccessControlAllowOrigin>>,
remote: Remote, remote: Remote,
fetch: Option<T>, fetch: Option<T>,
} }
@ -172,15 +177,15 @@ impl<T: Fetch> ServerBuilder<T> {
/// Change allowed hosts. /// Change allowed hosts.
/// `None` - All hosts are allowed /// `None` - All hosts are allowed
/// `Some(whitelist)` - Allow only whitelisted hosts (+ listen address) /// `Some(whitelist)` - Allow only whitelisted hosts (+ listen address)
pub fn allowed_hosts(mut self, allowed_hosts: Option<Vec<String>>) -> Self { pub fn allowed_hosts(mut self, allowed_hosts: DomainsValidation<Host>) -> Self {
self.allowed_hosts = allowed_hosts; self.allowed_hosts = allowed_hosts.into();
self self
} }
/// Extra cors headers. /// Extra cors headers.
/// `None` - no additional CORS URLs /// `None` - no additional CORS URLs
pub fn extra_cors_headers(mut self, cors: Option<Vec<String>>) -> Self { pub fn extra_cors_headers(mut self, cors: DomainsValidation<AccessControlAllowOrigin>) -> Self {
self.extra_cors = cors; self.extra_cors = cors.into();
self self
} }
@ -192,7 +197,7 @@ impl<T: Fetch> ServerBuilder<T> {
/// Asynchronously start server with no authentication, /// Asynchronously start server with no authentication,
/// returns result with `Server` handle on success or an error. /// returns result with `Server` handle on success or an error.
pub fn start_unsecured_http<S: Middleware<Metadata>>(self, addr: &SocketAddr, handler: RpcHandler<Metadata, S>) -> Result<Server, ServerError> { pub fn start_unsecured_http<S: Middleware<Metadata>>(self, addr: &SocketAddr, handler: MetaIoHandler<Metadata, S>, tokio_remote: TokioRemote) -> Result<Server, ServerError> {
let fetch = self.fetch_client()?; let fetch = self.fetch_client()?;
Server::start_http( Server::start_http(
addr, addr,
@ -207,13 +212,14 @@ impl<T: Fetch> ServerBuilder<T> {
self.sync_status, self.sync_status,
self.web_proxy_tokens, self.web_proxy_tokens,
self.remote, self.remote,
tokio_remote,
fetch, fetch,
) )
} }
/// Asynchronously start server with `HTTP Basic Authentication`, /// Asynchronously start server with `HTTP Basic Authentication`,
/// return result with `Server` handle on success or an error. /// return result with `Server` handle on success or an error.
pub fn start_basic_auth_http<S: Middleware<Metadata>>(self, addr: &SocketAddr, username: &str, password: &str, handler: RpcHandler<Metadata, S>) -> Result<Server, ServerError> { pub fn start_basic_auth_http<S: Middleware<Metadata>>(self, addr: &SocketAddr, username: &str, password: &str, handler: MetaIoHandler<Metadata, S>, tokio_remote: TokioRemote) -> Result<Server, ServerError> {
let fetch = self.fetch_client()?; let fetch = self.fetch_client()?;
Server::start_http( Server::start_http(
addr, addr,
@ -228,6 +234,7 @@ impl<T: Fetch> ServerBuilder<T> {
self.sync_status, self.sync_status,
self.web_proxy_tokens, self.web_proxy_tokens,
self.remote, self.remote,
tokio_remote,
fetch, fetch,
) )
} }
@ -243,12 +250,11 @@ impl<T: Fetch> ServerBuilder<T> {
/// Webapps HTTP server. /// Webapps HTTP server.
pub struct Server { pub struct Server {
server: Option<hyper::server::Listening>, server: Option<hyper::server::Listening>,
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
} }
impl Server { impl Server {
/// Returns a list of allowed hosts or `None` if all hosts are allowed. /// Returns a list of allowed hosts or `None` if all hosts are allowed.
fn allowed_hosts(hosts: Option<Vec<String>>, bind_address: String) -> Option<Vec<String>> { fn allowed_hosts(hosts: Option<Vec<Host>>, bind_address: String) -> Option<Vec<Host>> {
let mut allowed = Vec::new(); let mut allowed = Vec::new();
match hosts { match hosts {
@ -263,16 +269,19 @@ impl Server {
} }
/// Returns a list of CORS domains for API endpoint. /// Returns a list of CORS domains for API endpoint.
fn cors_domains(signer_address: Option<(String, u16)>, extra_cors: Option<Vec<String>>) -> Vec<String> { fn cors_domains(
signer_address: Option<(String, u16)>,
extra_cors: Option<Vec<AccessControlAllowOrigin>>,
) -> Vec<AccessControlAllowOrigin> {
let basic_cors = match signer_address { let basic_cors = match signer_address {
Some(signer_address) => vec![ Some(signer_address) => [
format!("http://{}{}", HOME_PAGE, DAPPS_DOMAIN), format!("http://{}{}", HOME_PAGE, DAPPS_DOMAIN),
format!("http://{}{}:{}", HOME_PAGE, DAPPS_DOMAIN, signer_address.1), format!("http://{}{}:{}", HOME_PAGE, DAPPS_DOMAIN, signer_address.1),
format!("http://{}", address(&signer_address)), format!("http://{}", address(&signer_address)),
format!("https://{}{}", HOME_PAGE, DAPPS_DOMAIN), format!("https://{}{}", HOME_PAGE, DAPPS_DOMAIN),
format!("https://{}{}:{}", HOME_PAGE, DAPPS_DOMAIN, signer_address.1), format!("https://{}{}:{}", HOME_PAGE, DAPPS_DOMAIN, signer_address.1),
format!("https://{}", address(&signer_address)), format!("https://{}", address(&signer_address)),
], ].into_iter().map(|val| AccessControlAllowOrigin::Value(val.into())).collect(),
None => vec![], None => vec![],
}; };
@ -284,10 +293,10 @@ impl Server {
fn start_http<A: Authorization + 'static, F: Fetch, T: Middleware<Metadata>>( fn start_http<A: Authorization + 'static, F: Fetch, T: Middleware<Metadata>>(
addr: &SocketAddr, addr: &SocketAddr,
hosts: Option<Vec<String>>, hosts: Option<Vec<Host>>,
extra_cors: Option<Vec<String>>, extra_cors: Option<Vec<AccessControlAllowOrigin>>,
authorization: A, authorization: A,
handler: RpcHandler<Metadata, T>, handler: MetaIoHandler<Metadata, T>,
dapps_path: PathBuf, dapps_path: PathBuf,
extra_dapps: Vec<PathBuf>, extra_dapps: Vec<PathBuf>,
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
@ -295,9 +304,9 @@ impl Server {
sync_status: Arc<SyncStatus>, sync_status: Arc<SyncStatus>,
web_proxy_tokens: Arc<WebProxyTokens>, web_proxy_tokens: Arc<WebProxyTokens>,
remote: Remote, remote: Remote,
tokio_remote: TokioRemote,
fetch: F, fetch: F,
) -> Result<Server, ServerError> { ) -> Result<Server, ServerError> {
let panic_handler = Arc::new(Mutex::new(None));
let authorization = Arc::new(authorization); let authorization = Arc::new(authorization);
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new( let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
hash_fetch::urlhint::URLHintContract::new(registrar), hash_fetch::urlhint::URLHintContract::new(registrar),
@ -318,7 +327,7 @@ impl Server {
let special = Arc::new({ let special = Arc::new({
let mut special = HashMap::new(); let mut special = HashMap::new();
special.insert(router::SpecialEndpoint::Rpc, rpc::rpc(handler, cors_domains.clone(), panic_handler.clone())); special.insert(router::SpecialEndpoint::Rpc, rpc::rpc(handler, tokio_remote, cors_domains.clone()));
special.insert(router::SpecialEndpoint::Utils, apps::utils()); special.insert(router::SpecialEndpoint::Utils, apps::utils());
special.insert( special.insert(
router::SpecialEndpoint::Api, router::SpecialEndpoint::Api,
@ -346,17 +355,11 @@ impl Server {
Server { Server {
server: Some(l), server: Some(l),
panic_handler: panic_handler,
} }
}) })
.map_err(ServerError::from) .map_err(ServerError::from)
} }
/// Set callback for panics.
pub fn set_panic_handler<F>(&self, handler: F) where F : Fn() -> () + Send + 'static {
*self.panic_handler.lock().unwrap() = Some(Box::new(handler));
}
#[cfg(test)] #[cfg(test)]
/// Returns address that this server is bound to. /// Returns address that this server is bound to.
pub fn addr(&self) -> &SocketAddr { pub fn addr(&self) -> &SocketAddr {
@ -408,6 +411,7 @@ fn address(address: &(String, u16)) -> String {
#[cfg(test)] #[cfg(test)]
mod util_tests { mod util_tests {
use super::Server; use super::Server;
use jsonrpc_http_server::AccessControlAllowOrigin;
#[test] #[test]
fn should_return_allowed_hosts() { fn should_return_allowed_hosts() {
@ -432,18 +436,18 @@ mod util_tests {
// when // when
let none = Server::cors_domains(None, None); let none = Server::cors_domains(None, None);
let some = Server::cors_domains(Some(("127.0.0.1".into(), 18180)), None); let some = Server::cors_domains(Some(("127.0.0.1".into(), 18180)), None);
let extra = Server::cors_domains(None, Some(vec!["all".to_owned()])); let extra = Server::cors_domains(None, Some(vec!["all".into()]));
// then // then
assert_eq!(none, Vec::<String>::new()); assert_eq!(none, Vec::<AccessControlAllowOrigin>::new());
assert_eq!(some, vec![ assert_eq!(some, vec![
"http://parity.web3.site".to_owned(), "http://parity.web3.site".into(),
"http://parity.web3.site:18180".into(), "http://parity.web3.site:18180".into(),
"http://127.0.0.1:18180".into(), "http://127.0.0.1:18180".into(),
"https://parity.web3.site".into(), "https://parity.web3.site".into(),
"https://parity.web3.site:18180".into(), "https://parity.web3.site:18180".into(),
"https://127.0.0.1:18180".into() "https://127.0.0.1:18180".into(),
]); ]);
assert_eq!(extra, vec!["all".to_owned()]); assert_eq!(extra, vec![AccessControlAllowOrigin::Any]);
} }
} }

View File

@ -19,18 +19,13 @@ use apps::DAPPS_DOMAIN;
use hyper::{server, header, StatusCode}; use hyper::{server, header, StatusCode};
use hyper::net::HttpStream; use hyper::net::HttpStream;
use jsonrpc_http_server::{is_host_header_valid};
use handlers::ContentHandler; use handlers::ContentHandler;
use jsonrpc_http_server;
use jsonrpc_server_utils::hosts;
pub fn is_valid(request: &server::Request<HttpStream>, allowed_hosts: &[String], endpoints: Vec<String>) -> bool { pub fn is_valid(req: &server::Request<HttpStream>, allowed_hosts: &Option<Vec<hosts::Host>>) -> bool {
let mut endpoints = endpoints.iter() let header_valid = jsonrpc_http_server::is_host_allowed(req, allowed_hosts);
.map(|endpoint| format!("{}{}", endpoint, DAPPS_DOMAIN)) match (header_valid, req.headers().get::<header::Host>()) {
.collect::<Vec<String>>();
endpoints.extend_from_slice(allowed_hosts);
let header_valid = is_host_header_valid(request, &endpoints);
match (header_valid, request.headers().get::<header::Host>()) {
(true, _) => true, (true, _) => true,
(_, Some(host)) => host.hostname.ends_with(DAPPS_DOMAIN), (_, Some(host)) => host.hostname.ends_with(DAPPS_DOMAIN),
_ => false, _ => false,

View File

@ -24,14 +24,16 @@ use address;
use std::cmp; use std::cmp;
use std::sync::Arc; use std::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use url::{Url, Host}; use url::{Url, Host};
use hyper::{self, server, header, Next, Encoder, Decoder, Control, StatusCode}; use hyper::{self, server, header, Next, Encoder, Decoder, Control, StatusCode};
use hyper::net::HttpStream; use hyper::net::HttpStream;
use jsonrpc_server_utils::hosts;
use apps::{self, DAPPS_DOMAIN}; use apps::{self, DAPPS_DOMAIN};
use apps::fetcher::Fetcher; use apps::fetcher::Fetcher;
use endpoint::{Endpoint, Endpoints, EndpointPath}; use endpoint::{Endpoint, Endpoints, EndpointPath};
use handlers::{self, Redirection, ContentHandler}; use handlers::{self, Redirection, ContentHandler};
use self::auth::{Authorization, Authorized};
/// Special endpoints are accessible on every domain (every dapp) /// Special endpoints are accessible on every domain (every dapp)
#[derive(Debug, PartialEq, Hash, Eq)] #[derive(Debug, PartialEq, Hash, Eq)]
@ -42,18 +44,18 @@ pub enum SpecialEndpoint {
None, None,
} }
pub struct Router<A: Authorization + 'static> { pub struct Router<A: auth::Authorization + 'static> {
control: Option<Control>, control: Option<Control>,
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
endpoints: Arc<Endpoints>, endpoints: Arc<Endpoints>,
fetch: Arc<Fetcher>, fetch: Arc<Fetcher>,
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>, special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
authorization: Arc<A>, authorization: Arc<A>,
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<hosts::Host>>,
handler: Box<server::Handler<HttpStream> + Send>, handler: Box<server::Handler<HttpStream> + Send>,
} }
impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> { impl<A: auth::Authorization + 'static> server::Handler<HttpStream> for Router<A> {
fn on_request(&mut self, req: server::Request<HttpStream>) -> Next { fn on_request(&mut self, req: server::Request<HttpStream>) -> Next {
// Choose proper handler depending on path / domain // Choose proper handler depending on path / domain
@ -66,20 +68,18 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", url, req); trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", url, req);
// Validate Host header // Validate Host header
if let Some(ref hosts) = self.allowed_hosts { trace!(target: "dapps", "Validating host headers against: {:?}", self.allowed_hosts);
trace!(target: "dapps", "Validating host headers against: {:?}", hosts); let is_valid = is_utils || host_validation::is_valid(&req, &self.allowed_hosts);
let is_valid = is_utils || host_validation::is_valid(&req, hosts, self.endpoints.keys().cloned().collect()); if !is_valid {
if !is_valid { debug!(target: "dapps", "Rejecting invalid host header.");
debug!(target: "dapps", "Rejecting invalid host header."); self.handler = host_validation::host_invalid_response();
self.handler = host_validation::host_invalid_response(); return self.handler.on_request(req);
return self.handler.on_request(req);
}
} }
trace!(target: "dapps", "Checking authorization."); trace!(target: "dapps", "Checking authorization.");
// Check authorization // Check authorization
let auth = self.authorization.is_authorized(&req); let auth = self.authorization.is_authorized(&req);
if let Authorized::No(handler) = auth { if let auth::Authorized::No(handler) = auth {
debug!(target: "dapps", "Authorization denied."); debug!(target: "dapps", "Authorization denied.");
self.handler = handler; self.handler = handler;
return self.handler.on_request(req); return self.handler.on_request(req);
@ -181,7 +181,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
} }
} }
impl<A: Authorization> Router<A> { impl<A: auth::Authorization> Router<A> {
pub fn new( pub fn new(
control: Control, control: Control,
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
@ -189,7 +189,7 @@ impl<A: Authorization> Router<A> {
endpoints: Arc<Endpoints>, endpoints: Arc<Endpoints>,
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>, special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
authorization: Arc<A>, authorization: Arc<A>,
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<hosts::Host>>,
) -> Self { ) -> Self {
let handler = special.get(&SpecialEndpoint::Utils) let handler = special.get(&SpecialEndpoint::Utils)

View File

@ -14,46 +14,57 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::{Arc, Mutex}; use std::sync::Arc;
use hyper; use hyper;
use ethcore_rpc::{Metadata, Origin}; use ethcore_rpc::{Metadata, Origin};
use jsonrpc_core::Middleware; use jsonrpc_core::{Middleware, MetaIoHandler};
use jsonrpc_core::reactor::RpcHandler; use jsonrpc_http_server::{self as http, AccessControlAllowOrigin, HttpMetaExtractor};
use jsonrpc_http_server::{Rpc, ServerHandler, PanicHandler, AccessControlAllowOrigin, HttpMetaExtractor}; use jsonrpc_http_server::tokio_core::reactor::Remote;
use endpoint::{Endpoint, EndpointPath, Handler}; use endpoint::{Endpoint, EndpointPath, Handler};
pub fn rpc<T: Middleware<Metadata>>( pub fn rpc<T: Middleware<Metadata>>(
handler: RpcHandler<Metadata, T>, handler: MetaIoHandler<Metadata, T>,
cors_domains: Vec<String>, remote: Remote,
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>, cors_domains: Vec<AccessControlAllowOrigin>,
) -> Box<Endpoint> { ) -> Box<Endpoint> {
Box::new(RpcEndpoint { Box::new(RpcEndpoint {
handler: handler, handler: Arc::new(handler),
remote: remote,
meta_extractor: Arc::new(MetadataExtractor), meta_extractor: Arc::new(MetadataExtractor),
panic_handler: panic_handler, cors_domain: Some(cors_domains),
cors_domain: Some(cors_domains.into_iter().map(AccessControlAllowOrigin::Value).collect()),
// NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router. // NOTE [ToDr] We don't need to do any hosts validation here. It's already done in router.
allowed_hosts: None, allowed_hosts: None,
}) })
} }
struct RpcEndpoint<T: Middleware<Metadata>> { struct RpcEndpoint<T: Middleware<Metadata>> {
handler: RpcHandler<Metadata, T>, handler: Arc<MetaIoHandler<Metadata, T>>,
remote: Remote,
meta_extractor: Arc<HttpMetaExtractor<Metadata>>, meta_extractor: Arc<HttpMetaExtractor<Metadata>>,
panic_handler: Arc<Mutex<Option<Box<Fn() -> () + Send>>>>,
cors_domain: Option<Vec<AccessControlAllowOrigin>>, cors_domain: Option<Vec<AccessControlAllowOrigin>>,
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<http::Host>>,
}
#[derive(Default)]
struct NoopMiddleware;
impl http::RequestMiddleware for NoopMiddleware {
fn on_request(&self, _request: &hyper::server::Request<hyper::net::HttpStream>) -> http::RequestMiddlewareAction {
http::RequestMiddlewareAction::Proceed
}
} }
impl<T: Middleware<Metadata>> Endpoint for RpcEndpoint<T> { impl<T: Middleware<Metadata>> Endpoint for RpcEndpoint<T> {
fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box<Handler> { fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box<Handler> {
let panic_handler = PanicHandler { handler: self.panic_handler.clone() }; Box::new(http::ServerHandler::new(
Box::new(ServerHandler::new( http::Rpc {
Rpc::new(self.handler.clone(), self.meta_extractor.clone()), handler: self.handler.clone(),
remote: self.remote.clone(),
extractor: self.meta_extractor.clone(),
},
self.cors_domain.clone(), self.cors_domain.clone(),
self.allowed_hosts.clone(), self.allowed_hosts.clone(),
panic_handler, Arc::new(NoopMiddleware),
control, control,
)) ))
} }

View File

@ -33,8 +33,8 @@ fn should_return_error() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned()); response.assert_status("HTTP/1.1 404 Not Found");
assert_eq!(response.headers.get(3).unwrap(), "Content-Type: application/json"); response.assert_header("Content-Type", "application/json");
assert_eq!(response.body, format!("58\n{}\n0\n\n", r#"{"code":"404","title":"Not Found","detail":"Resource you requested has not been found."}"#)); assert_eq!(response.body, format!("58\n{}\n0\n\n", r#"{"code":"404","title":"Not Found","detail":"Resource you requested has not been found."}"#));
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }
@ -56,8 +56,8 @@ fn should_serve_apps() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.headers.get(3).unwrap(), "Content-Type: application/json"); response.assert_header("Content-Type", "application/json");
assert!(response.body.contains("Parity UI"), response.body); assert!(response.body.contains("Parity UI"), response.body);
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }
@ -79,8 +79,8 @@ fn should_handle_ping() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.headers.get(3).unwrap(), "Content-Type: application/json"); response.assert_header("Content-Type", "application/json");
assert_eq!(response.body, "0\n\n".to_owned()); assert_eq!(response.body, "0\n\n".to_owned());
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }
@ -102,7 +102,7 @@ fn should_try_to_resolve_dapp() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned()); response.assert_status("HTTP/1.1 404 Not Found");
assert_eq!(registrar.calls.lock().len(), 2); assert_eq!(registrar.calls.lock().len(), 2);
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }
@ -125,12 +125,8 @@ fn should_return_signer_port_cors_headers() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert!( response.assert_header("Access-Control-Allow-Origin", "http://127.0.0.1:18180");
response.headers_raw.contains("Access-Control-Allow-Origin: http://127.0.0.1:18180"),
"CORS header for signer missing: {:?}",
response.headers
);
} }
#[test] #[test]
@ -151,12 +147,8 @@ fn should_return_signer_port_cors_headers_for_home_parity() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert!( response.assert_header("Access-Control-Allow-Origin", "http://parity.web3.site");
response.headers_raw.contains("Access-Control-Allow-Origin: http://parity.web3.site"),
"CORS header for parity.web3.site missing: {:?}",
response.headers
);
} }
@ -178,12 +170,8 @@ fn should_return_signer_port_cors_headers_for_home_parity_with_https() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert!( response.assert_header("Access-Control-Allow-Origin", "https://parity.web3.site");
response.headers_raw.contains("Access-Control-Allow-Origin: https://parity.web3.site"),
"CORS header for parity.web3.site missing: {:?}",
response.headers
);
} }
#[test] #[test]
@ -204,12 +192,8 @@ fn should_return_signer_port_cors_headers_for_home_parity_with_port() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert!( response.assert_header("Access-Control-Allow-Origin", "http://parity.web3.site:18180");
response.headers_raw.contains("Access-Control-Allow-Origin: http://parity.web3.site:18180"),
"CORS header for parity.web3.site missing: {:?}",
response.headers
);
} }
#[test] #[test]

View File

@ -21,13 +21,12 @@ use std::sync::Arc;
use env_logger::LogBuilder; use env_logger::LogBuilder;
use ethcore_rpc::Metadata; use ethcore_rpc::Metadata;
use jsonrpc_core::MetaIoHandler; use jsonrpc_core::MetaIoHandler;
use jsonrpc_core::reactor::RpcEventLoop;
use ServerBuilder; use ServerBuilder;
use Server; use Server;
use fetch::Fetch; use fetch::Fetch;
use devtools::http_client; use devtools::http_client;
use parity_reactor::Remote; use parity_reactor::{EventLoop, Remote};
mod registrar; mod registrar;
mod fetch; mod fetch;
@ -48,7 +47,7 @@ fn init_logger() {
pub struct ServerLoop { pub struct ServerLoop {
pub server: Server, pub server: Server,
pub event_loop: RpcEventLoop, pub event_loop: EventLoop,
} }
impl Deref for ServerLoop { impl Deref for ServerLoop {
@ -70,13 +69,12 @@ pub fn init_server<F, B>(process: F, io: MetaIoHandler<Metadata>, remote: Remote
// TODO [ToDr] When https://github.com/ethcore/jsonrpc/issues/26 is resolved // TODO [ToDr] When https://github.com/ethcore/jsonrpc/issues/26 is resolved
// this additional EventLoop wouldn't be needed, we should be able to re-use remote. // this additional EventLoop wouldn't be needed, we should be able to re-use remote.
let event_loop = RpcEventLoop::spawn(); let event_loop = EventLoop::spawn();
let handler = event_loop.handler(Arc::new(io));
let server = process(ServerBuilder::new( let server = process(ServerBuilder::new(
&dapps_path, registrar.clone(), remote, &dapps_path, registrar.clone(), remote,
)) ))
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT))) .signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
.start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), handler).unwrap(); .start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io, event_loop.raw_remote()).unwrap();
( (
ServerLoop { server: server, event_loop: event_loop }, ServerLoop { server: server, event_loop: event_loop },
registrar, registrar,
@ -89,12 +87,12 @@ pub fn serve_with_auth(user: &str, pass: &str) -> ServerLoop {
let mut dapps_path = env::temp_dir(); let mut dapps_path = env::temp_dir();
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading"); dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
let event_loop = RpcEventLoop::spawn(); let event_loop = EventLoop::spawn();
let handler = event_loop.handler(Arc::new(MetaIoHandler::default())); let io = MetaIoHandler::default();
let server = ServerBuilder::new(&dapps_path, registrar, Remote::new(event_loop.remote())) let server = ServerBuilder::new(&dapps_path, registrar, event_loop.remote())
.signer_address(Some(("127.0.0.1".into(), SIGNER_PORT))) .signer_address(Some(("127.0.0.1".into(), SIGNER_PORT)))
.allowed_hosts(None) .allowed_hosts(None.into())
.start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), user, pass, handler).unwrap(); .start_basic_auth_http(&"127.0.0.1:0".parse().unwrap(), user, pass, io, event_loop.raw_remote()).unwrap();
ServerLoop { ServerLoop {
server: server, server: server,
event_loop: event_loop, event_loop: event_loop,
@ -102,26 +100,28 @@ pub fn serve_with_auth(user: &str, pass: &str) -> ServerLoop {
} }
pub fn serve_with_rpc(io: MetaIoHandler<Metadata>) -> ServerLoop { pub fn serve_with_rpc(io: MetaIoHandler<Metadata>) -> ServerLoop {
init_server(|builder| builder.allowed_hosts(None), io, Remote::new_sync()).0 init_server(|builder| builder.allowed_hosts(None.into()), io, Remote::new_sync()).0
} }
pub fn serve_hosts(hosts: Option<Vec<String>>) -> ServerLoop { pub fn serve_hosts(hosts: Option<Vec<String>>) -> ServerLoop {
init_server(|builder| builder.allowed_hosts(hosts), Default::default(), Remote::new_sync()).0 let hosts = hosts.map(|hosts| hosts.into_iter().map(Into::into).collect());
init_server(|builder| builder.allowed_hosts(hosts.into()), Default::default(), Remote::new_sync()).0
} }
pub fn serve_extra_cors(extra_cors: Option<Vec<String>>) -> ServerLoop { pub fn serve_extra_cors(extra_cors: Option<Vec<String>>) -> ServerLoop {
init_server(|builder| builder.allowed_hosts(None).extra_cors_headers(extra_cors), Default::default(), Remote::new_sync()).0 let extra_cors = extra_cors.map(|cors| cors.into_iter().map(Into::into).collect());
init_server(|builder| builder.allowed_hosts(None.into()).extra_cors_headers(extra_cors.into()), Default::default(), Remote::new_sync()).0
} }
pub fn serve_with_registrar() -> (ServerLoop, Arc<FakeRegistrar>) { pub fn serve_with_registrar() -> (ServerLoop, Arc<FakeRegistrar>) {
init_server(|builder| builder.allowed_hosts(None), Default::default(), Remote::new_sync()) init_server(|builder| builder.allowed_hosts(None.into()), Default::default(), Remote::new_sync())
} }
pub fn serve_with_registrar_and_sync() -> (ServerLoop, Arc<FakeRegistrar>) { pub fn serve_with_registrar_and_sync() -> (ServerLoop, Arc<FakeRegistrar>) {
init_server(|builder| { init_server(|builder| {
builder builder
.sync_status(Arc::new(|| true)) .sync_status(Arc::new(|| true))
.allowed_hosts(None) .allowed_hosts(None.into())
}, Default::default(), Remote::new_sync()) }, Default::default(), Remote::new_sync())
} }
@ -133,7 +133,7 @@ pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (Serv
let fetch = FakeFetch::default(); let fetch = FakeFetch::default();
let f = fetch.clone(); let f = fetch.clone();
let (server, reg) = init_server(move |builder| { let (server, reg) = init_server(move |builder| {
builder.allowed_hosts(None).fetch(f.clone()) builder.allowed_hosts(None.into()).fetch(f.clone())
}, Default::default(), if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() }); }, Default::default(), if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() });
(server, fetch, reg) (server, fetch, reg)
@ -144,7 +144,7 @@ pub fn serve_with_fetch(web_token: &'static str) -> (ServerLoop, FakeFetch) {
let f = fetch.clone(); let f = fetch.clone();
let (server, _) = init_server(move |builder| { let (server, _) = init_server(move |builder| {
builder builder
.allowed_hosts(None) .allowed_hosts(None.into())
.fetch(f.clone()) .fetch(f.clone())
.web_proxy_tokens(Arc::new(move |token| &token == web_token)) .web_proxy_tokens(Arc::new(move |token| &token == web_token))
}, Default::default(), Remote::new_sync()); }, Default::default(), Remote::new_sync());
@ -153,7 +153,7 @@ pub fn serve_with_fetch(web_token: &'static str) -> (ServerLoop, FakeFetch) {
} }
pub fn serve() -> ServerLoop { pub fn serve() -> ServerLoop {
init_server(|builder| builder.allowed_hosts(None), Default::default(), Remote::new_sync()).0 init_server(|builder| builder.allowed_hosts(None.into()), Default::default(), Remote::new_sync()).0
} }
pub fn request(server: ServerLoop, request: &str) -> http_client::Response { pub fn request(server: ServerLoop, request: &str) -> http_client::Response {

View File

@ -32,7 +32,7 @@ fn should_redirect_to_home() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); response.assert_status("HTTP/1.1 302 Found");
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180"); assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
} }
@ -52,7 +52,7 @@ fn should_redirect_to_home_when_trailing_slash_is_missing() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); response.assert_status("HTTP/1.1 302 Found");
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180"); assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
} }
@ -72,7 +72,7 @@ fn should_redirect_to_home_for_users_with_cached_redirection() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 302 Found".to_owned()); response.assert_status("HTTP/1.1 302 Found");
assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180"); assert_eq!(response.headers.get(0).unwrap(), "Location: http://127.0.0.1:18180");
} }
@ -92,7 +92,7 @@ fn should_display_404_on_invalid_dapp() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned()); response.assert_status("HTTP/1.1 404 Not Found");
assert_security_headers_for_embed(&response.headers); assert_security_headers_for_embed(&response.headers);
} }
@ -112,7 +112,7 @@ fn should_display_404_on_invalid_dapp_with_domain() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned()); response.assert_status("HTTP/1.1 404 Not Found");
assert_security_headers_for_embed(&response.headers); assert_security_headers_for_embed(&response.headers);
} }
@ -134,8 +134,8 @@ fn should_serve_rpc() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.body, format!("58\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":null}"#)); assert_eq!(response.body, format!("4C\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":null}"#));
} }
#[test] #[test]
@ -156,8 +156,8 @@ fn should_serve_rpc_at_slash_rpc() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.body, format!("58\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error","data":null},"id":null}"#)); assert_eq!(response.body, format!("4C\n{}\n\n0\n\n", r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":null}"#));
} }
@ -178,7 +178,7 @@ fn should_serve_proxy_pac() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.body, "DD\n\nfunction FindProxyForURL(url, host) {\n\tif (shExpMatch(host, \"parity.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:18180\";\n\t}\n\n\tif (shExpMatch(host, \"*.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:8080\";\n\t}\n\n\treturn \"DIRECT\";\n}\n\n0\n\n".to_owned()); assert_eq!(response.body, "DD\n\nfunction FindProxyForURL(url, host) {\n\tif (shExpMatch(host, \"parity.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:18180\";\n\t}\n\n\tif (shExpMatch(host, \"*.web3.site\"))\n\t{\n\t\treturn \"PROXY 127.0.0.1:8080\";\n\t}\n\n\treturn \"DIRECT\";\n}\n\n0\n\n".to_owned());
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }
@ -200,7 +200,7 @@ fn should_serve_utils() {
); );
// then // then
assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); response.assert_status("HTTP/1.1 200 OK");
assert_eq!(response.body.contains("function(){"), true); assert_eq!(response.body.contains("function(){"), true);
assert_security_headers(&response.headers); assert_security_headers(&response.headers);
} }

View File

@ -33,13 +33,13 @@ use std::sync::Arc;
use std::net::{SocketAddr, IpAddr}; use std::net::{SocketAddr, IpAddr};
use error::ServerError; use error::ServerError;
use route::Out; use route::Out;
use jsonrpc_http_server::cors;
use hyper::server::{Listening, Handler, Request, Response}; use hyper::server::{Listening, Handler, Request, Response};
use hyper::net::HttpStream; use hyper::net::HttpStream;
use hyper::header::{Vary, ContentLength, ContentType, AccessControlAllowOrigin}; use hyper::header::{self, Vary, ContentLength, ContentType};
use hyper::{Next, Encoder, Decoder, Method, RequestUri, StatusCode}; use hyper::{Next, Encoder, Decoder, Method, RequestUri, StatusCode};
use ethcore::client::BlockChainClient; use ethcore::client::BlockChainClient;
pub use jsonrpc_http_server::{AccessControlAllowOrigin, Host, DomainsValidation};
/// Request/response handler /// Request/response handler
pub struct IpfsHandler { pub struct IpfsHandler {
@ -47,12 +47,12 @@ pub struct IpfsHandler {
out: Out, out: Out,
/// How many bytes from the response have been written /// How many bytes from the response have been written
out_progress: usize, out_progress: usize,
/// Origin request header /// CORS response header
origin: Option<String>, cors_header: Option<header::AccessControlAllowOrigin>,
/// Allowed CORS domains /// Allowed CORS domains
cors_domains: Option<Vec<AccessControlAllowOrigin>>, cors_domains: Option<Vec<AccessControlAllowOrigin>>,
/// Hostnames allowed in the `Host` request header /// Hostnames allowed in the `Host` request header
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<Host>>,
/// Reference to the Blockchain Client /// Reference to the Blockchain Client
client: Arc<BlockChainClient>, client: Arc<BlockChainClient>,
} }
@ -62,50 +62,27 @@ impl IpfsHandler {
&*self.client &*self.client
} }
pub fn new(cors: Option<Vec<String>>, hosts: Option<Vec<String>>, client: Arc<BlockChainClient>) -> Self { pub fn new(cors: DomainsValidation<AccessControlAllowOrigin>, hosts: DomainsValidation<Host>, client: Arc<BlockChainClient>) -> Self {
fn origin_to_header(origin: String) -> AccessControlAllowOrigin {
match origin.as_str() {
"*" => AccessControlAllowOrigin::Any,
"null" | "" => AccessControlAllowOrigin::Null,
_ => AccessControlAllowOrigin::Value(origin),
}
}
IpfsHandler { IpfsHandler {
out: Out::Bad("Invalid Request"), out: Out::Bad("Invalid Request"),
out_progress: 0, out_progress: 0,
origin: None, cors_header: None,
cors_domains: cors.map(|vec| vec.into_iter().map(origin_to_header).collect()), cors_domains: cors.into(),
allowed_hosts: hosts, allowed_hosts: hosts.into(),
client: client, client: client,
} }
} }
fn is_host_allowed(&self, req: &Request<HttpStream>) -> bool { fn is_origin_allowed(&self, origin_provided: bool) -> bool {
match self.allowed_hosts { match (origin_provided, self.cors_header.as_ref()) {
Some(ref hosts) => jsonrpc_http_server::is_host_header_valid(&req, hosts), // Request without Origin are always OK.
None => true, (false, _) => true,
// If there is a cors header to be returned it's ok.
(true, Some(_)) => true,
// If origin is provided and we won't return cors header it's bad.
(true, None) => false,
} }
} }
fn is_origin_allowed(&self) -> bool {
// Check origin header first, no header passed is good news
let origin = match self.origin {
Some(ref origin) => origin,
None => return true,
};
let cors_domains = match self.cors_domains {
Some(ref domains) => domains,
None => return false,
};
cors_domains.iter().any(|domain| match *domain {
AccessControlAllowOrigin::Value(ref allowed) => origin == allowed,
AccessControlAllowOrigin::Any => true,
AccessControlAllowOrigin::Null => origin == "",
})
}
} }
/// Implement Hyper's HTTP handler /// Implement Hyper's HTTP handler
@ -115,15 +92,15 @@ impl Handler<HttpStream> for IpfsHandler {
return Next::write(); return Next::write();
} }
self.origin = cors::read_origin(&req); self.cors_header = jsonrpc_http_server::cors_header(&req, &self.cors_domains);
if !self.is_host_allowed(&req) { if !jsonrpc_http_server::is_host_allowed(&req, &self.allowed_hosts) {
self.out = Out::Bad("Disallowed Host header"); self.out = Out::Bad("Disallowed Host header");
return Next::write(); return Next::write();
} }
if !self.is_origin_allowed() { if !self.is_origin_allowed(req.headers().get::<header::Origin>().is_some()) {
self.out = Out::Bad("Disallowed Origin header"); self.out = Out::Bad("Disallowed Origin header");
return Next::write(); return Next::write();
@ -176,7 +153,7 @@ impl Handler<HttpStream> for IpfsHandler {
} }
} }
if let Some(cors_header) = cors::get_cors_header(&self.cors_domains, &self.origin) { if let Some(cors_header) = self.cors_header.take() {
res.headers_mut().set(cors_header); res.headers_mut().set(cors_header);
res.headers_mut().set(Vary::Items(vec!["Origin".into()])); res.headers_mut().set(Vary::Items(vec!["Origin".into()]));
} }
@ -219,11 +196,11 @@ fn write_chunk<W: Write>(transport: &mut W, progress: &mut usize, data: &[u8]) -
} }
/// Add current interface (default: "127.0.0.1:5001") to list of allowed hosts /// Add current interface (default: "127.0.0.1:5001") to list of allowed hosts
fn include_current_interface(mut hosts: Vec<String>, interface: String, port: u16) -> Vec<String> { fn include_current_interface(mut hosts: Vec<Host>, interface: String, port: u16) -> Vec<Host> {
hosts.push(match port { hosts.push(match port {
80 => interface, 80 => interface,
_ => format!("{}:{}", interface, port), _ => format!("{}:{}", interface, port),
}); }.into());
hosts hosts
} }
@ -231,14 +208,15 @@ fn include_current_interface(mut hosts: Vec<String>, interface: String, port: u1
pub fn start_server( pub fn start_server(
port: u16, port: u16,
interface: String, interface: String,
cors: Option<Vec<String>>, cors: DomainsValidation<AccessControlAllowOrigin>,
hosts: Option<Vec<String>>, hosts: DomainsValidation<Host>,
client: Arc<BlockChainClient> client: Arc<BlockChainClient>
) -> Result<Listening, ServerError> { ) -> Result<Listening, ServerError> {
let ip: IpAddr = interface.parse().map_err(|_| ServerError::InvalidInterface)?; let ip: IpAddr = interface.parse().map_err(|_| ServerError::InvalidInterface)?;
let addr = SocketAddr::new(ip, port); let addr = SocketAddr::new(ip, port);
let hosts = hosts.map(move |hosts| include_current_interface(hosts, interface, port)); let hosts: Option<Vec<_>> = hosts.into();
let hosts: DomainsValidation<_> = hosts.map(move |hosts| include_current_interface(hosts, interface, port)).into();
Ok( Ok(
hyper::Server::http(&addr)? hyper::Server::http(&addr)?

View File

@ -23,9 +23,8 @@ use ethcore_rpc::informant::RpcStats;
use ethsync::SyncProvider; use ethsync::SyncProvider;
use hash_fetch::fetch::Client as FetchClient; use hash_fetch::fetch::Client as FetchClient;
use helpers::replace_home; use helpers::replace_home;
use io::PanicHandler;
use jsonrpc_core::reactor::Remote;
use rpc_apis::{self, SignerService}; use rpc_apis::{self, SignerService};
use parity_reactor;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Configuration { pub struct Configuration {
@ -60,11 +59,10 @@ impl Default for Configuration {
} }
pub struct Dependencies { pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>, pub apis: Arc<rpc_apis::Dependencies>,
pub client: Arc<Client>, pub client: Arc<Client>,
pub sync: Arc<SyncProvider>, pub sync: Arc<SyncProvider>,
pub remote: Remote, pub remote: parity_reactor::TokioRemote,
pub fetch: FetchClient, pub fetch: FetchClient,
pub signer: Arc<SignerService>, pub signer: Arc<SignerService>,
pub stats: Arc<RpcStats>, pub stats: Arc<RpcStats>,
@ -137,9 +135,9 @@ mod server {
use ansi_term::Colour; use ansi_term::Colour;
use ethcore::transaction::{Transaction, Action}; use ethcore::transaction::{Transaction, Action};
use ethcore::client::{Client, BlockChainClient, BlockId}; use ethcore::client::{Client, BlockChainClient, BlockId};
use ethcore_dapps::{AccessControlAllowOrigin, Host};
use ethcore_rpc::is_major_importing; use ethcore_rpc::is_major_importing;
use hash_fetch::urlhint::ContractClient; use hash_fetch::urlhint::ContractClient;
use jsonrpc_core::reactor::RpcHandler;
use parity_reactor; use parity_reactor;
use rpc_apis; use rpc_apis;
@ -162,6 +160,8 @@ mod server {
Arc::new(Registrar { client: deps.client.clone() }), Arc::new(Registrar { client: deps.client.clone() }),
parity_reactor::Remote::new(deps.remote.clone()), parity_reactor::Remote::new(deps.remote.clone()),
); );
let allowed_hosts: Option<Vec<_>> = allowed_hosts.map(|hosts| hosts.into_iter().map(Host::from).collect());
let cors: Option<Vec<_>> = cors.map(|cors| cors.into_iter().map(AccessControlAllowOrigin::from).collect());
let sync = deps.sync.clone(); let sync = deps.sync.clone();
let client = deps.client.clone(); let client = deps.client.clone();
@ -172,8 +172,8 @@ mod server {
.web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token))) .web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token)))
.extra_dapps(&extra_dapps) .extra_dapps(&extra_dapps)
.signer_address(deps.signer.address()) .signer_address(deps.signer.address())
.allowed_hosts(allowed_hosts) .allowed_hosts(allowed_hosts.into())
.extra_cors_headers(cors); .extra_cors_headers(cors.into());
let api_set = if all_apis { let api_set = if all_apis {
warn!("{}", Colour::Red.bold().paint("*** INSECURE *** Running Dapps with all APIs exposed.")); warn!("{}", Colour::Red.bold().paint("*** INSECURE *** Running Dapps with all APIs exposed."));
@ -183,13 +183,12 @@ mod server {
rpc_apis::ApiSet::UnsafeContext rpc_apis::ApiSet::UnsafeContext
}; };
let apis = rpc_apis::setup_rpc(deps.stats, deps.apis.clone(), api_set); let apis = rpc_apis::setup_rpc(deps.stats, deps.apis.clone(), api_set);
let handler = RpcHandler::new(Arc::new(apis), deps.remote);
let start_result = match auth { let start_result = match auth {
None => { None => {
server.start_unsecured_http(url, handler) server.start_unsecured_http(url, apis, deps.remote)
}, },
Some((username, password)) => { Some((username, password)) => {
server.start_basic_auth_http(url, &username, &password, handler) server.start_basic_auth_http(url, &username, &password, apis, deps.remote)
}, },
}; };
@ -199,13 +198,7 @@ mod server {
_ => Err(format!("WebApps io error: {}", err)), _ => Err(format!("WebApps io error: {}", err)),
}, },
Err(e) => Err(format!("WebApps error: {:?}", e)), Err(e) => Err(format!("WebApps error: {:?}", e)),
Ok(server) => { Ok(server) => Ok(server),
let ph = deps.panic_handler;
server.set_panic_handler(move || {
ph.notify_all("Panic in WebApp thread.".to_owned());
});
Ok(server)
},
} }
} }

View File

@ -1,40 +1,59 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc; use std::sync::Arc;
use parity_ipfs_api; use parity_ipfs_api::{self, AccessControlAllowOrigin, Host};
use parity_ipfs_api::error::ServerError; use parity_ipfs_api::error::ServerError;
use ethcore::client::BlockChainClient; use ethcore::client::BlockChainClient;
use hyper::server::Listening; use hyper::server::Listening;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Configuration { pub struct Configuration {
pub enabled: bool, pub enabled: bool,
pub port: u16, pub port: u16,
pub interface: String, pub interface: String,
pub cors: Option<Vec<String>>, pub cors: Option<Vec<String>>,
pub hosts: Option<Vec<String>>, pub hosts: Option<Vec<String>>,
} }
impl Default for Configuration { impl Default for Configuration {
fn default() -> Self { fn default() -> Self {
Configuration { Configuration {
enabled: false, enabled: false,
port: 5001, port: 5001,
interface: "127.0.0.1".into(), interface: "127.0.0.1".into(),
cors: None, cors: None,
hosts: Some(Vec::new()), hosts: Some(Vec::new()),
} }
} }
} }
pub fn start_server(conf: Configuration, client: Arc<BlockChainClient>) -> Result<Option<Listening>, ServerError> { pub fn start_server(conf: Configuration, client: Arc<BlockChainClient>) -> Result<Option<Listening>, ServerError> {
if !conf.enabled { if !conf.enabled {
return Ok(None); return Ok(None);
} }
parity_ipfs_api::start_server( let cors = conf.cors.map(|cors| cors.into_iter().map(AccessControlAllowOrigin::from).collect());
conf.port, let hosts = conf.hosts.map(|hosts| hosts.into_iter().map(Host::from).collect());
conf.interface,
conf.cors, parity_ipfs_api::start_server(
conf.hosts, conf.port,
client conf.interface,
).map(Some) cors.into(),
hosts.into(),
client
).map(Some)
} }

View File

@ -18,19 +18,18 @@ use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::io; use std::io;
use io::PanicHandler;
use dir::default_data_path; use dir::default_data_path;
use ethcore_rpc::{self as rpc, RpcServerError, IpcServerError, Metadata, Origin}; use ethcore_rpc::{self as rpc, HttpServerError, IpcServerError, Metadata, Origin, AccessControlAllowOrigin, Host};
use ethcore_rpc::informant::{RpcStats, Middleware}; use ethcore_rpc::informant::{RpcStats, Middleware};
use helpers::parity_ipc_path; use helpers::parity_ipc_path;
use hyper; use hyper;
use jsonrpc_core::MetaIoHandler; use jsonrpc_core::MetaIoHandler;
use jsonrpc_core::reactor::{RpcHandler, Remote};
use rpc_apis; use rpc_apis;
use rpc_apis::ApiSet; use rpc_apis::ApiSet;
use parity_reactor::TokioRemote;
pub use ethcore_rpc::{IpcServer, Server as HttpServer}; pub use ethcore_rpc::{IpcServer, HttpServer};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct HttpConfiguration { pub struct HttpConfiguration {
@ -84,9 +83,8 @@ impl fmt::Display for IpcConfiguration {
} }
pub struct Dependencies { pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>, pub apis: Arc<rpc_apis::Dependencies>,
pub remote: Remote, pub remote: TokioRemote,
pub stats: Arc<RpcStats>, pub stats: Arc<RpcStats>,
} }
@ -123,12 +121,13 @@ pub fn setup_http_rpc_server(
allowed_hosts: Option<Vec<String>>, allowed_hosts: Option<Vec<String>>,
apis: ApiSet apis: ApiSet
) -> Result<HttpServer, String> { ) -> Result<HttpServer, String> {
let apis = setup_apis(apis, dependencies); let handler = setup_apis(apis, dependencies);
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone()); let remote = dependencies.remote.clone();
let ph = dependencies.panic_handler.clone(); let cors_domains: Option<Vec<_>> = cors_domains.map(|domains| domains.into_iter().map(AccessControlAllowOrigin::from).collect());
let start_result = rpc::start_http(url, cors_domains, allowed_hosts, ph, handler, RpcExtractor); let allowed_hosts: Option<Vec<_>> = allowed_hosts.map(|hosts| hosts.into_iter().map(Host::from).collect());
let start_result = rpc::start_http(url, cors_domains.into(), allowed_hosts.into(), handler, remote, RpcExtractor);
match start_result { match start_result {
Err(RpcServerError::IoError(err)) => match err.kind() { Err(HttpServerError::IoError(err)) => match err.kind() {
io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)), io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)),
_ => Err(format!("RPC io error: {}", err)), _ => Err(format!("RPC io error: {}", err)),
}, },
@ -143,9 +142,9 @@ pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result<Option<Ipc
} }
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer<Metadata, Middleware>, String> { pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer<Metadata, Middleware>, String> {
let apis = setup_apis(apis, dependencies); let handler = setup_apis(apis, dependencies);
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone()); let remote = dependencies.remote.clone();
match rpc::start_ipc(addr, handler) { match rpc::start_ipc(addr, handler, remote) {
Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)), Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)),
Err(any_error) => Err(format!("Rpc error: {:?}", any_error)), Err(any_error) => Err(format!("Rpc error: {:?}", any_error)),
Ok(server) => Ok(server) Ok(server) => Ok(server)

View File

@ -434,7 +434,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
}); });
let dependencies = rpc::Dependencies { let dependencies = rpc::Dependencies {
panic_handler: panic_handler.clone(),
apis: deps_for_rpc_apis.clone(), apis: deps_for_rpc_apis.clone(),
remote: event_loop.raw_remote(), remote: event_loop.raw_remote(),
stats: rpc_stats.clone(), stats: rpc_stats.clone(),
@ -446,7 +445,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
// the dapps server // the dapps server
let dapps_deps = dapps::Dependencies { let dapps_deps = dapps::Dependencies {
panic_handler: panic_handler.clone(),
apis: deps_for_rpc_apis.clone(), apis: deps_for_rpc_apis.clone(),
client: client.clone(), client: client.clone(),
sync: sync_provider.clone(), sync: sync_provider.clone(),
@ -459,7 +457,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
// the signer server // the signer server
let signer_deps = signer::Dependencies { let signer_deps = signer::Dependencies {
panic_handler: panic_handler.clone(),
apis: deps_for_rpc_apis.clone(), apis: deps_for_rpc_apis.clone(),
remote: event_loop.raw_remote(), remote: event_loop.raw_remote(),
rpc_stats: rpc_stats.clone(), rpc_stats: rpc_stats.clone(),

View File

@ -26,8 +26,7 @@ use ethcore_rpc::informant::RpcStats;
use ethcore_rpc; use ethcore_rpc;
use ethcore_signer as signer; use ethcore_signer as signer;
use helpers::replace_home; use helpers::replace_home;
use io::{ForwardPanic, PanicHandler}; use parity_reactor::TokioRemote;
use jsonrpc_core::reactor::{RpcHandler, Remote};
use rpc_apis; use rpc_apis;
use util::path::restrict_permissions_owner; use util::path::restrict_permissions_owner;
use util::H256; use util::H256;
@ -57,9 +56,8 @@ impl Default for Configuration {
} }
pub struct Dependencies { pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>, pub apis: Arc<rpc_apis::Dependencies>,
pub remote: Remote, pub remote: TokioRemote,
pub rpc_stats: Arc<RpcStats>, pub rpc_stats: Arc<RpcStats>,
} }
@ -143,9 +141,9 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str
} }
let server = server.skip_origin_validation(conf.skip_origin_validation); let server = server.skip_origin_validation(conf.skip_origin_validation);
let server = server.stats(deps.rpc_stats.clone()); let server = server.stats(deps.rpc_stats.clone());
let apis = rpc_apis::setup_rpc(deps.rpc_stats, deps.apis, rpc_apis::ApiSet::SafeContext); let handler = rpc_apis::setup_rpc(deps.rpc_stats, deps.apis, rpc_apis::ApiSet::SafeContext);
let handler = RpcHandler::new(Arc::new(apis), deps.remote); let remote = deps.remote.clone();
server.start_with_extractor(addr, handler, StandardExtractor) server.start_with_extractor(addr, handler, remote, StandardExtractor)
}; };
match start_result { match start_result {
@ -154,10 +152,7 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str
_ => Err(format!("Trusted Signer io error: {}", err)), _ => Err(format!("Trusted Signer io error: {}", err)),
}, },
Err(e) => Err(format!("Trusted Signer Error: {:?}", e)), Err(e) => Err(format!("Trusted Signer Error: {:?}", e)),
Ok(server) => { Ok(server) => Ok(server),
deps.panic_handler.forward_from(&server);
Ok(server)
},
} }
} }

View File

@ -10,18 +10,20 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
futures = "0.1" futures = "0.1"
log = "0.3" log = "0.3"
order-stat = "0.1"
rustc-serialize = "0.3"
semver = "0.5" semver = "0.5"
serde = "0.9" serde = "0.9"
serde_json = "0.9"
serde_derive = "0.9" serde_derive = "0.9"
rustc-serialize = "0.3" serde_json = "0.9"
time = "0.1" time = "0.1"
transient-hashmap = "0.1" transient-hashmap = "0.1"
order-stat = "0.1"
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-ipc-server = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-macros = { git = "https://github.com/ethcore/jsonrpc.git" }
ethcore-io = { path = "../util/io" } ethcore-io = { path = "../util/io" }
ethcore-ipc = { path = "../ipc/rpc" } ethcore-ipc = { path = "../ipc/rpc" }
ethcore-util = { path = "../util" } ethcore-util = { path = "../util" }
@ -35,11 +37,12 @@ ethjson = { path = "../json" }
ethcore-devtools = { path = "../devtools" } ethcore-devtools = { path = "../devtools" }
ethcore-light = { path = "../ethcore/light" } ethcore-light = { path = "../ethcore/light" }
parity-updater = { path = "../updater" } parity-updater = { path = "../updater" }
parity-reactor = { path = "../util/reactor" }
rlp = { path = "../util/rlp" } rlp = { path = "../util/rlp" }
fetch = { path = "../util/fetch" } fetch = { path = "../util/fetch" }
parity-reactor = { path = "../util/reactor" }
clippy = { version = "0.0.103", optional = true}
stats = { path = "../util/stats" } stats = { path = "../util/stats" }
clippy = { version = "0.0.103", optional = true}
[features] [features]
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev"] dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev"]

View File

@ -19,31 +19,32 @@
#![cfg_attr(feature="nightly", feature(plugin))] #![cfg_attr(feature="nightly", feature(plugin))]
#![cfg_attr(feature="nightly", plugin(clippy))] #![cfg_attr(feature="nightly", plugin(clippy))]
extern crate semver;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate jsonrpc_core;
extern crate jsonrpc_http_server;
extern crate ethcore_io as io;
extern crate ethcore;
extern crate ethkey;
extern crate ethcrypto as crypto;
extern crate ethstore;
extern crate ethsync;
extern crate ethash;
extern crate ethcore_light as light;
extern crate transient_hashmap;
extern crate jsonrpc_ipc_server as ipc;
extern crate ethcore_ipc;
extern crate time;
extern crate rlp;
extern crate fetch;
extern crate futures; extern crate futures;
extern crate order_stat; extern crate order_stat;
extern crate parity_updater as updater; extern crate rustc_serialize;
extern crate semver;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate transient_hashmap;
extern crate jsonrpc_core;
pub extern crate jsonrpc_http_server as http;
pub extern crate jsonrpc_ipc_server as ipc;
extern crate ethash;
extern crate ethcore;
extern crate ethcore_io as io;
extern crate ethcore_ipc;
extern crate ethcore_light as light;
extern crate ethcrypto as crypto;
extern crate ethkey;
extern crate ethstore;
extern crate ethsync;
extern crate fetch;
extern crate parity_reactor; extern crate parity_reactor;
extern crate parity_updater as updater;
extern crate rlp;
extern crate stats; extern crate stats;
#[macro_use] #[macro_use]
@ -60,57 +61,50 @@ extern crate ethjson;
#[cfg(test)] #[cfg(test)]
extern crate ethcore_devtools as devtools; extern crate ethcore_devtools as devtools;
use std::sync::Arc; pub mod v1;
use std::net::SocketAddr;
use io::PanicHandler;
use jsonrpc_core::reactor::RpcHandler;
pub use ipc::{Server as IpcServer, Error as IpcServerError}; pub use ipc::{Server as IpcServer, Error as IpcServerError};
pub use jsonrpc_http_server::{ServerBuilder, Server, RpcServerError, HttpMetaExtractor}; pub use http::{HttpMetaExtractor, Server as HttpServer, Error as HttpServerError, AccessControlAllowOrigin, Host};
pub mod v1;
pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, Metadata, Origin, informant, dispatch}; pub use v1::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, Metadata, Origin, informant, dispatch};
pub use v1::block_import::is_major_importing; pub use v1::block_import::is_major_importing;
use std::net::SocketAddr;
use http::tokio_core;
/// Start http server asynchronously and returns result with `Server` handle on success or an error. /// Start http server asynchronously and returns result with `Server` handle on success or an error.
pub fn start_http<M, T, S>( pub fn start_http<M, S, H, T>(
addr: &SocketAddr, addr: &SocketAddr,
cors_domains: Option<Vec<String>>, cors_domains: http::DomainsValidation<http::AccessControlAllowOrigin>,
allowed_hosts: Option<Vec<String>>, allowed_hosts: http::DomainsValidation<http::Host>,
panic_handler: Arc<PanicHandler>, handler: H,
handler: RpcHandler<M, S>, remote: tokio_core::reactor::Remote,
extractor: T, extractor: T,
) -> Result<Server, RpcServerError> where ) -> Result<HttpServer, HttpServerError> where
M: jsonrpc_core::Metadata, M: jsonrpc_core::Metadata,
S: jsonrpc_core::Middleware<M>, S: jsonrpc_core::Middleware<M>,
H: Into<jsonrpc_core::MetaIoHandler<M, S>>,
T: HttpMetaExtractor<M>, T: HttpMetaExtractor<M>,
{ {
http::ServerBuilder::new(handler)
let cors_domains = cors_domains.map(|domains| { .event_loop_remote(remote)
domains.into_iter() .meta_extractor(extractor)
.map(|v| match v.as_str() {
"*" => jsonrpc_http_server::AccessControlAllowOrigin::Any,
"null" => jsonrpc_http_server::AccessControlAllowOrigin::Null,
v => jsonrpc_http_server::AccessControlAllowOrigin::Value(v.into()),
})
.collect()
});
ServerBuilder::with_rpc_handler(handler)
.meta_extractor(Arc::new(extractor))
.cors(cors_domains.into()) .cors(cors_domains.into())
.allowed_hosts(allowed_hosts.into()) .allowed_hosts(allowed_hosts.into())
.panic_handler(move || {
panic_handler.notify_all("Panic in RPC thread.".to_owned());
})
.start_http(addr) .start_http(addr)
} }
/// Start ipc server asynchronously and returns result with `Server` handle on success or an error. /// Start ipc server asynchronously and returns result with `Server` handle on success or an error.
pub fn start_ipc<M: jsonrpc_core::Metadata, S: jsonrpc_core::Middleware<M>>( pub fn start_ipc<M, S, H>(
addr: &str, addr: &str,
handler: RpcHandler<M, S>, handler: H,
) -> Result<ipc::Server<M, S>, ipc::Error> { remote: tokio_core::reactor::Remote,
let server = ipc::Server::with_rpc_handler(addr, handler)?; ) -> Result<ipc::Server<M, S>, ipc::Error> where
M: jsonrpc_core::Metadata,
S: jsonrpc_core::Middleware<M>,
H: Into<jsonrpc_core::MetaIoHandler<M, S>>,
{
let server = ipc::Server::with_remote(addr, handler, ipc::UninitializedRemote::Shared(remote))?;
server.run_async()?; server.run_async()?;
Ok(server) Ok(server)
} }

View File

@ -875,7 +875,7 @@ fn rpc_eth_send_transaction_with_bad_to() {
"id": 1 "id": 1
}"#; }"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid length.","data":null},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid length."},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
} }
@ -1058,7 +1058,7 @@ fn rpc_get_work_returns_no_work_if_cant_mine() {
eth_tester.client.set_queue_size(10); eth_tester.client.set_queue_size(10);
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Still syncing.","data":null},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Still syncing."},"id":1}"#;
assert_eq!(eth_tester.io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(eth_tester.io.handle_request_sync(request), Some(response.to_owned()));
} }
@ -1117,6 +1117,6 @@ fn rpc_get_work_should_timeout() {
// Request with timeout of 10 seconds. This should fail. // Request with timeout of 10 seconds. This should fail.
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": ["10"], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": ["10"], "id": 1}"#;
let err_response = r#"{"jsonrpc":"2.0","error":{"code":-32003,"message":"Work has not changed.","data":null},"id":1}"#; let err_response = r#"{"jsonrpc":"2.0","error":{"code":-32003,"message":"Work has not changed."},"id":1}"#;
assert_eq!(eth_tester.io.handle_request_sync(request), Some(err_response.to_owned())); assert_eq!(eth_tester.io.handle_request_sync(request), Some(err_response.to_owned()));
} }

View File

@ -346,7 +346,7 @@ fn rpc_parity_unsigned_transactions_count_when_signer_disabled() {
let io = deps.default_client(); let io = deps.default_client();
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
} }
@ -382,7 +382,7 @@ fn rpc_parity_signer_port() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -400,7 +400,7 @@ fn rpc_parity_dapps_port() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));
@ -418,7 +418,7 @@ fn rpc_parity_dapps_interface() {
// when // when
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#; let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#;
let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#; let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#;
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available."},"id":1}"#;
// then // then
assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned()));

View File

@ -230,7 +230,7 @@ fn should_be_able_to_kill_account() {
let address = accounts[0]; let address = accounts[0];
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_killAccount", "params": ["0xf00baba2f00baba2f00baba2f00baba2f00baba2"], "id": 1}}"#); let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_killAccount", "params": ["0xf00baba2f00baba2f00baba2f00baba2f00baba2"], "id": 1}}"#);
let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid length 1, expected a tuple of size 2","data":null},"id":1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid length 1, expected a tuple of size 2"},"id":1}"#;
let res = tester.io.handle_request_sync(&request); let res = tester.io.handle_request_sync(&request);
assert_eq!(res, Some(response.into())); assert_eq!(res, Some(response.into()));

View File

@ -13,6 +13,7 @@ rustc_version = "0.1"
[dependencies] [dependencies]
rand = "0.3.14" rand = "0.3.14"
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" }
jsonrpc-server-utils = { git = "https://github.com/ethcore/jsonrpc.git" }
log = "0.3" log = "0.3"
env_logger = "0.3" env_logger = "0.3"
parity-dapps-glue = { version = "1.4", optional = true } parity-dapps-glue = { version = "1.4", optional = true }

View File

@ -30,21 +30,23 @@
//! //!
//! ``` //! ```
//! extern crate jsonrpc_core; //! extern crate jsonrpc_core;
//! extern crate jsonrpc_server_utils;
//! extern crate ethcore_signer; //! extern crate ethcore_signer;
//! extern crate ethcore_rpc; //! extern crate ethcore_rpc;
//! //!
//! use std::sync::Arc; //! use std::sync::Arc;
//! use jsonrpc_core::IoHandler; //! use jsonrpc_core::IoHandler;
//! use jsonrpc_core::reactor::RpcEventLoop; //! use jsonrpc_server_utils::reactor::RpcEventLoop;
//! use ethcore_signer::ServerBuilder; //! use ethcore_signer::ServerBuilder;
//! use ethcore_rpc::ConfirmationsQueue; //! use ethcore_rpc::ConfirmationsQueue;
//! //!
//! fn main() { //! fn main() {
//! let queue = Arc::new(ConfirmationsQueue::default()); //! let queue = Arc::new(ConfirmationsQueue::default());
//! let io = Arc::new(IoHandler::new().into()); //! let io = IoHandler::default();
//! let event_loop = RpcEventLoop::spawn(); //! let event_loop = RpcEventLoop::spawn().unwrap();
//! let remote = event_loop.remote();
//! let _server = ServerBuilder::new(queue, "/tmp/authcodes".into()) //! let _server = ServerBuilder::new(queue, "/tmp/authcodes".into())
//! .start("127.0.0.1:8084".parse().unwrap(), event_loop.handler(io)); //! .start("127.0.0.1:8084".parse().unwrap(), io, remote);
//! } //! }
//! ``` //! ```
@ -57,6 +59,7 @@ extern crate ethcore_util as util;
extern crate ethcore_rpc as rpc; extern crate ethcore_rpc as rpc;
extern crate ethcore_io as io; extern crate ethcore_io as io;
extern crate jsonrpc_core; extern crate jsonrpc_core;
extern crate jsonrpc_server_utils;
extern crate ws; extern crate ws;
extern crate ethcore_devtools as devtools; extern crate ethcore_devtools as devtools;

View File

@ -22,7 +22,7 @@ use devtools::RandomTempPath;
use rpc::ConfirmationsQueue; use rpc::ConfirmationsQueue;
use jsonrpc_core::IoHandler; use jsonrpc_core::IoHandler;
use jsonrpc_core::reactor::RpcEventLoop; use jsonrpc_server_utils::reactor::RpcEventLoop;
use rand; use rand;
use ServerBuilder; use ServerBuilder;
@ -70,9 +70,10 @@ pub fn serve() -> (ServerLoop, usize, GuardedAuthCodes) {
let queue = Arc::new(ConfirmationsQueue::default()); let queue = Arc::new(ConfirmationsQueue::default());
let builder = ServerBuilder::new(queue, path.to_path_buf()); let builder = ServerBuilder::new(queue, path.to_path_buf());
let port = 35000 + rand::random::<usize>() % 10000; let port = 35000 + rand::random::<usize>() % 10000;
let event_loop = RpcEventLoop::spawn(); let event_loop = RpcEventLoop::spawn().unwrap();
let handler = event_loop.handler(Arc::new(IoHandler::default().into())); let io = IoHandler::default();
let server = builder.start(format!("127.0.0.1:{}", port).parse().unwrap(), handler).unwrap(); let remote = event_loop.remote();
let server = builder.start(format!("127.0.0.1:{}", port).parse().unwrap(), io, remote).unwrap();
let res = ServerLoop { let res = ServerLoop {
server: server, server: server,
event_loop: event_loop, event_loop: event_loop,

View File

@ -26,8 +26,8 @@ use std::thread;
use std; use std;
use io::{PanicHandler, OnPanicListener, MayPanic}; use io::{PanicHandler, OnPanicListener, MayPanic};
use jsonrpc_core::{Metadata, Middleware}; use jsonrpc_core::{Metadata, Middleware, MetaIoHandler};
use jsonrpc_core::reactor::RpcHandler; use jsonrpc_server_utils::tokio_core::reactor::Remote;
use rpc::{ConfirmationsQueue}; use rpc::{ConfirmationsQueue};
use rpc::informant::RpcStats; use rpc::informant::RpcStats;
@ -92,21 +92,28 @@ impl ServerBuilder {
/// Starts a new `WebSocket` server in separate thread. /// Starts a new `WebSocket` server in separate thread.
/// Returns a `Server` handle which closes the server when droped. /// Returns a `Server` handle which closes the server when droped.
pub fn start<M: Metadata, S: Middleware<M>>(self, addr: SocketAddr, handler: RpcHandler<M, S>) -> Result<Server, ServerError> { pub fn start<M: Metadata, S: Middleware<M>, H: Into<MetaIoHandler<M, S>>>(
self.start_with_extractor(addr, handler, NoopExtractor) self,
addr: SocketAddr,
handler: H,
remote: Remote,
) -> Result<Server, ServerError> {
self.start_with_extractor(addr, handler, remote, NoopExtractor)
} }
/// Starts a new `WebSocket` server in separate thread. /// Starts a new `WebSocket` server in separate thread.
/// Returns a `Server` handle which closes the server when droped. /// Returns a `Server` handle which closes the server when droped.
pub fn start_with_extractor<M: Metadata, S: Middleware<M>, T: session::MetaExtractor<M>>( pub fn start_with_extractor<M: Metadata, S: Middleware<M>, H: Into<MetaIoHandler<M, S>>, T: session::MetaExtractor<M>>(
self, self,
addr: SocketAddr, addr: SocketAddr,
handler: RpcHandler<M, S>, handler: H,
remote: Remote,
meta_extractor: T, meta_extractor: T,
) -> Result<Server, ServerError> { ) -> Result<Server, ServerError> {
Server::start( Server::start(
addr, addr,
handler, handler.into(),
remote,
self.queue, self.queue,
self.authcodes_path, self.authcodes_path,
self.skip_origin_validation, self.skip_origin_validation,
@ -136,7 +143,8 @@ impl Server {
/// Returns a `Server` handle which closes the server when droped. /// Returns a `Server` handle which closes the server when droped.
fn start<M: Metadata, S: Middleware<M>, T: session::MetaExtractor<M>>( fn start<M: Metadata, S: Middleware<M>, T: session::MetaExtractor<M>>(
addr: SocketAddr, addr: SocketAddr,
handler: RpcHandler<M, S>, handler: MetaIoHandler<M, S>,
remote: Remote,
queue: Arc<ConfirmationsQueue>, queue: Arc<ConfirmationsQueue>,
authcodes_path: PathBuf, authcodes_path: PathBuf,
skip_origin_validation: bool, skip_origin_validation: bool,
@ -156,7 +164,7 @@ impl Server {
let origin = format!("{}", addr); let origin = format!("{}", addr);
let port = addr.port(); let port = addr.port();
let ws = ws::Builder::new().with_settings(config).build( let ws = ws::Builder::new().with_settings(config).build(
session::Factory::new(handler, origin, port, authcodes_path, skip_origin_validation, stats, meta_extractor) session::Factory::new(handler, remote, origin, port, authcodes_path, skip_origin_validation, stats, meta_extractor)
)?; )?;
let panic_handler = PanicHandler::new_in_arc(); let panic_handler = PanicHandler::new_in_arc();

View File

@ -21,8 +21,9 @@ use std::sync::Arc;
use std::str::FromStr; use std::str::FromStr;
use authcode_store::AuthCodes; use authcode_store::AuthCodes;
use jsonrpc_core::{Metadata, Middleware}; use jsonrpc_core::{Metadata, Middleware, MetaIoHandler};
use jsonrpc_core::reactor::RpcHandler; use jsonrpc_core::futures::Future;
use jsonrpc_server_utils::tokio_core::reactor::Remote;
use rpc::informant::RpcStats; use rpc::informant::RpcStats;
use util::{H256, version}; use util::{H256, version};
use ws; use ws;
@ -145,7 +146,8 @@ pub struct Session<M: Metadata, S: Middleware<M>, T> {
self_origin: String, self_origin: String,
self_port: u16, self_port: u16,
authcodes_path: PathBuf, authcodes_path: PathBuf,
handler: RpcHandler<M, S>, handler: Arc<MetaIoHandler<M, S>>,
remote: Remote,
file_handler: Arc<ui::Handler>, file_handler: Arc<ui::Handler>,
stats: Option<Arc<RpcStats>>, stats: Option<Arc<RpcStats>>,
meta_extractor: T, meta_extractor: T,
@ -237,7 +239,7 @@ impl<M: Metadata, S: Middleware<M>, T: MetaExtractor<M>> ws::Handler for Session
// TODO [ToDr] Move to on_connect // TODO [ToDr] Move to on_connect
let metadata = self.meta_extractor.extract_metadata(&self.session_id); let metadata = self.meta_extractor.extract_metadata(&self.session_id);
self.handler.handle_request(req, metadata, move |response| { let future = self.handler.handle_request(req, metadata).map(move |response| {
if let Some(result) = response { if let Some(result) = response {
let res = out.send(result); let res = out.send(result);
if let Err(e) = res { if let Err(e) = res {
@ -245,12 +247,14 @@ impl<M: Metadata, S: Middleware<M>, T: MetaExtractor<M>> ws::Handler for Session
} }
} }
}); });
self.remote.spawn(move |_| future);
Ok(()) Ok(())
} }
} }
pub struct Factory<M: Metadata, S: Middleware<M>, T> { pub struct Factory<M: Metadata, S: Middleware<M>, T> {
handler: RpcHandler<M, S>, handler: Arc<MetaIoHandler<M, S>>,
remote: Remote,
skip_origin_validation: bool, skip_origin_validation: bool,
self_origin: String, self_origin: String,
self_port: u16, self_port: u16,
@ -262,7 +266,8 @@ pub struct Factory<M: Metadata, S: Middleware<M>, T> {
impl<M: Metadata, S: Middleware<M>, T> Factory<M, S, T> { impl<M: Metadata, S: Middleware<M>, T> Factory<M, S, T> {
pub fn new( pub fn new(
handler: RpcHandler<M, S>, handler: MetaIoHandler<M, S>,
remote: Remote,
self_origin: String, self_origin: String,
self_port: u16, self_port: u16,
authcodes_path: PathBuf, authcodes_path: PathBuf,
@ -271,7 +276,8 @@ impl<M: Metadata, S: Middleware<M>, T> Factory<M, S, T> {
meta_extractor: T, meta_extractor: T,
) -> Self { ) -> Self {
Factory { Factory {
handler: handler, handler: Arc::new(handler),
remote: remote,
skip_origin_validation: skip_origin_validation, skip_origin_validation: skip_origin_validation,
self_origin: self_origin, self_origin: self_origin,
self_port: self_port, self_port: self_port,
@ -293,6 +299,7 @@ impl<M: Metadata, S: Middleware<M>, T: MetaExtractor<M>> ws::Factory for Factory
session_id: 0.into(), session_id: 0.into(),
out: sender, out: sender,
handler: self.handler.clone(), handler: self.handler.clone(),
remote: self.remote.clone(),
skip_origin_validation: self.skip_origin_validation, skip_origin_validation: self.skip_origin_validation,
self_origin: self.self_origin.clone(), self_origin: self.self_origin.clone(),
self_port: self.self_port, self_port: self.self_port,

View File

@ -44,8 +44,8 @@ pub use traits::{
}; };
use jsonrpc_tcp_server::{ use jsonrpc_tcp_server::{
Server as JsonRpcServer, RequestContext, MetaExtractor, Dispatcher, Server as JsonRpcServer, ServerBuilder as JsonRpcServerBuilder,
PushMessageError RequestContext, MetaExtractor, Dispatcher, PushMessageError,
}; };
use jsonrpc_core::{MetaIoHandler, Params, to_value, Value, Metadata, Compatibility}; use jsonrpc_core::{MetaIoHandler, Params, to_value, Value, Metadata, Compatibility};
use jsonrpc_macros::IoDelegate; use jsonrpc_macros::IoDelegate;
@ -57,6 +57,8 @@ use util::{H256, Hashable, RwLock, RwLockReadGuard};
type RpcResult = BoxFuture<jsonrpc_core::Value, jsonrpc_core::Error>; type RpcResult = BoxFuture<jsonrpc_core::Value, jsonrpc_core::Error>;
const NOTIFY_COUNTER_INITIAL: u32 = 16;
struct StratumRpc { struct StratumRpc {
stratum: RwLock<Option<Arc<Stratum>>>, stratum: RwLock<Option<Arc<Stratum>>>,
} }
@ -112,7 +114,7 @@ impl MetaExtractor<SocketMetadata> for PeerMetaExtractor {
} }
pub struct Stratum { pub struct Stratum {
rpc_server: JsonRpcServer<SocketMetadata>, rpc_server: Option<JsonRpcServer>,
/// Subscribed clients /// Subscribed clients
subscribers: RwLock<Vec<SocketAddr>>, subscribers: RwLock<Vec<SocketAddr>>,
/// List of workers supposed to receive job update /// List of workers supposed to receive job update
@ -129,7 +131,11 @@ pub struct Stratum {
tcp_dispatcher: Dispatcher, tcp_dispatcher: Dispatcher,
} }
const NOTIFY_COUNTER_INITIAL: u32 = 16; impl Drop for Stratum {
fn drop(&mut self) {
self.rpc_server.take().map(|server| server.close());
}
}
impl Stratum { impl Stratum {
pub fn start( pub fn start(
@ -148,12 +154,14 @@ impl Stratum {
let mut handler = MetaIoHandler::<SocketMetadata>::with_compatibility(Compatibility::Both); let mut handler = MetaIoHandler::<SocketMetadata>::with_compatibility(Compatibility::Both);
handler.extend_with(delegate); handler.extend_with(delegate);
let server = JsonRpcServer::new(addr.clone(), Arc::new(handler)) let server = JsonRpcServerBuilder::new(handler)
.extractor(Arc::new(PeerMetaExtractor) as Arc<MetaExtractor<SocketMetadata>>); .session_meta_extractor(PeerMetaExtractor);
let tcp_dispatcher = server.dispatcher();
let server = server.start(addr)?;
let stratum = Arc::new(Stratum { let stratum = Arc::new(Stratum {
tcp_dispatcher: server.dispatcher(), tcp_dispatcher: tcp_dispatcher,
rpc_server: server, rpc_server: Some(server),
subscribers: RwLock::new(Vec::new()), subscribers: RwLock::new(Vec::new()),
job_que: RwLock::new(HashSet::new()), job_que: RwLock::new(HashSet::new()),
dispatcher: dispatcher, dispatcher: dispatcher,
@ -162,10 +170,6 @@ impl Stratum {
notify_counter: RwLock::new(NOTIFY_COUNTER_INITIAL), notify_counter: RwLock::new(NOTIFY_COUNTER_INITIAL),
}); });
*rpc.stratum.write() = Some(stratum.clone()); *rpc.stratum.write() = Some(stratum.clone());
let running_stratum = stratum.clone();
::std::thread::spawn(move || running_stratum.rpc_server.run());
Ok(stratum) Ok(stratum)
} }

View File

@ -24,7 +24,7 @@ use std::thread;
use std::sync::mpsc; use std::sync::mpsc;
use std::time::Duration; use std::time::Duration;
use futures::{Future, IntoFuture}; use futures::{Future, IntoFuture};
use self::tokio_core::reactor::{Remote as TokioRemote, Timeout}; pub use tokio_core::reactor::{Remote as TokioRemote, Timeout};
/// Event Loop for futures. /// Event Loop for futures.
/// Wrapper around `tokio::reactor::Core`. /// Wrapper around `tokio::reactor::Core`.
@ -47,7 +47,7 @@ impl EventLoop {
let remote = rx.recv().expect("tx is transfered to a newly spawned thread."); let remote = rx.recv().expect("tx is transfered to a newly spawned thread.");
EventLoop { EventLoop {
remote: Remote{ remote: Remote {
inner: Mode::Tokio(remote), inner: Mode::Tokio(remote),
}, },
handle: EventLoopHandle { handle: EventLoopHandle {