Extended network options (#2845)
* More network configuration options * Filter UDP requests * Fixed tests * Fixed test warning
This commit is contained in:
parent
7f210b05bb
commit
1a5bae8ef1
@ -29,6 +29,9 @@ id = "0x1"
|
|||||||
bootnodes = []
|
bootnodes = []
|
||||||
discovery = true
|
discovery = true
|
||||||
warp = true
|
warp = true
|
||||||
|
allow_ips = "all"
|
||||||
|
snapshot_peers = 0
|
||||||
|
max_pending_peers = 64
|
||||||
|
|
||||||
reserved_only = false
|
reserved_only = false
|
||||||
reserved_peers = "./path_to_file"
|
reserved_peers = "./path_to_file"
|
||||||
|
@ -18,6 +18,9 @@ discovery = true
|
|||||||
nat = "any"
|
nat = "any"
|
||||||
min_peers = 10
|
min_peers = 10
|
||||||
max_peers = 20
|
max_peers = 20
|
||||||
|
max_pending_peers = 30
|
||||||
|
snapshot_peers = 40
|
||||||
|
allow_ips = "public"
|
||||||
|
|
||||||
reserved_only = true
|
reserved_only = true
|
||||||
reserved_peers = "./path/to/reserved_peers"
|
reserved_peers = "./path/to/reserved_peers"
|
||||||
|
@ -114,8 +114,14 @@ usage! {
|
|||||||
or |c: &Config| otry!(c.network).min_peers.clone(),
|
or |c: &Config| otry!(c.network).min_peers.clone(),
|
||||||
flag_max_peers: u16 = 50u16,
|
flag_max_peers: u16 = 50u16,
|
||||||
or |c: &Config| otry!(c.network).max_peers.clone(),
|
or |c: &Config| otry!(c.network).max_peers.clone(),
|
||||||
|
flag_max_pending_peers: u16 = 64u16,
|
||||||
|
or |c: &Config| otry!(c.network).max_pending_peers.clone(),
|
||||||
|
flag_snapshot_peers: u16 = 0u16,
|
||||||
|
or |c: &Config| otry!(c.network).snapshot_peers.clone(),
|
||||||
flag_nat: String = "any",
|
flag_nat: String = "any",
|
||||||
or |c: &Config| otry!(c.network).nat.clone(),
|
or |c: &Config| otry!(c.network).nat.clone(),
|
||||||
|
flag_allow_ips: String = "all",
|
||||||
|
or |c: &Config| otry!(c.network).allow_ips.clone(),
|
||||||
flag_network_id: Option<String> = None,
|
flag_network_id: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
or |c: &Config| otry!(c.network).id.clone().map(Some),
|
||||||
flag_bootnodes: Option<String> = None,
|
flag_bootnodes: Option<String> = None,
|
||||||
@ -307,7 +313,10 @@ struct Network {
|
|||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
min_peers: Option<u16>,
|
min_peers: Option<u16>,
|
||||||
max_peers: Option<u16>,
|
max_peers: Option<u16>,
|
||||||
|
snapshot_peers: Option<u16>,
|
||||||
|
max_pending_peers: Option<u16>,
|
||||||
nat: Option<String>,
|
nat: Option<String>,
|
||||||
|
allow_ips: Option<String>,
|
||||||
id: Option<String>,
|
id: Option<String>,
|
||||||
bootnodes: Option<Vec<String>>,
|
bootnodes: Option<Vec<String>>,
|
||||||
discovery: Option<bool>,
|
discovery: Option<bool>,
|
||||||
@ -494,6 +503,9 @@ mod tests {
|
|||||||
flag_port: 30303u16,
|
flag_port: 30303u16,
|
||||||
flag_min_peers: 25u16,
|
flag_min_peers: 25u16,
|
||||||
flag_max_peers: 50u16,
|
flag_max_peers: 50u16,
|
||||||
|
flag_max_pending_peers: 64u16,
|
||||||
|
flag_snapshot_peers: 0u16,
|
||||||
|
flag_allow_ips: "all".into(),
|
||||||
flag_nat: "any".into(),
|
flag_nat: "any".into(),
|
||||||
flag_network_id: Some("0x1".into()),
|
flag_network_id: Some("0x1".into()),
|
||||||
flag_bootnodes: Some("".into()),
|
flag_bootnodes: Some("".into()),
|
||||||
@ -653,6 +665,9 @@ mod tests {
|
|||||||
port: None,
|
port: None,
|
||||||
min_peers: Some(10),
|
min_peers: Some(10),
|
||||||
max_peers: Some(20),
|
max_peers: Some(20),
|
||||||
|
max_pending_peers: Some(30),
|
||||||
|
snapshot_peers: Some(40),
|
||||||
|
allow_ips: Some("public".into()),
|
||||||
nat: Some("any".into()),
|
nat: Some("any".into()),
|
||||||
id: None,
|
id: None,
|
||||||
bootnodes: None,
|
bootnodes: None,
|
||||||
|
@ -71,7 +71,9 @@ Networking Options:
|
|||||||
--port PORT Override the port on which the node should listen
|
--port PORT Override the port on which the node should listen
|
||||||
(default: {flag_port}).
|
(default: {flag_port}).
|
||||||
--min-peers NUM Try to maintain at least NUM peers (default: {flag_min_peers}).
|
--min-peers NUM Try to maintain at least NUM peers (default: {flag_min_peers}).
|
||||||
--max-peers NUM Allow up to that many peers (default: {flag_max_peers}).
|
--max-peers NUM Allow up to NUM peers (default: {flag_max_peers}).
|
||||||
|
--snapshot-peers NUM Allow additional NUM peers for a snapshot sync
|
||||||
|
(default: {flag_snapshot_peers}).
|
||||||
--nat METHOD Specify method to use for determining public
|
--nat METHOD Specify method to use for determining public
|
||||||
address. Must be one of: any, none, upnp,
|
address. Must be one of: any, none, upnp,
|
||||||
extip:<IP> (default: {flag_nat}).
|
extip:<IP> (default: {flag_nat}).
|
||||||
@ -86,6 +88,12 @@ Networking Options:
|
|||||||
These nodes will always have a reserved slot on top
|
These nodes will always have a reserved slot on top
|
||||||
of the normal maximum peers. (default: {flag_reserved_peers:?})
|
of the normal maximum peers. (default: {flag_reserved_peers:?})
|
||||||
--reserved-only Connect only to reserved nodes. (default: {flag_reserved_only})
|
--reserved-only Connect only to reserved nodes. (default: {flag_reserved_only})
|
||||||
|
--allow-ips FILTER Filter outbound connections. Must be one of:
|
||||||
|
private - connect to private network IP addresses only;
|
||||||
|
public - connect to public network IP addresses only;
|
||||||
|
all - connect to any IP address.
|
||||||
|
(default: {flag_allow_ips})
|
||||||
|
--max-pending-peers NUM Allow up to NUM pending connections. (default: {flag_max_pending_peers})
|
||||||
|
|
||||||
API and Console Options:
|
API and Console Options:
|
||||||
--no-jsonrpc Disable the JSON-RPC API server. (default: {flag_no_jsonrpc})
|
--no-jsonrpc Disable the JSON-RPC API server. (default: {flag_no_jsonrpc})
|
||||||
|
@ -22,7 +22,7 @@ use std::cmp::max;
|
|||||||
use cli::{Args, ArgsError};
|
use cli::{Args, ArgsError};
|
||||||
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
use util::{Hashable, U256, Uint, Bytes, version_data, Secret, Address};
|
||||||
use util::log::Colour;
|
use util::log::Colour;
|
||||||
use ethsync::{NetworkConfiguration, is_valid_node_url};
|
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
|
||||||
use ethcore::client::{VMType, Mode};
|
use ethcore::client::{VMType, Mode};
|
||||||
use ethcore::miner::MinerOptions;
|
use ethcore::miner::MinerOptions;
|
||||||
|
|
||||||
@ -332,10 +332,27 @@ impl Configuration {
|
|||||||
max(self.min_peers(), peers)
|
max(self.min_peers(), peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allow_ips(&self) -> Result<AllowIP, String> {
|
||||||
|
match self.args.flag_allow_ips.as_str() {
|
||||||
|
"all" => Ok(AllowIP::All),
|
||||||
|
"public" => Ok(AllowIP::Public),
|
||||||
|
"private" => Ok(AllowIP::Private),
|
||||||
|
_ => Err("Invalid IP filter value".to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn min_peers(&self) -> u32 {
|
fn min_peers(&self) -> u32 {
|
||||||
self.args.flag_peers.unwrap_or(self.args.flag_min_peers) as u32
|
self.args.flag_peers.unwrap_or(self.args.flag_min_peers) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn max_pending_peers(&self) -> u32 {
|
||||||
|
self.args.flag_max_pending_peers as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn snapshot_peers(&self) -> u32 {
|
||||||
|
self.args.flag_snapshot_peers as u32
|
||||||
|
}
|
||||||
|
|
||||||
fn work_notify(&self) -> Vec<String> {
|
fn work_notify(&self) -> Vec<String> {
|
||||||
self.args.flag_notify_work.as_ref().map_or_else(Vec::new, |s| s.split(',').map(|s| s.to_owned()).collect())
|
self.args.flag_notify_work.as_ref().map_or_else(Vec::new, |s| s.split(',').map(|s| s.to_owned()).collect())
|
||||||
}
|
}
|
||||||
@ -474,6 +491,9 @@ impl Configuration {
|
|||||||
ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover;
|
ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover;
|
||||||
ret.max_peers = self.max_peers();
|
ret.max_peers = self.max_peers();
|
||||||
ret.min_peers = self.min_peers();
|
ret.min_peers = self.min_peers();
|
||||||
|
ret.snapshot_peers = self.snapshot_peers();
|
||||||
|
ret.allow_ips = try!(self.allow_ips());
|
||||||
|
ret.max_pending_peers = self.max_pending_peers();
|
||||||
let mut net_path = PathBuf::from(self.directories().db);
|
let mut net_path = PathBuf::from(self.directories().db);
|
||||||
net_path.push("network");
|
net_path.push("network");
|
||||||
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
|
||||||
|
@ -185,7 +185,7 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
||||||
use ethsync::NetworkConfiguration;
|
use ethsync::{NetworkConfiguration, AllowIP};
|
||||||
NetworkConfiguration {
|
NetworkConfiguration {
|
||||||
config_path: Some(replace_home("$HOME/.parity/network")),
|
config_path: Some(replace_home("$HOME/.parity/network")),
|
||||||
net_config_path: None,
|
net_config_path: None,
|
||||||
@ -198,6 +198,9 @@ pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
|
|||||||
use_secret: None,
|
use_secret: None,
|
||||||
max_peers: 50,
|
max_peers: 50,
|
||||||
min_peers: 25,
|
min_peers: 25,
|
||||||
|
snapshot_peers: 0,
|
||||||
|
max_pending_peers: 64,
|
||||||
|
allow_ips: AllowIP::All,
|
||||||
reserved_nodes: Vec::new(),
|
reserved_nodes: Vec::new(),
|
||||||
allow_non_reserved: true,
|
allow_non_reserved: true,
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ use std::sync::Arc;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use util::Bytes;
|
use util::Bytes;
|
||||||
use network::{NetworkProtocolHandler, NetworkService, NetworkContext, PeerId, ProtocolId,
|
use network::{NetworkProtocolHandler, NetworkService, NetworkContext, PeerId, ProtocolId,
|
||||||
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, NetworkError};
|
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, NetworkError,
|
||||||
|
AllowIP as NetworkAllowIP};
|
||||||
use util::{U256, H256};
|
use util::{U256, H256};
|
||||||
use io::{TimerToken};
|
use io::{TimerToken};
|
||||||
use ethcore::client::{BlockChainClient, ChainNotify};
|
use ethcore::client::{BlockChainClient, ChainNotify};
|
||||||
@ -102,13 +103,15 @@ pub struct EthSync {
|
|||||||
handler: Arc<SyncProtocolHandler>,
|
handler: Arc<SyncProtocolHandler>,
|
||||||
/// The main subprotocol name
|
/// The main subprotocol name
|
||||||
subprotocol_name: [u8; 3],
|
subprotocol_name: [u8; 3],
|
||||||
|
/// Configuration
|
||||||
|
config: NetworkConfiguration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthSync {
|
impl EthSync {
|
||||||
/// Creates and register protocol with the network service
|
/// Creates and register protocol with the network service
|
||||||
pub fn new(config: SyncConfig, chain: Arc<BlockChainClient>, snapshot_service: Arc<SnapshotService>, network_config: NetworkConfiguration) -> Result<Arc<EthSync>, NetworkError> {
|
pub fn new(config: SyncConfig, chain: Arc<BlockChainClient>, snapshot_service: Arc<SnapshotService>, network_config: NetworkConfiguration) -> Result<Arc<EthSync>, NetworkError> {
|
||||||
let chain_sync = ChainSync::new(config, &*chain);
|
let chain_sync = ChainSync::new(config, &*chain);
|
||||||
let service = try!(NetworkService::new(try!(network_config.into_basic())));
|
let service = try!(NetworkService::new(try!(network_config.clone().into_basic())));
|
||||||
let sync = Arc::new(EthSync{
|
let sync = Arc::new(EthSync{
|
||||||
network: service,
|
network: service,
|
||||||
handler: Arc::new(SyncProtocolHandler {
|
handler: Arc::new(SyncProtocolHandler {
|
||||||
@ -118,6 +121,7 @@ impl EthSync {
|
|||||||
overlay: RwLock::new(HashMap::new()),
|
overlay: RwLock::new(HashMap::new()),
|
||||||
}),
|
}),
|
||||||
subprotocol_name: config.subprotocol_name,
|
subprotocol_name: config.subprotocol_name,
|
||||||
|
config: network_config,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(sync)
|
Ok(sync)
|
||||||
@ -276,6 +280,29 @@ impl ManageNetwork for EthSync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// IP fiter
|
||||||
|
#[derive(Binary, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum AllowIP {
|
||||||
|
/// Connect to any address
|
||||||
|
All,
|
||||||
|
/// Connect to private network only
|
||||||
|
Private,
|
||||||
|
/// Connect to public network only
|
||||||
|
Public,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AllowIP {
|
||||||
|
/// Attempt to parse the peer mode from a string.
|
||||||
|
pub fn parse(s: &str) -> Option<Self> {
|
||||||
|
match s {
|
||||||
|
"all" => Some(AllowIP::All),
|
||||||
|
"private" => Some(AllowIP::Private),
|
||||||
|
"public" => Some(AllowIP::Public),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Binary, Debug, Clone, PartialEq, Eq)]
|
#[derive(Binary, Debug, Clone, PartialEq, Eq)]
|
||||||
/// Network service configuration
|
/// Network service configuration
|
||||||
pub struct NetworkConfiguration {
|
pub struct NetworkConfiguration {
|
||||||
@ -301,10 +328,16 @@ pub struct NetworkConfiguration {
|
|||||||
pub max_peers: u32,
|
pub max_peers: u32,
|
||||||
/// Min number of connected peers to maintain
|
/// Min number of connected peers to maintain
|
||||||
pub min_peers: u32,
|
pub min_peers: u32,
|
||||||
|
/// Max pending peers.
|
||||||
|
pub max_pending_peers: u32,
|
||||||
|
/// Reserved snapshot sync peers.
|
||||||
|
pub snapshot_peers: u32,
|
||||||
/// List of reserved node addresses.
|
/// List of reserved node addresses.
|
||||||
pub reserved_nodes: Vec<String>,
|
pub reserved_nodes: Vec<String>,
|
||||||
/// The non-reserved peer mode.
|
/// The non-reserved peer mode.
|
||||||
pub allow_non_reserved: bool,
|
pub allow_non_reserved: bool,
|
||||||
|
/// IP Filtering
|
||||||
|
pub allow_ips: AllowIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkConfiguration {
|
impl NetworkConfiguration {
|
||||||
@ -340,7 +373,14 @@ impl NetworkConfiguration {
|
|||||||
use_secret: self.use_secret,
|
use_secret: self.use_secret,
|
||||||
max_peers: self.max_peers,
|
max_peers: self.max_peers,
|
||||||
min_peers: self.min_peers,
|
min_peers: self.min_peers,
|
||||||
|
max_handshakes: self.max_pending_peers,
|
||||||
|
reserved_protocols: hash_map![WARP_SYNC_PROTOCOL_ID => self.snapshot_peers],
|
||||||
reserved_nodes: self.reserved_nodes,
|
reserved_nodes: self.reserved_nodes,
|
||||||
|
allow_ips: match self.allow_ips {
|
||||||
|
AllowIP::All => NetworkAllowIP::All,
|
||||||
|
AllowIP::Private => NetworkAllowIP::Private,
|
||||||
|
AllowIP::Public => NetworkAllowIP::Public,
|
||||||
|
},
|
||||||
non_reserved_mode: if self.allow_non_reserved { NonReservedPeerMode::Accept } else { NonReservedPeerMode::Deny },
|
non_reserved_mode: if self.allow_non_reserved { NonReservedPeerMode::Accept } else { NonReservedPeerMode::Deny },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -360,7 +400,14 @@ impl From<BasicNetworkConfiguration> for NetworkConfiguration {
|
|||||||
use_secret: other.use_secret,
|
use_secret: other.use_secret,
|
||||||
max_peers: other.max_peers,
|
max_peers: other.max_peers,
|
||||||
min_peers: other.min_peers,
|
min_peers: other.min_peers,
|
||||||
|
max_pending_peers: other.max_handshakes,
|
||||||
|
snapshot_peers: *other.reserved_protocols.get(&WARP_SYNC_PROTOCOL_ID).unwrap_or(&0),
|
||||||
reserved_nodes: other.reserved_nodes,
|
reserved_nodes: other.reserved_nodes,
|
||||||
|
allow_ips: match other.allow_ips {
|
||||||
|
NetworkAllowIP::All => AllowIP::All,
|
||||||
|
NetworkAllowIP::Private => AllowIP::Private,
|
||||||
|
NetworkAllowIP::Public => AllowIP::Public,
|
||||||
|
},
|
||||||
allow_non_reserved: match other.non_reserved_mode { NonReservedPeerMode::Accept => true, _ => false } ,
|
allow_non_reserved: match other.non_reserved_mode { NonReservedPeerMode::Accept => true, _ => false } ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ mod api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use api::{EthSync, SyncProvider, SyncClient, NetworkManagerClient, ManageNetwork, SyncConfig,
|
pub use api::{EthSync, SyncProvider, SyncClient, NetworkManagerClient, ManageNetwork, SyncConfig,
|
||||||
ServiceConfiguration, NetworkConfiguration, PeerInfo};
|
ServiceConfiguration, NetworkConfiguration, PeerInfo, AllowIP};
|
||||||
pub use chain::{SyncStatus, SyncState};
|
pub use chain::{SyncStatus, SyncState};
|
||||||
pub use network::{is_valid_node_url, NonReservedPeerMode, NetworkError};
|
pub use network::{is_valid_node_url, NonReservedPeerMode, NetworkError};
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ use node_table::*;
|
|||||||
use error::NetworkError;
|
use error::NetworkError;
|
||||||
use io::{StreamToken, IoContext};
|
use io::{StreamToken, IoContext};
|
||||||
use ethkey::{Secret, KeyPair, sign, recover};
|
use ethkey::{Secret, KeyPair, sign, recover};
|
||||||
|
use AllowIP;
|
||||||
|
|
||||||
use PROTOCOL_VERSION;
|
use PROTOCOL_VERSION;
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ pub struct Discovery {
|
|||||||
send_queue: VecDeque<Datagramm>,
|
send_queue: VecDeque<Datagramm>,
|
||||||
check_timestamps: bool,
|
check_timestamps: bool,
|
||||||
adding_nodes: Vec<NodeEntry>,
|
adding_nodes: Vec<NodeEntry>,
|
||||||
|
allow_ips: AllowIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TableUpdates {
|
pub struct TableUpdates {
|
||||||
@ -103,7 +105,7 @@ pub struct TableUpdates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Discovery {
|
impl Discovery {
|
||||||
pub fn new(key: &KeyPair, listen: SocketAddr, public: NodeEndpoint, token: StreamToken) -> Discovery {
|
pub fn new(key: &KeyPair, listen: SocketAddr, public: NodeEndpoint, token: StreamToken, allow_ips: AllowIP) -> Discovery {
|
||||||
let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket");
|
let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket");
|
||||||
Discovery {
|
Discovery {
|
||||||
id: key.public().clone(),
|
id: key.public().clone(),
|
||||||
@ -118,15 +120,18 @@ impl Discovery {
|
|||||||
send_queue: VecDeque::new(),
|
send_queue: VecDeque::new(),
|
||||||
check_timestamps: true,
|
check_timestamps: true,
|
||||||
adding_nodes: Vec::new(),
|
adding_nodes: Vec::new(),
|
||||||
|
allow_ips: allow_ips,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new node to discovery table. Pings the node.
|
/// Add a new node to discovery table. Pings the node.
|
||||||
pub fn add_node(&mut self, e: NodeEntry) {
|
pub fn add_node(&mut self, e: NodeEntry) {
|
||||||
|
if e.endpoint.is_allowed(self.allow_ips) {
|
||||||
let endpoint = e.endpoint.clone();
|
let endpoint = e.endpoint.clone();
|
||||||
self.update_node(e);
|
self.update_node(e);
|
||||||
self.ping(&endpoint);
|
self.ping(&endpoint);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a list of nodes. Pings a few nodes each round
|
/// Add a list of nodes. Pings a few nodes each round
|
||||||
pub fn add_node_list(&mut self, nodes: Vec<NodeEntry>) {
|
pub fn add_node_list(&mut self, nodes: Vec<NodeEntry>) {
|
||||||
@ -137,9 +142,11 @@ impl Discovery {
|
|||||||
/// Add a list of known nodes to the table.
|
/// Add a list of known nodes to the table.
|
||||||
pub fn init_node_list(&mut self, mut nodes: Vec<NodeEntry>) {
|
pub fn init_node_list(&mut self, mut nodes: Vec<NodeEntry>) {
|
||||||
for n in nodes.drain(..) {
|
for n in nodes.drain(..) {
|
||||||
|
if n.endpoint.is_allowed(self.allow_ips) {
|
||||||
self.update_node(n);
|
self.update_node(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_node(&mut self, e: NodeEntry) {
|
fn update_node(&mut self, e: NodeEntry) {
|
||||||
trace!(target: "discovery", "Inserting {:?}", &e);
|
trace!(target: "discovery", "Inserting {:?}", &e);
|
||||||
@ -394,10 +401,11 @@ impl Discovery {
|
|||||||
try!(self.check_timestamp(timestamp));
|
try!(self.check_timestamp(timestamp));
|
||||||
let mut added_map = HashMap::new();
|
let mut added_map = HashMap::new();
|
||||||
let entry = NodeEntry { id: node.clone(), endpoint: source.clone() };
|
let entry = NodeEntry { id: node.clone(), endpoint: source.clone() };
|
||||||
if !entry.endpoint.is_valid() || !entry.endpoint.is_global() {
|
if !entry.endpoint.is_valid() {
|
||||||
debug!(target: "discovery", "Got bad address: {:?}", entry);
|
debug!(target: "discovery", "Got bad address: {:?}", entry);
|
||||||
}
|
} else if !entry.endpoint.is_allowed(self.allow_ips) {
|
||||||
else {
|
debug!(target: "discovery", "Address not allowed: {:?}", entry);
|
||||||
|
} else {
|
||||||
self.update_node(entry.clone());
|
self.update_node(entry.clone());
|
||||||
added_map.insert(node.clone(), entry);
|
added_map.insert(node.clone(), entry);
|
||||||
}
|
}
|
||||||
@ -470,6 +478,10 @@ impl Discovery {
|
|||||||
debug!(target: "discovery", "Bad address: {:?}", endpoint);
|
debug!(target: "discovery", "Bad address: {:?}", endpoint);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if !endpoint.is_allowed(self.allow_ips) {
|
||||||
|
debug!(target: "discovery", "Address not allowed: {:?}", endpoint);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let node_id: NodeId = try!(r.val_at(3));
|
let node_id: NodeId = try!(r.val_at(3));
|
||||||
if node_id == self.id {
|
if node_id == self.id {
|
||||||
continue;
|
continue;
|
||||||
@ -539,6 +551,7 @@ mod tests {
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
use ethkey::{Random, Generator};
|
use ethkey::{Random, Generator};
|
||||||
|
use AllowIP;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn find_node() {
|
fn find_node() {
|
||||||
@ -563,8 +576,8 @@ mod tests {
|
|||||||
let key2 = Random.generate().unwrap();
|
let key2 = Random.generate().unwrap();
|
||||||
let ep1 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40444").unwrap(), udp_port: 40444 };
|
let ep1 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40444").unwrap(), udp_port: 40444 };
|
||||||
let ep2 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40445").unwrap(), udp_port: 40445 };
|
let ep2 = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40445").unwrap(), udp_port: 40445 };
|
||||||
let mut discovery1 = Discovery::new(&key1, ep1.address.clone(), ep1.clone(), 0);
|
let mut discovery1 = Discovery::new(&key1, ep1.address.clone(), ep1.clone(), 0, AllowIP::All);
|
||||||
let mut discovery2 = Discovery::new(&key2, ep2.address.clone(), ep2.clone(), 0);
|
let mut discovery2 = Discovery::new(&key2, ep2.address.clone(), ep2.clone(), 0, AllowIP::All);
|
||||||
|
|
||||||
let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@127.0.0.1:7770").unwrap();
|
let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@127.0.0.1:7770").unwrap();
|
||||||
let node2 = Node::from_str("enode://b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@127.0.0.1:7771").unwrap();
|
let node2 = Node::from_str("enode://b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@127.0.0.1:7771").unwrap();
|
||||||
@ -596,7 +609,7 @@ mod tests {
|
|||||||
fn removes_expired() {
|
fn removes_expired() {
|
||||||
let key = Random.generate().unwrap();
|
let key = Random.generate().unwrap();
|
||||||
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40447 };
|
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40447 };
|
||||||
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0);
|
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0, AllowIP::All);
|
||||||
for _ in 0..1200 {
|
for _ in 0..1200 {
|
||||||
discovery.add_node(NodeEntry { id: NodeId::random(), endpoint: ep.clone() });
|
discovery.add_node(NodeEntry { id: NodeId::random(), endpoint: ep.clone() });
|
||||||
}
|
}
|
||||||
@ -624,7 +637,7 @@ mod tests {
|
|||||||
fn packets() {
|
fn packets() {
|
||||||
let key = Random.generate().unwrap();
|
let key = Random.generate().unwrap();
|
||||||
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40447").unwrap(), udp_port: 40447 };
|
let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40447").unwrap(), udp_port: 40447 };
|
||||||
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0);
|
let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0, AllowIP::All);
|
||||||
discovery.check_timestamps = false;
|
discovery.check_timestamps = false;
|
||||||
let from = SocketAddr::from_str("99.99.99.99:40445").unwrap();
|
let from = SocketAddr::from_str("99.99.99.99:40445").unwrap();
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ use rlp::*;
|
|||||||
use session::{Session, SessionInfo, SessionData};
|
use session::{Session, SessionInfo, SessionData};
|
||||||
use error::*;
|
use error::*;
|
||||||
use io::*;
|
use io::*;
|
||||||
use {NetworkProtocolHandler, NonReservedPeerMode, PROTOCOL_VERSION};
|
use {NetworkProtocolHandler, NonReservedPeerMode, AllowIP, PROTOCOL_VERSION};
|
||||||
use node_table::*;
|
use node_table::*;
|
||||||
use stats::NetworkStats;
|
use stats::NetworkStats;
|
||||||
use discovery::{Discovery, TableUpdates, NodeEntry};
|
use discovery::{Discovery, TableUpdates, NodeEntry};
|
||||||
@ -45,8 +45,7 @@ use parking_lot::{Mutex, RwLock};
|
|||||||
type Slab<T> = ::slab::Slab<T, usize>;
|
type Slab<T> = ::slab::Slab<T, usize>;
|
||||||
|
|
||||||
const MAX_SESSIONS: usize = 1024 + MAX_HANDSHAKES;
|
const MAX_SESSIONS: usize = 1024 + MAX_HANDSHAKES;
|
||||||
const MAX_HANDSHAKES: usize = 80;
|
const MAX_HANDSHAKES: usize = 1024;
|
||||||
const MAX_HANDSHAKES_PER_ROUND: usize = 32;
|
|
||||||
|
|
||||||
// Tokens
|
// Tokens
|
||||||
const TCP_ACCEPT: usize = SYS_TIMER + 1;
|
const TCP_ACCEPT: usize = SYS_TIMER + 1;
|
||||||
@ -89,12 +88,18 @@ pub struct NetworkConfiguration {
|
|||||||
pub use_secret: Option<Secret>,
|
pub use_secret: Option<Secret>,
|
||||||
/// Minimum number of connected peers to maintain
|
/// Minimum number of connected peers to maintain
|
||||||
pub min_peers: u32,
|
pub min_peers: u32,
|
||||||
/// Maximum allowd number of peers
|
/// Maximum allowed number of peers
|
||||||
pub max_peers: u32,
|
pub max_peers: u32,
|
||||||
|
/// Maximum handshakes
|
||||||
|
pub max_handshakes: u32,
|
||||||
|
/// Reserved protocols. Peers with <key> protocol get additional <value> connection slots.
|
||||||
|
pub reserved_protocols: HashMap<ProtocolId, u32>,
|
||||||
/// List of reserved node addresses.
|
/// List of reserved node addresses.
|
||||||
pub reserved_nodes: Vec<String>,
|
pub reserved_nodes: Vec<String>,
|
||||||
/// The non-reserved peer mode.
|
/// The non-reserved peer mode.
|
||||||
pub non_reserved_mode: NonReservedPeerMode,
|
pub non_reserved_mode: NonReservedPeerMode,
|
||||||
|
/// IP filter
|
||||||
|
pub allow_ips: AllowIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NetworkConfiguration {
|
impl Default for NetworkConfiguration {
|
||||||
@ -118,6 +123,9 @@ impl NetworkConfiguration {
|
|||||||
use_secret: None,
|
use_secret: None,
|
||||||
min_peers: 25,
|
min_peers: 25,
|
||||||
max_peers: 50,
|
max_peers: 50,
|
||||||
|
max_handshakes: 64,
|
||||||
|
reserved_protocols: HashMap::new(),
|
||||||
|
allow_ips: AllowIP::All,
|
||||||
reserved_nodes: Vec::new(),
|
reserved_nodes: Vec::new(),
|
||||||
non_reserved_mode: NonReservedPeerMode::Accept,
|
non_reserved_mode: NonReservedPeerMode::Accept,
|
||||||
}
|
}
|
||||||
@ -364,7 +372,7 @@ pub struct Host {
|
|||||||
|
|
||||||
impl Host {
|
impl Host {
|
||||||
/// Create a new instance
|
/// Create a new instance
|
||||||
pub fn new(config: NetworkConfiguration, stats: Arc<NetworkStats>) -> Result<Host, NetworkError> {
|
pub fn new(mut config: NetworkConfiguration, stats: Arc<NetworkStats>) -> Result<Host, NetworkError> {
|
||||||
trace!(target: "host", "Creating new Host object");
|
trace!(target: "host", "Creating new Host object");
|
||||||
|
|
||||||
let mut listen_address = match config.listen_address {
|
let mut listen_address = match config.listen_address {
|
||||||
@ -394,6 +402,7 @@ impl Host {
|
|||||||
|
|
||||||
let boot_nodes = config.boot_nodes.clone();
|
let boot_nodes = config.boot_nodes.clone();
|
||||||
let reserved_nodes = config.reserved_nodes.clone();
|
let reserved_nodes = config.reserved_nodes.clone();
|
||||||
|
config.max_handshakes = min(config.max_handshakes, MAX_HANDSHAKES as u32);
|
||||||
|
|
||||||
let mut host = Host {
|
let mut host = Host {
|
||||||
info: RwLock::new(HostInfo {
|
info: RwLock::new(HostInfo {
|
||||||
@ -532,6 +541,7 @@ impl Host {
|
|||||||
}
|
}
|
||||||
let local_endpoint = self.info.read().local_endpoint.clone();
|
let local_endpoint = self.info.read().local_endpoint.clone();
|
||||||
let public_address = self.info.read().config.public_address.clone();
|
let public_address = self.info.read().config.public_address.clone();
|
||||||
|
let allow_ips = self.info.read().config.allow_ips;
|
||||||
let public_endpoint = match public_address {
|
let public_endpoint = match public_address {
|
||||||
None => {
|
None => {
|
||||||
let public_address = select_public_address(local_endpoint.address.port());
|
let public_address = select_public_address(local_endpoint.address.port());
|
||||||
@ -563,7 +573,7 @@ impl Host {
|
|||||||
if info.config.discovery_enabled && info.config.non_reserved_mode == NonReservedPeerMode::Accept {
|
if info.config.discovery_enabled && info.config.non_reserved_mode == NonReservedPeerMode::Accept {
|
||||||
let mut udp_addr = local_endpoint.address.clone();
|
let mut udp_addr = local_endpoint.address.clone();
|
||||||
udp_addr.set_port(local_endpoint.udp_port);
|
udp_addr.set_port(local_endpoint.udp_port);
|
||||||
Some(Discovery::new(&info.keys, udp_addr, public_endpoint, DISCOVERY))
|
Some(Discovery::new(&info.keys, udp_addr, public_endpoint, DISCOVERY, allow_ips))
|
||||||
} else { None }
|
} else { None }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -618,14 +628,14 @@ impl Host {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn connect_peers(&self, io: &IoContext<NetworkIoMessage>) {
|
fn connect_peers(&self, io: &IoContext<NetworkIoMessage>) {
|
||||||
let (min_peers, mut pin) = {
|
let (min_peers, mut pin, max_handshakes, allow_ips) = {
|
||||||
let info = self.info.read();
|
let info = self.info.read();
|
||||||
if info.capabilities.is_empty() {
|
if info.capabilities.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let config = &info.config;
|
let config = &info.config;
|
||||||
|
|
||||||
(config.min_peers, config.non_reserved_mode == NonReservedPeerMode::Deny)
|
(config.min_peers, config.non_reserved_mode == NonReservedPeerMode::Deny, config.max_handshakes as usize, config.allow_ips)
|
||||||
};
|
};
|
||||||
|
|
||||||
let session_count = self.session_count();
|
let session_count = self.session_count();
|
||||||
@ -642,22 +652,22 @@ impl Host {
|
|||||||
|
|
||||||
let handshake_count = self.handshake_count();
|
let handshake_count = self.handshake_count();
|
||||||
// allow 16 slots for incoming connections
|
// allow 16 slots for incoming connections
|
||||||
let handshake_limit = MAX_HANDSHAKES - 16;
|
if handshake_count >= max_handshakes {
|
||||||
if handshake_count >= handshake_limit {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate over all nodes, reserved ones coming first.
|
// iterate over all nodes, reserved ones coming first.
|
||||||
// if we are pinned to only reserved nodes, ignore all others.
|
// if we are pinned to only reserved nodes, ignore all others.
|
||||||
let nodes = reserved_nodes.iter().cloned().chain(if !pin {
|
let nodes = reserved_nodes.iter().cloned().chain(if !pin {
|
||||||
self.nodes.read().nodes()
|
self.nodes.read().nodes(allow_ips)
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let max_handshakes_per_round = max_handshakes / 2;
|
||||||
let mut started: usize = 0;
|
let mut started: usize = 0;
|
||||||
for id in nodes.filter(|ref id| !self.have_session(id) && !self.connecting_to(id))
|
for id in nodes.filter(|ref id| !self.have_session(id) && !self.connecting_to(id))
|
||||||
.take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) {
|
.take(min(max_handshakes_per_round, max_handshakes - handshake_count)) {
|
||||||
self.connect_peer(&id, io);
|
self.connect_peer(&id, io);
|
||||||
started += 1;
|
started += 1;
|
||||||
}
|
}
|
||||||
@ -790,7 +800,14 @@ impl Host {
|
|||||||
let session_count = self.session_count();
|
let session_count = self.session_count();
|
||||||
let (max_peers, reserved_only) = {
|
let (max_peers, reserved_only) = {
|
||||||
let info = self.info.read();
|
let info = self.info.read();
|
||||||
(info.config.max_peers, info.config.non_reserved_mode == NonReservedPeerMode::Deny)
|
let mut max_peers = info.config.max_peers;
|
||||||
|
for cap in s.info.capabilities.iter() {
|
||||||
|
if let Some(num) = info.config.reserved_protocols.get(&cap.protocol) {
|
||||||
|
max_peers += *num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(max_peers, info.config.non_reserved_mode == NonReservedPeerMode::Deny)
|
||||||
};
|
};
|
||||||
|
|
||||||
if session_count >= max_peers as usize || reserved_only {
|
if session_count >= max_peers as usize || reserved_only {
|
||||||
|
@ -56,6 +56,22 @@ impl SocketAddrExt for Ipv6Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SocketAddrExt for IpAddr {
|
||||||
|
fn is_unspecified_s(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
IpAddr::V4(ref ip) => ip.is_unspecified_s(),
|
||||||
|
IpAddr::V6(ref ip) => ip.is_unspecified_s(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_global_s(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
IpAddr::V4(ref ip) => ip.is_global_s(),
|
||||||
|
IpAddr::V6(ref ip) => ip.is_global_s(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
mod getinterfaces {
|
mod getinterfaces {
|
||||||
use std::{mem, io, ptr};
|
use std::{mem, io, ptr};
|
||||||
|
@ -137,3 +137,15 @@ impl NonReservedPeerMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// IP fiter
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
|
||||||
|
pub enum AllowIP {
|
||||||
|
/// Connect to any address
|
||||||
|
All,
|
||||||
|
/// Connect to private network only
|
||||||
|
Private,
|
||||||
|
/// Connect to public network only
|
||||||
|
Public,
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ use util::UtilError;
|
|||||||
use rlp::*;
|
use rlp::*;
|
||||||
use time::Tm;
|
use time::Tm;
|
||||||
use error::NetworkError;
|
use error::NetworkError;
|
||||||
|
use AllowIP;
|
||||||
use discovery::{TableUpdates, NodeEntry};
|
use discovery::{TableUpdates, NodeEntry};
|
||||||
use ip_utils::*;
|
use ip_utils::*;
|
||||||
pub use rustc_serialize::json::Json;
|
pub use rustc_serialize::json::Json;
|
||||||
@ -53,9 +54,15 @@ impl NodeEndpoint {
|
|||||||
SocketAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a.ip().clone(), self.udp_port, a.flowinfo(), a.scope_id())),
|
SocketAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a.ip().clone(), self.udp_port, a.flowinfo(), a.scope_id())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeEndpoint {
|
pub fn is_allowed(&self, filter: AllowIP) -> bool {
|
||||||
|
match filter {
|
||||||
|
AllowIP::All => true,
|
||||||
|
AllowIP::Private => !self.address.ip().is_global_s(),
|
||||||
|
AllowIP::Public => self.address.ip().is_global_s(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_rlp(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
pub fn from_rlp(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||||
let tcp_port = try!(rlp.val_at::<u16>(2));
|
let tcp_port = try!(rlp.val_at::<u16>(2));
|
||||||
let udp_port = try!(rlp.val_at::<u16>(1));
|
let udp_port = try!(rlp.val_at::<u16>(1));
|
||||||
@ -98,13 +105,6 @@ impl NodeEndpoint {
|
|||||||
SocketAddr::V6(a) => !a.ip().is_unspecified_s()
|
SocketAddr::V6(a) => !a.ip().is_unspecified_s()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_global(&self) -> bool {
|
|
||||||
match self.address {
|
|
||||||
SocketAddr::V4(a) => a.ip().is_global_s(),
|
|
||||||
SocketAddr::V6(a) => a.ip().is_global_s()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for NodeEndpoint {
|
impl FromStr for NodeEndpoint {
|
||||||
@ -219,8 +219,8 @@ impl NodeTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns node ids sorted by number of failures
|
/// Returns node ids sorted by number of failures
|
||||||
pub fn nodes(&self) -> Vec<NodeId> {
|
pub fn nodes(&self, filter: AllowIP) -> Vec<NodeId> {
|
||||||
let mut refs: Vec<&Node> = self.nodes.values().filter(|n| !self.useless_nodes.contains(&n.id)).collect();
|
let mut refs: Vec<&Node> = self.nodes.values().filter(|n| !self.useless_nodes.contains(&n.id) && n.endpoint.is_allowed(filter)).collect();
|
||||||
refs.sort_by(|a, b| a.failures.cmp(&b.failures));
|
refs.sort_by(|a, b| a.failures.cmp(&b.failures));
|
||||||
refs.iter().map(|n| n.id.clone()).collect()
|
refs.iter().map(|n| n.id.clone()).collect()
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ impl NodeTable {
|
|||||||
let mut json = String::new();
|
let mut json = String::new();
|
||||||
json.push_str("{\n");
|
json.push_str("{\n");
|
||||||
json.push_str("\"nodes\": [\n");
|
json.push_str("\"nodes\": [\n");
|
||||||
let node_ids = self.nodes();
|
let node_ids = self.nodes(AllowIP::All);
|
||||||
for i in 0 .. node_ids.len() {
|
for i in 0 .. node_ids.len() {
|
||||||
let node = self.nodes.get(&node_ids[i]).unwrap();
|
let node = self.nodes.get(&node_ids[i]).unwrap();
|
||||||
json.push_str(&format!("\t{{ \"url\": \"{}\", \"failures\": {} }}{}\n", node, node.failures, if i == node_ids.len() - 1 {""} else {","}))
|
json.push_str(&format!("\t{{ \"url\": \"{}\", \"failures\": {} }}{}\n", node, node.failures, if i == node_ids.len() - 1 {""} else {","}))
|
||||||
@ -361,6 +361,7 @@ mod tests {
|
|||||||
use std::net::*;
|
use std::net::*;
|
||||||
use util::hash::*;
|
use util::hash::*;
|
||||||
use devtools::*;
|
use devtools::*;
|
||||||
|
use AllowIP;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn endpoint_parse() {
|
fn endpoint_parse() {
|
||||||
@ -406,7 +407,7 @@ mod tests {
|
|||||||
table.note_failure(&id1);
|
table.note_failure(&id1);
|
||||||
table.note_failure(&id2);
|
table.note_failure(&id2);
|
||||||
|
|
||||||
let r = table.nodes();
|
let r = table.nodes(AllowIP::All);
|
||||||
assert_eq!(r[0][..], id3[..]);
|
assert_eq!(r[0][..], id3[..]);
|
||||||
assert_eq!(r[1][..], id2[..]);
|
assert_eq!(r[1][..], id2[..]);
|
||||||
assert_eq!(r[2][..], id1[..]);
|
assert_eq!(r[2][..], id1[..]);
|
||||||
@ -428,7 +429,7 @@ mod tests {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let table = NodeTable::new(Some(temp_path.as_path().to_str().unwrap().to_owned()));
|
let table = NodeTable::new(Some(temp_path.as_path().to_str().unwrap().to_owned()));
|
||||||
let r = table.nodes();
|
let r = table.nodes(AllowIP::All);
|
||||||
assert_eq!(r[0][..], id1[..]);
|
assert_eq!(r[0][..], id1[..]);
|
||||||
assert_eq!(r[1][..], id2[..]);
|
assert_eq!(r[1][..], id2[..]);
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,6 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use devtools::*;
|
use devtools::*;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
fn test_db(config: &DatabaseConfig) {
|
fn test_db(config: &DatabaseConfig) {
|
||||||
let path = RandomTempPath::create_dir();
|
let path = RandomTempPath::create_dir();
|
||||||
@ -673,6 +672,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn df_to_rotational() {
|
fn df_to_rotational() {
|
||||||
|
use std::path::PathBuf;
|
||||||
// Example df output.
|
// Example df output.
|
||||||
let example_df = vec![70, 105, 108, 101, 115, 121, 115, 116, 101, 109, 32, 32, 32, 32, 32, 49, 75, 45, 98, 108, 111, 99, 107, 115, 32, 32, 32, 32, 32, 85, 115, 101, 100, 32, 65, 118, 97, 105, 108, 97, 98, 108, 101, 32, 85, 115, 101, 37, 32, 77, 111, 117, 110, 116, 101, 100, 32, 111, 110, 10, 47, 100, 101, 118, 47, 115, 100, 97, 49, 32, 32, 32, 32, 32, 32, 32, 54, 49, 52, 48, 57, 51, 48, 48, 32, 51, 56, 56, 50, 50, 50, 51, 54, 32, 32, 49, 57, 52, 52, 52, 54, 49, 54, 32, 32, 54, 55, 37, 32, 47, 10];
|
let example_df = vec![70, 105, 108, 101, 115, 121, 115, 116, 101, 109, 32, 32, 32, 32, 32, 49, 75, 45, 98, 108, 111, 99, 107, 115, 32, 32, 32, 32, 32, 85, 115, 101, 100, 32, 65, 118, 97, 105, 108, 97, 98, 108, 101, 32, 85, 115, 101, 37, 32, 77, 111, 117, 110, 116, 101, 100, 32, 111, 110, 10, 47, 100, 101, 118, 47, 115, 100, 97, 49, 32, 32, 32, 32, 32, 32, 32, 54, 49, 52, 48, 57, 51, 48, 48, 32, 51, 56, 56, 50, 50, 50, 51, 54, 32, 32, 49, 57, 52, 52, 52, 54, 49, 54, 32, 32, 54, 55, 37, 32, 47, 10];
|
||||||
let expected_output = Some(PathBuf::from("/sys/block/sda/queue/rotational"));
|
let expected_output = Some(PathBuf::from("/sys/block/sda/queue/rotational"));
|
||||||
|
Loading…
Reference in New Issue
Block a user