1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// Copyright 2017-2018 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//!
//! Ways to configure the Roughenough server.
//!
//! The [ServerConfig](trait.ServerConfig.html) trait specifies the required and optional
//! parameters available for configuring a Roughenoguh server instance.
//!
//! Implementations of `ServerConfig` obtain configurations from different back-end sources.
//!
extern crate hex;
extern crate log;
use std::net::SocketAddr;
use std::time::Duration;
mod file;
pub use self::file::FileConfig;
mod environment;
pub use self::environment::EnvironmentConfig;
use Error;
/// Maximum number of requests to process in one batch and include the the Merkle tree.
pub const DEFAULT_BATCH_SIZE: u8 = 64;
/// Amount of time between each logged status update.
pub const DEFAULT_STATUS_INTERVAL: Duration = Duration::from_secs(600);
///
/// Specifies parameters needed to configure a Roughenough server.
///
/// Parameters labeled "**Required**" must are always be provided and have no default value.
/// Parameters labeled "**Optional**" provide default values that can be overridden.
///
/// * **`interface`** - [Required] IP address or interface name for listening to client requests
/// * **`port`** - [Required] UDP port to listen for requests
/// * **`seed`** - [Required] A 32-byte hexadecimal value used to generate the server's long-term
/// key pair. **This is a secret value and must be un-guessable**,
/// treat it with care.
/// * **`batch_size`** - [Optional] The maximum number of requests to process in one batch. All
/// nonces in a batch are used to build a Merkle tree, the root of which
/// is signed.
/// Defaults to [DEFAULT_BATCH_SIZE](constant.DEFAULT_BATCH_SIZE.html)
/// * **`status_interval`** - [Optional] Amount of time between each logged status update.
/// Defaults to [DEFAULT_STATUS_INTERVAL](constant.DEFAULT_STATUS_INTERVAL.html)
///
/// Implementations of this trait obtain a valid configuration from different back-
/// end sources.
///
/// See:
/// * [FileConfig](struct.FileConfig.html)
///
pub trait ServerConfig {
/// [Required] IP address or interface name to listen for client requests
fn interface(&self) -> &str;
/// [Required] UDP port to listen for requests
fn port(&self) -> u16;
/// [Required] A 32-byte hexadecimal value used to generate the server's
/// long-term key pair. **This is a secret value and must be un-guessable**,
/// treat it with care.
fn seed(&self) -> &[u8];
/// [Optional] The maximum number of requests to process in one batch. All
/// nonces in a batch are used to build a Merkle tree, the root of which is signed.
/// Defaults to [DEFAULT_BATCH_SIZE](constant.DEFAULT_BATCH_SIZE.html)
fn batch_size(&self) -> u8;
/// [Optional] Amount of time between each logged status update.
/// Defaults to [DEFAULT_STATUS_INTERVAL](constant.DEFAULT_STATUS_INTERVAL.html)
fn status_interval(&self) -> Duration;
/// Convenience function to create a `SocketAddr` from the provided `interface` and `port`
fn socket_addr(&self) -> Result<SocketAddr, Error>;
}
pub fn is_valid_config(cfg: &Box<ServerConfig>) -> bool {
let mut is_valid = true;
if cfg.port() == 0 {
error!("unset port: {}", cfg.port());
is_valid = false;
}
if cfg.interface().is_empty() {
error!("interface is missing");
is_valid = false;
}
match cfg.socket_addr() {
Err(e) => {
error!("{}:{}: {:?}", cfg.interface(), cfg.port(), e);
is_valid = false;
}
_ => ()
}
if cfg.seed().is_empty() {
error!("seed value is missing");
is_valid = false;
}
if !cfg.seed().is_empty() && cfg.seed().len() != 32 {
error!("seed value must be 32 characters long");
is_valid = false;
}
if cfg.batch_size() < 1 || cfg.batch_size() > 64 {
error!("batch_size {} is invalid; valid range 1-64", cfg.batch_size());
is_valid = false;
}
is_valid
}
|