Merge branch 'master' into 0.7.2_patch
This commit is contained in:
commit
389e6004d1
@ -1,4 +1,7 @@
|
||||
language: rust
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
|
@ -2,6 +2,13 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## unreleased
|
||||
### Fixed
|
||||
- Randomized ports for client connections and message ids, #23
|
||||
|
||||
### Changed
|
||||
- Cleaned up the Server implementation to isolate connection handlers
|
||||
|
||||
## 0.7.2 2016-08-10
|
||||
### Fixed
|
||||
- Issue #28: RRSIG validation of wildcards, label length > wildcard length
|
||||
|
201
Cargo.lock
generated
201
Cargo.lock
generated
@ -2,24 +2,25 @@
|
||||
name = "trust-dns"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"backtrace 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"data-encoding 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.1.12 (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)",
|
||||
"openssl 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusqlite 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -27,15 +28,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -43,8 +45,8 @@ name = "backtrace-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -69,10 +71,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.2.21"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -86,16 +88,16 @@ name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.6.78"
|
||||
version = "0.6.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"regex 0.1.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -105,39 +107,40 @@ name = "error-chain"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.26"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "gdi32-sys"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.15"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.9"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -153,7 +156,7 @@ name = "libsqlite3-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -180,28 +183,23 @@ name = "memchr"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mempool"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -209,71 +207,98 @@ name = "miow"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.23"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.7.8"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys-extras 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys-extras 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.7.8"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys-extras"
|
||||
version = "0.7.8"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -294,24 +319,24 @@ name = "rand"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.62"
|
||||
version = "0.1.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mempool 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.3.1"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -320,12 +345,17 @@ version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libsqlite3-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.19"
|
||||
@ -349,19 +379,36 @@ dependencies = [
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.1.28"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -369,10 +416,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "user32-sys"
|
||||
version = "0.1.2"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -383,7 +430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -396,7 +443,7 @@ name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -73,6 +73,7 @@ log = "^0.3.5"
|
||||
mio = "^0.5.1"
|
||||
openssl = "^0.7.8"
|
||||
openssl-sys = "^0.7.8"
|
||||
rand = "^0.3"
|
||||
rustc-serialize = "^0.3.18"
|
||||
rusqlite = "^0.7.3"
|
||||
time = "^0.1.35"
|
||||
|
13
README.md
13
README.md
@ -127,12 +127,21 @@ presume that the trust-dns repos have already been synced to the local system:
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- openssl development libraries are necessary
|
||||
- openssl development libraries
|
||||
- sqlite3 development libraries
|
||||
|
||||
Mac OS X: using homebrew
|
||||
|
||||
|
||||
$ brew install openssl
|
||||
$ brew link --force openssl
|
||||
$ brew install sqlite
|
||||
|
||||
Debian-based (includes Ubuntu & Raspbian): using apt-get
|
||||
|
||||
$ apt-get install openssl
|
||||
$ apt-get install libssl-dev
|
||||
$ apt-get install libsqlite3-dev
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
|
@ -12,13 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc as Rc;
|
||||
|
||||
use chrono::UTC;
|
||||
use data_encoding::base32hex;
|
||||
use openssl::crypto::pkey::Role;
|
||||
use rand;
|
||||
|
||||
use ::error::*;
|
||||
use ::rr::{DNSClass, RecordType, Record, RData};
|
||||
@ -34,7 +35,6 @@ use ::client::ClientConnection;
|
||||
/// disallow TCP in some cases, so if TCP double check if UDP works.
|
||||
pub struct Client<C: ClientConnection> {
|
||||
client_connection: RefCell<C>,
|
||||
next_id: Cell<u16>,
|
||||
trust_anchor: TrustAnchor,
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ impl<C: ClientConnection> Client<C> {
|
||||
/// * `client_connection` - the client_connection to use for all communication
|
||||
pub fn new(client_connection: C) -> Client<C> {
|
||||
Client{ client_connection: RefCell::new(client_connection),
|
||||
next_id: Cell::new(1037),
|
||||
trust_anchor: TrustAnchor::default() }
|
||||
}
|
||||
|
||||
@ -59,7 +58,6 @@ impl<C: ClientConnection> Client<C> {
|
||||
/// root public_key.
|
||||
pub fn with_trust_anchor(client_connection: C, trust_anchor: TrustAnchor) -> Client<C> {
|
||||
Client{ client_connection: RefCell::new(client_connection),
|
||||
next_id: Cell::new(1037),
|
||||
trust_anchor: trust_anchor }
|
||||
}
|
||||
|
||||
@ -494,7 +492,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
let id = self.next_id();
|
||||
let id: u16 = rand::random();
|
||||
// TODO make recursion a parameter
|
||||
message.id(id).message_type(MessageType::Query).op_code(OpCode::Query).recursion_desired(true);
|
||||
|
||||
@ -566,7 +564,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
let mut prerequisite = Record::with(record.get_name().clone(), record.get_rr_type(), 0);
|
||||
@ -642,7 +640,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
if must_exist {
|
||||
@ -729,7 +727,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
// make sure the record is what is expected
|
||||
@ -816,7 +814,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
// the class must be none for delete
|
||||
@ -893,7 +891,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
// the class must be none for an rrset delete
|
||||
@ -962,7 +960,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
// build the message
|
||||
let mut message: Message = Message::new();
|
||||
message.id(self.next_id()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.id(rand::random()).message_type(MessageType::Query).op_code(OpCode::Update).recursion_desired(false);
|
||||
message.add_zone(zone);
|
||||
|
||||
// the TTL shoudl be 0
|
||||
@ -1018,13 +1016,6 @@ impl<C: ClientConnection> Client<C> {
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// increments the next_id for use in messages
|
||||
fn next_id(&self) -> u16 {
|
||||
let id = self.next_id.get();
|
||||
self.next_id.set(id + 1);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::error::Error as StdError;
|
||||
use std::io::Error as IoError;
|
||||
|
||||
use ::op::ResponseCode;
|
||||
|
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
use std::error::Error as StdError;
|
||||
use std::io;
|
||||
|
||||
use toml::ParserError;
|
||||
|
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::error::Error as StdError;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
use openssl::ssl::error::SslError;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::error::Error as StdError;
|
||||
|
||||
error_chain! {
|
||||
// The type defined for this error. These are the conventional
|
||||
// and recommended names, but they can be arbitrarily chosen.
|
||||
|
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
use std::error::Error as StdError;
|
||||
use std::num;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
use std::error::Error as StdError;
|
||||
use std::num;
|
||||
use std::io;
|
||||
use std::net::AddrParseError;
|
||||
|
@ -4,8 +4,6 @@
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
use std::error::Error as StdError;
|
||||
|
||||
use rusqlite;
|
||||
|
||||
use super::{decode_error, encode_error};
|
||||
|
@ -33,6 +33,7 @@ extern crate data_encoding;
|
||||
extern crate mio;
|
||||
extern crate openssl;
|
||||
extern crate openssl_sys;
|
||||
extern crate rand;
|
||||
extern crate rusqlite;
|
||||
extern crate rustc_serialize;
|
||||
extern crate time;
|
||||
|
@ -19,7 +19,7 @@ use std::io;
|
||||
use std::sync::Arc;
|
||||
use std::cell::Cell;
|
||||
|
||||
use mio::{Token, EventLoop, Handler, EventSet, PollOpt, TryAccept};
|
||||
use mio::{Token, Evented, EventLoop, Handler, EventSet, PollOpt};
|
||||
use mio::tcp::{TcpListener, TcpStream};
|
||||
use mio::udp::UdpSocket;
|
||||
|
||||
@ -31,13 +31,7 @@ use ::udp::{UdpHandler, UdpState};
|
||||
|
||||
// TODO, might be cool to store buffers for later usage...
|
||||
pub struct Server {
|
||||
udp_sockets: HashMap<Token, UdpSocket>,
|
||||
// for each udp_socket, there is a set of udp_responses. The token is the same as the one
|
||||
// registered in udp_sockets above, and the vector is the set of addresses for which we have
|
||||
// responses.
|
||||
udp_requests: HashMap<Token, VecDeque<UdpHandler>>,
|
||||
tcp_sockets: HashMap<Token, TcpListener>,
|
||||
tcp_handlers: HashMap<Token, TcpHandler>,
|
||||
handlers: HashMap<Token, DnsHandlerType>,
|
||||
next_token: Cell<usize>,
|
||||
catalog: Arc<Catalog>, // should the catalog just be static?
|
||||
}
|
||||
@ -45,10 +39,7 @@ pub struct Server {
|
||||
impl Server {
|
||||
pub fn new(catalog: Catalog) -> Server {
|
||||
Server {
|
||||
udp_sockets: HashMap::new(),
|
||||
udp_requests: HashMap::new(),
|
||||
tcp_sockets: HashMap::new(),
|
||||
tcp_handlers: HashMap::new(),
|
||||
handlers: HashMap::new(),
|
||||
next_token: Cell::new(0),
|
||||
catalog: Arc::new(catalog),
|
||||
}
|
||||
@ -58,9 +49,7 @@ impl Server {
|
||||
for _ in 0..100 {
|
||||
self.next_token.set(self.next_token.get()+1);
|
||||
let token: Token = Token(self.next_token.get());
|
||||
if self.tcp_sockets.contains_key(&token) { continue }
|
||||
else if self.tcp_handlers.contains_key(&token) { continue }
|
||||
else if self.udp_sockets.contains_key(&token) { continue }
|
||||
if self.handlers.contains_key(&token) { continue }
|
||||
|
||||
// ok, safe to use
|
||||
return token;
|
||||
@ -72,14 +61,14 @@ impl Server {
|
||||
/// register a UDP socket. Should be bound before calling this.
|
||||
pub fn register_socket(&mut self, socket: UdpSocket) {
|
||||
let token = self.next_token();
|
||||
self.udp_sockets.insert(token, socket);
|
||||
self.handlers.insert(token, DnsHandlerType::UdpSocket((socket, VecDeque::new())));
|
||||
}
|
||||
|
||||
/// register a TcpListener to the Server. This should already be bound to either an IPv6 or an
|
||||
/// IPv4 address.
|
||||
pub fn register_listener(&mut self, listener: TcpListener) {
|
||||
let token = self.next_token();
|
||||
self.tcp_sockets.insert(token, listener);
|
||||
self.handlers.insert(token, DnsHandlerType::TcpListener(listener));
|
||||
}
|
||||
|
||||
/// TODO how to do threads? should we do a bunch of listener threads and then query threads?
|
||||
@ -90,8 +79,13 @@ impl Server {
|
||||
let mut event_loop: EventLoop<Self> = try!(EventLoop::new());
|
||||
|
||||
// registering these on non-writable events, since these are the listeners.
|
||||
for (ref token, ref socket) in &self.udp_sockets { try!(event_loop.register(*socket, **token, !EventSet::writable(), PollOpt::all())); }
|
||||
for (ref token, ref socket) in &self.tcp_sockets { try!(event_loop.register(*socket, **token, !EventSet::writable(), PollOpt::all())); }
|
||||
for (token, handler) in self.handlers.iter() {
|
||||
match *handler {
|
||||
DnsHandlerType::UdpSocket(ref handler) => try!(event_loop.register(handler.get_socket(), *token, !EventSet::writable(), PollOpt::all())),
|
||||
DnsHandlerType::TcpListener(ref handler) => try!(event_loop.register(handler.get_socket(), *token, !EventSet::writable(), PollOpt::all())),
|
||||
DnsHandlerType::TcpHandler(_) => panic!("tcp handlers should not have been registered yet"),
|
||||
}
|
||||
}
|
||||
|
||||
try!(event_loop.run(self));
|
||||
|
||||
@ -140,175 +134,279 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
// each dns handler type is used for managing client requests.
|
||||
enum DnsHandlerType {
|
||||
// the deque represents responses that need to be sent back to the client
|
||||
// as of now this these are local requests, but in the future these will be resolver based
|
||||
// responses, which will have some time between resolve and response
|
||||
UdpSocket((UdpSocket, VecDeque<UdpHandler>)),
|
||||
// Inbound TCP connections
|
||||
TcpListener(TcpListener),
|
||||
// Handlers for the TCP connections
|
||||
TcpHandler(TcpHandler),
|
||||
}
|
||||
|
||||
/// Handler for DNS requests
|
||||
trait DnsHandler {
|
||||
/// Called when the Evented of the Handler is woken up on activity
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `events` - the set of events that that woke this socket up
|
||||
/// * `catalog` - the local catalog for lookups
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// Returns a tuple of the next event_set for this handler, and/or a new handler to add to the
|
||||
/// the event_loop. If the first of the tuple is None, self will be removed from the event_loop.
|
||||
/// If the second is None, nothing will happen, otherwise the new handler will be added to the
|
||||
/// event_loop.
|
||||
fn handle(&mut self, events: EventSet, catalog: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>);
|
||||
|
||||
/// returns the Evented which self wraps.
|
||||
fn get_socket(&self) -> &Evented;
|
||||
}
|
||||
|
||||
impl DnsHandler for DnsHandlerType {
|
||||
fn handle(&mut self, events: EventSet, catalog: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>) {
|
||||
match *self {
|
||||
DnsHandlerType::UdpSocket(ref mut udp_handler) => udp_handler.handle(events, catalog),
|
||||
DnsHandlerType::TcpListener(ref mut tcp_listener) => tcp_listener.handle(events, catalog),
|
||||
DnsHandlerType::TcpHandler(ref mut tcp_handler) => tcp_handler.handle(events, catalog),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_socket(&self) -> &Evented {
|
||||
match *self {
|
||||
DnsHandlerType::UdpSocket(ref udp_handler) => udp_handler.get_socket() as &Evented,
|
||||
DnsHandlerType::TcpListener(ref tcp_listener) => tcp_listener.get_socket() as &Evented,
|
||||
DnsHandlerType::TcpHandler(ref tcp_handler) => tcp_handler.get_socket() as &Evented,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DnsHandler for TcpListener {
|
||||
fn handle(&mut self, events: EventSet, _: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>) {
|
||||
if events.is_error() { panic!("unexpected error state on: {:?}", self) }
|
||||
else if events.is_hup() { panic!("listening socket hungup: {:?}", self) }
|
||||
else if events.is_readable() || events.is_writable() {
|
||||
// there's a new connection coming in
|
||||
// give it a new token and insert the stream on the eventlistener
|
||||
// then store in the map for reference when dealing with new streams
|
||||
for _ in 0..100 { // loop a max of 100 times, don't want to starve the responses.
|
||||
match self.accept() {
|
||||
Ok(Some((stream, addr))) => {
|
||||
info!("new tcp connection from: {}", addr);
|
||||
return (Some(EventSet::all()), Some((DnsHandlerType::TcpHandler(TcpHandler::new_server_handler(stream)),
|
||||
!EventSet::writable())))
|
||||
},
|
||||
Ok(None) => {
|
||||
return (Some(EventSet::all()), None)
|
||||
},
|
||||
Err(e) => panic!("unexpected error accepting: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this should never happen
|
||||
return (Some(EventSet::all()), None)
|
||||
}
|
||||
|
||||
fn get_socket(&self) -> &Evented {
|
||||
return self as &Evented
|
||||
}
|
||||
}
|
||||
|
||||
impl DnsHandler for (UdpSocket, VecDeque<UdpHandler>) {
|
||||
fn handle(&mut self, events: EventSet, catalog: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>) {
|
||||
let ref socket = self.0;
|
||||
let ref mut requests = self.1;
|
||||
|
||||
if events.is_error() {
|
||||
panic!("unexpected socket error: {:?}", socket)
|
||||
} else if events.is_hup() {
|
||||
panic!("unexpected socket hangup: {:?}", socket)
|
||||
} else {
|
||||
let mut next_event: EventSet = EventSet::all();
|
||||
|
||||
// process the responses before the requests...
|
||||
if events.is_writable() {
|
||||
let mut remove: Vec<usize> = Vec::new();
|
||||
|
||||
// send all the data for the incomplete requests
|
||||
for (i, req) in requests.iter().enumerate() {
|
||||
match req.handle_message (&socket, events) {
|
||||
Ok(UdpState::Done) => {
|
||||
// complete, remove
|
||||
remove.push(i);
|
||||
},
|
||||
Ok(..) => {
|
||||
// Noop, request not complete
|
||||
},
|
||||
Err(ref e) if io::ErrorKind::WouldBlock == e.kind() => {
|
||||
// this is expected with the connection would block
|
||||
// noop
|
||||
},
|
||||
Err(e) => {
|
||||
// shutdown the connection, remove it.
|
||||
warn!("error writing socket: {:?} error: {}", socket, e);
|
||||
// TODO: do we need to shutdown the stream?
|
||||
remove.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove the complete requests
|
||||
for i in remove {
|
||||
requests.remove(i);
|
||||
// TODO might want to compress the list here, as it could become a leak after a large
|
||||
// set of requests.
|
||||
}
|
||||
|
||||
if requests.is_empty() {
|
||||
next_event = !EventSet::writable();
|
||||
}
|
||||
}
|
||||
|
||||
// now process the incoming requests
|
||||
if events.is_readable() {
|
||||
// collect new requests
|
||||
// TODO: could a ton of inbound requests starve the server
|
||||
for _ in 0..100 {
|
||||
if let Some(handler) = UdpHandler::new_server(&socket, catalog.clone()) {
|
||||
// this is a new request for a UDP transaction
|
||||
// let the handler read, etc.
|
||||
requests.push_back(handler);
|
||||
|
||||
next_event = EventSet::all();
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (Some(next_event), None)
|
||||
}
|
||||
|
||||
return (Some(EventSet::all()), None)
|
||||
}
|
||||
|
||||
fn get_socket(&self) -> &Evented {
|
||||
return &self.0 as &Evented
|
||||
}
|
||||
}
|
||||
|
||||
impl DnsHandler for TcpHandler {
|
||||
fn handle(&mut self, events: EventSet, catalog: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>) {
|
||||
if events.is_error() {
|
||||
warn!("closing, error from: {:?}", self.get_stream());
|
||||
// TODO: do we need to shutdown the stream?
|
||||
return (None, None);
|
||||
} else if events.is_hup() {
|
||||
info!("client hungup: {:?}", self.get_stream());
|
||||
// TODO: do we need to shutdown the stream?
|
||||
return (None, None);
|
||||
} else if events.is_readable() || events.is_writable() {
|
||||
let mut process_resquest = false;
|
||||
// the handler will deal with the rest of the connection, we need to check the return value
|
||||
// for an error with wouldblock, this means that the handler couldn't complete the request.
|
||||
match self.handle_message(events) {
|
||||
Ok(TcpState::Done) => {
|
||||
// reset, the client will close the connection according to the spec
|
||||
self.reset();
|
||||
debug!("TcpState::Done");
|
||||
},
|
||||
Ok(TcpState::WillWriteLength) => {
|
||||
// this means that we have gotten through recieving a packet
|
||||
process_resquest = true;
|
||||
debug!("TcpState::WillWriteLength");
|
||||
}
|
||||
Ok(..) => {
|
||||
// registering the event to only wake up on the correct event
|
||||
// this reduces looping on states like writable that can remain set for a long time
|
||||
debug!("reregistering for next call: {:?}", self.get_events());
|
||||
},
|
||||
Err(ref e) if io::ErrorKind::WouldBlock == e.kind() => {
|
||||
// this is expected with the connection would block
|
||||
// noop
|
||||
},
|
||||
Err(e) => {
|
||||
// shutdown the connection, remove it.
|
||||
warn!("connection: {:?} shutdown on error: {}", self.get_stream(), e);
|
||||
// TODO: do we need to shutdown the stream?
|
||||
return (None, None);
|
||||
}
|
||||
}
|
||||
|
||||
// need to process the response
|
||||
if process_resquest {
|
||||
let response = Server::process_request(self.get_buffer(), self.get_stream(), catalog.as_ref());
|
||||
if Server::encode_message(response, self.get_buffer_mut()).is_err() {
|
||||
warn!("could not encode message to: {:?}", self.get_stream());
|
||||
return (None, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("reregistering for next call: {:?}", self.get_events());
|
||||
return (Some(self.get_events()), None)
|
||||
}
|
||||
|
||||
fn get_socket(&self) -> &Evented {
|
||||
return self.get_stream() as &Evented
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler for Server {
|
||||
type Timeout = Token; // Timeouts are registered with tokens.
|
||||
type Message = ();
|
||||
|
||||
fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
|
||||
let mut remove: Option<RemoveFrom> = None;
|
||||
let mut remove_token: Option<Token> = None;
|
||||
let mut add_handler: Option<(DnsHandlerType, EventSet)> = None;
|
||||
|
||||
if let Some(socket) = self.udp_sockets.get(&token) {
|
||||
if events.is_error() {
|
||||
panic!("unexpected socket error: {:?}", socket)
|
||||
} else if events.is_hup() {
|
||||
panic!("unexpected socket hangup: {:?}", socket)
|
||||
// The token should always exist
|
||||
if let Some(mut handler) = self.handlers.get_mut(&token) {
|
||||
// the handler will perform the lookup or other actions.
|
||||
// if none is returned for event_set_opt, the handler will be revmoed
|
||||
let (event_set_opt, add) = handler.handle(events, &self.catalog);
|
||||
|
||||
// this represents a new handler to watch
|
||||
add_handler = add;
|
||||
|
||||
// given the new event_set option, reregister the socket
|
||||
if let Some(event_set) = event_set_opt {
|
||||
let socket: &Evented = handler.get_socket();
|
||||
if let Err(err) = event_loop.reregister(socket, token, event_set, PollOpt::all()) {
|
||||
// removing the socket in case of an error
|
||||
warn!("cound not reregister {:?}: {}", token, err);
|
||||
remove_token = Some(token);
|
||||
}
|
||||
} else {
|
||||
// process the responses before the requests...
|
||||
if events.is_writable() {
|
||||
// send out our queued up responses
|
||||
if let Some(reqs) = self.udp_requests.get_mut(&token) {
|
||||
let mut remove: Vec<usize> = Vec::new();
|
||||
|
||||
// send all the data for the incomplete requests
|
||||
for (i, req) in reqs.iter().enumerate() {
|
||||
match req.handle_message (&socket, events) {
|
||||
Ok(UdpState::Done) => {
|
||||
// complete, remove
|
||||
remove.push(i);
|
||||
},
|
||||
Ok(..) => {
|
||||
// Noop, request not complete
|
||||
},
|
||||
Err(ref e) if io::ErrorKind::WouldBlock == e.kind() => {
|
||||
// this is expected with the connection would block
|
||||
// noop
|
||||
},
|
||||
Err(e) => {
|
||||
// shutdown the connection, remove it.
|
||||
warn!("error writing socket: {:?} error: {}", socket, e);
|
||||
// TODO: do we need to shutdown the stream?
|
||||
remove.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove the complete requests
|
||||
for i in remove {
|
||||
reqs.remove(i);
|
||||
// TODO might want to compress the list here, as it could become a leak after a large
|
||||
// set of requests.
|
||||
}
|
||||
|
||||
if reqs.is_empty() {
|
||||
// theres nothing left you write, go back to just reading...
|
||||
if let Err(e) = event_loop.reregister(socket, token, !EventSet::writable(), PollOpt::all()) {
|
||||
error!("could not reregister socket: {:?} error: {}", socket, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now process the incoming requests
|
||||
if events.is_readable() {
|
||||
// collect new requests
|
||||
// TODO: could a ton of inbound requests starve the server
|
||||
while let Some(handler) = UdpHandler::new_server(socket, self.catalog.clone()) {
|
||||
// this is a new request for a UDP transaction
|
||||
// let the handler read, etc.
|
||||
self.udp_requests.entry(token).or_insert(VecDeque::new()).push_back(handler);
|
||||
|
||||
// reregeister the UDP socket for writes
|
||||
if let Err(e) = event_loop.reregister(socket, token, EventSet::all(), PollOpt::all()) {
|
||||
error!("could not reregister socket: {:?} error: {}", socket, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if let Some(ref socket) = self.tcp_sockets.get(&token) {
|
||||
if events.is_error() { panic!("unexpected error state on: {:?}", socket) }
|
||||
else if events.is_hup() { panic!("listening socket hungup: {:?}", socket) }
|
||||
else if events.is_readable() || events.is_writable() {
|
||||
// there's a new connection coming in
|
||||
// give it a new token and insert the stream on the eventlistener
|
||||
// then store in the map for reference when dealing with new streams
|
||||
loop {
|
||||
match socket.accept() {
|
||||
Ok(Some((stream, addr))) => {
|
||||
let token = self.next_token();
|
||||
|
||||
// initially we want readable sockets...
|
||||
match event_loop.register(&stream, token, !EventSet::writable(), PollOpt::level()) {
|
||||
Err(e) => error!("could not register stream: {:?} cause: {}", stream, e),
|
||||
Ok(()) => {
|
||||
info!("accepted tcp connection from: {:?} on {:?}", addr, stream.local_addr().ok());
|
||||
self.tcp_handlers.insert(token, TcpHandler::new_server_handler(stream));
|
||||
}
|
||||
}
|
||||
},
|
||||
Ok(None) => return,
|
||||
Err(e) => panic!("unexpected error accepting: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(ref mut handler) = self.tcp_handlers.get_mut(&token) {
|
||||
if events.is_error() {
|
||||
warn!("closing, error from: {:?}", handler.get_stream());
|
||||
// TODO: do we need to shutdown the stream?
|
||||
remove = Some(RemoveFrom::TcpHandlers(token));
|
||||
} else if events.is_hup() {
|
||||
info!("client hungup: {:?}", handler.get_stream());
|
||||
// TODO: do we need to shutdown the stream?
|
||||
remove = Some(RemoveFrom::TcpHandlers(token));
|
||||
} else if events.is_readable() || events.is_writable() {
|
||||
let mut process_resquest = false;
|
||||
// the handler will deal with the rest of the connection, we need to check the return value
|
||||
// for an error with wouldblock, this means that the handler couldn't complete the request.
|
||||
match handler.handle_message(events) {
|
||||
Ok(TcpState::Done) => {
|
||||
// reset, the client will close the connection according to the spec
|
||||
handler.reset();
|
||||
debug!("TcpState::Done");
|
||||
},
|
||||
Ok(TcpState::WillWriteLength) => {
|
||||
// this means that we have gotten through recieving a packet
|
||||
process_resquest = true;
|
||||
debug!("TcpState::WillWriteLength");
|
||||
}
|
||||
Ok(..) => {
|
||||
// registering the event to only wake up on the correct event
|
||||
// this reduces looping on states like writable that can remain set for a long time
|
||||
//if let Err(e) = event_loop.reregister(handler.get_stream(), token, handler.get_events(), PollOpt::level()) {
|
||||
debug!("reregistering for next call: {:?}", handler.get_events());
|
||||
if let Err(e) = event_loop.reregister(handler.get_stream(), token, handler.get_events(), PollOpt::all()) {
|
||||
error!("could not reregister stream: {:?} cause: {}", handler.get_stream(), e);
|
||||
remove = Some(RemoveFrom::TcpHandlers(token));
|
||||
}
|
||||
},
|
||||
Err(ref e) if io::ErrorKind::WouldBlock == e.kind() => {
|
||||
// this is expected with the connection would block
|
||||
// noop
|
||||
},
|
||||
Err(e) => {
|
||||
// shutdown the connection, remove it.
|
||||
warn!("connection: {:?} shutdown on error: {}", handler.get_stream(), e);
|
||||
// TODO: do we need to shutdown the stream?
|
||||
remove = Some(RemoveFrom::TcpHandlers(token));
|
||||
}
|
||||
}
|
||||
|
||||
// need to process the response
|
||||
if process_resquest {
|
||||
let response = Self::process_request(handler.get_buffer(), handler.get_stream(), self.catalog.as_ref());
|
||||
if Self::encode_message(response, handler.get_buffer_mut()).is_err() {
|
||||
warn!("could not encode message to: {:?}", handler.get_stream());
|
||||
remove = Some(RemoveFrom::TcpHandlers(token))
|
||||
}
|
||||
|
||||
debug!("reregistering for next call: {:?}", handler.get_events());
|
||||
if let Err(e) = event_loop.reregister(handler.get_stream(), token, handler.get_events(), PollOpt::all()) {
|
||||
error!("could not reregister stream: {:?} cause: {}", handler.get_stream(), e);
|
||||
remove = Some(RemoveFrom::TcpHandlers(token));
|
||||
}
|
||||
}
|
||||
remove_token = Some(token);
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to remove something
|
||||
match remove {
|
||||
Some(RemoveFrom::TcpHandlers(t)) => { self.tcp_handlers.remove(&t); },
|
||||
//Some(RemoveFrom::UdpRequests(t)) => { self.udp_requests.remove(&t); },
|
||||
None => (),
|
||||
// unregister the token
|
||||
remove_token.and_then(|token| {
|
||||
self.handlers.remove(&token)
|
||||
}).and_then(|handler| {
|
||||
event_loop.deregister(handler.get_socket()).unwrap_or_else(|e| debug!("error deregistering: {}", e));
|
||||
Some(())
|
||||
});
|
||||
|
||||
// need to register a new handler if there was one.
|
||||
if let Some((handler, event_set)) = add_handler {
|
||||
let register_res: io::Result<Token> = {
|
||||
let socket: &Evented = handler.get_socket();
|
||||
|
||||
let next_token = self.next_token();
|
||||
event_loop.register(socket, next_token, event_set, PollOpt::all()).map(|_| next_token)
|
||||
};
|
||||
|
||||
match register_res {
|
||||
Ok(token) => { self.handlers.insert(token, handler); },
|
||||
Err(err) => warn!("error registering handler: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,11 +417,6 @@ impl Handler for Server {
|
||||
}
|
||||
}
|
||||
|
||||
enum RemoveFrom {
|
||||
TcpHandlers(Token),
|
||||
//UdpRequests(Token),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod server_tests {
|
||||
use std::thread;
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
|
||||
@ -46,6 +45,8 @@ impl TcpClientConnection {
|
||||
///
|
||||
/// * `name_server` - address of the name server to use for queries
|
||||
pub fn new(name_server: SocketAddr) -> ClientResult<Self> {
|
||||
// TODO: randomize local port binding issue #23
|
||||
// probably not necessary for TCP...
|
||||
debug!("connecting to {:?}", name_server);
|
||||
let stream = try!(TcpStream::connect(&name_server));
|
||||
|
||||
|
@ -20,6 +20,8 @@ use std::fmt;
|
||||
|
||||
use mio::udp::UdpSocket;
|
||||
use mio::{Token, EventLoop, Handler, EventSet, PollOpt}; // not * b/c don't want confusion with std::net
|
||||
use rand::Rng;
|
||||
use rand;
|
||||
|
||||
use ::error::*;
|
||||
use client::ClientConnection;
|
||||
@ -34,6 +36,23 @@ pub struct UdpClientConnection {
|
||||
}
|
||||
|
||||
impl UdpClientConnection {
|
||||
fn next_bound_local_address() -> ClientResult<UdpSocket> {
|
||||
let mut rand = rand::thread_rng();
|
||||
|
||||
let mut error = Err(ClientErrorKind::Message("could not bind address in 10 tries").into());
|
||||
for _ in 0..10 {
|
||||
let zero_addr = ("0.0.0.0", rand.gen_range(1025_u16, u16::max_value())).to_socket_addrs().expect("could not parse 0.0.0.0 address").
|
||||
next().expect("no addresses parsed from 0.0.0.0");
|
||||
|
||||
match UdpSocket::bound(&zero_addr) {
|
||||
Ok(socket) => return Ok(socket),
|
||||
Err(err) => error = Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
error
|
||||
}
|
||||
|
||||
/// Creates a new client connection.
|
||||
///
|
||||
/// *Note* this has side affects of binding the socket to 0.0.0.0 and starting the listening
|
||||
@ -43,11 +62,9 @@ impl UdpClientConnection {
|
||||
///
|
||||
/// * `name_server` - address of the name server to use for queries
|
||||
pub fn new(name_server: SocketAddr) -> ClientResult<Self> {
|
||||
// TODO: allow the bind address to be specified...
|
||||
// client binds to all addresses... this shouldn't ever fail
|
||||
let zero_addr = ("0.0.0.0", 0).to_socket_addrs().expect("could not parse 0.0.0.0 address").
|
||||
next().expect("no addresses parsed from 0.0.0.0");
|
||||
|
||||
let socket = try!(UdpSocket::bound(&zero_addr));
|
||||
let socket = try!(Self::next_bound_local_address());
|
||||
let mut event_loop: EventLoop<Response> = try!(EventLoop::new());
|
||||
// TODO make the timeout configurable, 5 seconds is the dig default
|
||||
// TODO the error is private to mio, which makes this awkward...
|
||||
|
Loading…
Reference in New Issue
Block a user