Abstract devp2p (#8048)
* Rename ethcore-network to ethcore-network-devp2p * Fix typo * Extract generic traits into util/network * Simplify util/network * Fix devp2p tests * Remove old feature * Fix RPC tests
This commit is contained in:
parent
47a02480c4
commit
eeee90def5
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -621,6 +621,20 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-network"
|
name = "ethcore-network"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
dependencies = [
|
||||||
|
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-io 1.11.0",
|
||||||
|
"ethcrypto 0.1.0",
|
||||||
|
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethkey 0.3.0",
|
||||||
|
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rlp 0.2.1",
|
||||||
|
"snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ethcore-network-devp2p"
|
||||||
|
version = "1.11.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -628,6 +642,7 @@ dependencies = [
|
|||||||
"ethcore-bytes 0.1.0",
|
"ethcore-bytes 0.1.0",
|
||||||
"ethcore-io 1.11.0",
|
"ethcore-io 1.11.0",
|
||||||
"ethcore-logger 1.11.0",
|
"ethcore-logger 1.11.0",
|
||||||
|
"ethcore-network 1.11.0",
|
||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethkey 0.3.0",
|
"ethkey 0.3.0",
|
||||||
@ -849,6 +864,7 @@ dependencies = [
|
|||||||
"ethcore-io 1.11.0",
|
"ethcore-io 1.11.0",
|
||||||
"ethcore-light 1.11.0",
|
"ethcore-light 1.11.0",
|
||||||
"ethcore-network 1.11.0",
|
"ethcore-network 1.11.0",
|
||||||
|
"ethcore-network-devp2p 1.11.0",
|
||||||
"ethcore-transaction 0.1.0",
|
"ethcore-transaction 0.1.0",
|
||||||
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethkey 0.3.0",
|
"ethkey 0.3.0",
|
||||||
@ -1712,7 +1728,7 @@ dependencies = [
|
|||||||
"ethcore 1.11.0",
|
"ethcore 1.11.0",
|
||||||
"ethcore-bytes 0.1.0",
|
"ethcore-bytes 0.1.0",
|
||||||
"ethcore-io 1.11.0",
|
"ethcore-io 1.11.0",
|
||||||
"ethcore-network 1.11.0",
|
"ethcore-network-devp2p 1.11.0",
|
||||||
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kvdb-memorydb 0.1.0",
|
"kvdb-memorydb 0.1.0",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -47,7 +47,7 @@ pub trait IoContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> IoContext for NetworkContext<'a> {
|
impl<T> IoContext for T where T: ?Sized + NetworkContext {
|
||||||
fn send(&self, peer: PeerId, packet_id: u8, packet_body: Vec<u8>) {
|
fn send(&self, peer: PeerId, packet_id: u8, packet_body: Vec<u8>) {
|
||||||
if let Err(e) = self.send(peer, packet_id, packet_body) {
|
if let Err(e) = self.send(peer, packet_id, packet_body) {
|
||||||
debug!(target: "pip", "Error sending packet to peer {}: {}", peer, e);
|
debug!(target: "pip", "Error sending packet to peer {}: {}", peer, e);
|
||||||
|
@ -1089,23 +1089,23 @@ impl NetworkProtocolHandler for LightProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||||
self.handle_packet(io, peer, packet_id, data);
|
self.handle_packet(&io, peer, packet_id, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
self.on_connect(peer, io);
|
self.on_connect(peer, &io);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
self.on_disconnect(*peer, io);
|
self.on_disconnect(*peer, &io);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
|
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
|
||||||
match timer {
|
match timer {
|
||||||
TIMEOUT => self.timeout_check(io),
|
TIMEOUT => self.timeout_check(&io),
|
||||||
TICK_TIMEOUT => self.tick_handlers(io),
|
TICK_TIMEOUT => self.tick_handlers(&io),
|
||||||
PROPAGATE_TIMEOUT => self.propagate_transactions(io),
|
PROPAGATE_TIMEOUT => self.propagate_transactions(&io),
|
||||||
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(io),
|
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(&io),
|
||||||
_ => warn!(target: "pip", "received timeout on unknown token {}", timer),
|
_ => warn!(target: "pip", "received timeout on unknown token {}", timer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ethcore = { path = ".."}
|
ethcore = { path = ".."}
|
||||||
ethcore-bytes = { path = "../../util/bytes" }
|
ethcore-bytes = { path = "../../util/bytes" }
|
||||||
ethcore-network = { path = "../../util/network" }
|
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||||
ethereum-types = "0.2"
|
ethereum-types = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
parking_lot = "0.5"
|
parking_lot = "0.5"
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
extern crate ethabi;
|
extern crate ethabi;
|
||||||
extern crate ethcore;
|
extern crate ethcore;
|
||||||
extern crate ethcore_bytes as bytes;
|
extern crate ethcore_bytes as bytes;
|
||||||
extern crate ethcore_network as network;
|
extern crate ethcore_network_devp2p as network;
|
||||||
extern crate ethereum_types;
|
extern crate ethereum_types;
|
||||||
extern crate lru_cache;
|
extern crate lru_cache;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
|
@ -10,6 +10,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ethcore-bytes = { path = "../util/bytes" }
|
ethcore-bytes = { path = "../util/bytes" }
|
||||||
ethcore-network = { path = "../util/network" }
|
ethcore-network = { path = "../util/network" }
|
||||||
|
ethcore-network-devp2p = { path = "../util/network-devp2p" }
|
||||||
ethcore-io = { path = "../util/io" }
|
ethcore-io = { path = "../util/io" }
|
||||||
ethcore-light = { path = "../ethcore/light" }
|
ethcore-light = { path = "../ethcore/light" }
|
||||||
ethcore-transaction = { path = "../ethcore/transaction" }
|
ethcore-transaction = { path = "../ethcore/transaction" }
|
||||||
|
@ -18,8 +18,9 @@ use std::sync::Arc;
|
|||||||
use std::collections::{HashMap, BTreeMap};
|
use std::collections::{HashMap, BTreeMap};
|
||||||
use std::io;
|
use std::io;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use network::{NetworkProtocolHandler, NetworkService, NetworkContext, HostInfo, PeerId, ProtocolId,
|
use devp2p::{NetworkService, ConnectionFilter};
|
||||||
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind, ConnectionFilter};
|
use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId,
|
||||||
|
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind};
|
||||||
use ethereum_types::{H256, H512, U256};
|
use ethereum_types::{H256, H512, U256};
|
||||||
use io::{TimerToken};
|
use io::{TimerToken};
|
||||||
use ethcore::ethstore::ethkey::Secret;
|
use ethcore::ethstore::ethkey::Secret;
|
||||||
@ -393,7 +394,7 @@ impl ChainNotify for EthSync {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let chain_info = self.eth_handler.chain.chain_info();
|
let chain_info = self.eth_handler.chain.chain_info();
|
||||||
light_proto.make_announcement(context, Announcement {
|
light_proto.make_announcement(&context, Announcement {
|
||||||
head_hash: chain_info.best_block_hash,
|
head_hash: chain_info.best_block_hash,
|
||||||
head_num: chain_info.best_block_number,
|
head_num: chain_info.best_block_number,
|
||||||
head_td: chain_info.total_difficulty,
|
head_td: chain_info.total_difficulty,
|
||||||
@ -737,7 +738,7 @@ impl LightSync {
|
|||||||
{
|
{
|
||||||
self.network.with_context_eval(
|
self.network.with_context_eval(
|
||||||
self.subprotocol_name,
|
self.subprotocol_name,
|
||||||
move |ctx| self.proto.with_context(ctx, f),
|
move |ctx| self.proto.with_context(&ctx, f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
extern crate ethcore_network as network;
|
extern crate ethcore_network as network;
|
||||||
|
extern crate ethcore_network_devp2p as devp2p;
|
||||||
extern crate ethcore_bytes as bytes;
|
extern crate ethcore_bytes as bytes;
|
||||||
extern crate ethcore_io as io;
|
extern crate ethcore_io as io;
|
||||||
extern crate ethcore_transaction as transaction;
|
extern crate ethcore_transaction as transaction;
|
||||||
@ -68,4 +69,5 @@ mod api;
|
|||||||
|
|
||||||
pub use api::*;
|
pub use api::*;
|
||||||
pub use chain::{SyncStatus, SyncState};
|
pub use chain::{SyncStatus, SyncState};
|
||||||
pub use network::{validate_node_url, NonReservedPeerMode, Error, ErrorKind, ConnectionFilter, ConnectionDirection};
|
pub use devp2p::{validate_node_url, ConnectionFilter, ConnectionDirection};
|
||||||
|
pub use network::{NonReservedPeerMode, Error, ErrorKind};
|
||||||
|
@ -61,19 +61,19 @@ pub trait SyncIo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps `NetworkContext` and the blockchain client
|
/// Wraps `NetworkContext` and the blockchain client
|
||||||
pub struct NetSyncIo<'s, 'h> where 'h: 's {
|
pub struct NetSyncIo<'s> {
|
||||||
network: &'s NetworkContext<'h>,
|
network: &'s NetworkContext,
|
||||||
chain: &'s BlockChainClient,
|
chain: &'s BlockChainClient,
|
||||||
snapshot_service: &'s SnapshotService,
|
snapshot_service: &'s SnapshotService,
|
||||||
chain_overlay: &'s RwLock<HashMap<BlockNumber, Bytes>>,
|
chain_overlay: &'s RwLock<HashMap<BlockNumber, Bytes>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, 'h> NetSyncIo<'s, 'h> {
|
impl<'s> NetSyncIo<'s> {
|
||||||
/// Creates a new instance from the `NetworkContext` and the blockchain client reference.
|
/// Creates a new instance from the `NetworkContext` and the blockchain client reference.
|
||||||
pub fn new(network: &'s NetworkContext<'h>,
|
pub fn new(network: &'s NetworkContext,
|
||||||
chain: &'s BlockChainClient,
|
chain: &'s BlockChainClient,
|
||||||
snapshot_service: &'s SnapshotService,
|
snapshot_service: &'s SnapshotService,
|
||||||
chain_overlay: &'s RwLock<HashMap<BlockNumber, Bytes>>) -> NetSyncIo<'s, 'h> {
|
chain_overlay: &'s RwLock<HashMap<BlockNumber, Bytes>>) -> NetSyncIo<'s> {
|
||||||
NetSyncIo {
|
NetSyncIo {
|
||||||
network: network,
|
network: network,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
@ -83,7 +83,7 @@ impl<'s, 'h> NetSyncIo<'s, 'h> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> {
|
impl<'s> SyncIo for NetSyncIo<'s> {
|
||||||
fn disable_peer(&mut self, peer_id: PeerId) {
|
fn disable_peer(&mut self, peer_id: PeerId) {
|
||||||
self.network.disable_peer(peer_id);
|
self.network.disable_peer(peer_id);
|
||||||
}
|
}
|
||||||
|
44
util/network-devp2p/Cargo.toml
Normal file
44
util/network-devp2p/Cargo.toml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
[package]
|
||||||
|
description = "DevP2P implementation of the ethcore network library"
|
||||||
|
homepage = "http://parity.io"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
name = "ethcore-network-devp2p"
|
||||||
|
version = "1.11.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.3"
|
||||||
|
mio = "0.6.8"
|
||||||
|
bytes = "0.4"
|
||||||
|
rand = "0.4"
|
||||||
|
time = "0.1.34"
|
||||||
|
tiny-keccak = "1.3"
|
||||||
|
rust-crypto = "0.2.34"
|
||||||
|
slab = "0.2"
|
||||||
|
igd = "0.6"
|
||||||
|
libc = "0.2.7"
|
||||||
|
parking_lot = "0.5"
|
||||||
|
ansi_term = "0.10"
|
||||||
|
rustc-hex = "1.0"
|
||||||
|
ethcore-io = { path = "../io" }
|
||||||
|
ethcore-bytes = { path = "../bytes" }
|
||||||
|
ethcore-network = { path = "../network" }
|
||||||
|
ethereum-types = "0.2"
|
||||||
|
ethkey = { path = "../../ethkey" }
|
||||||
|
ethcrypto = { path = "../../ethcrypto" }
|
||||||
|
rlp = { path = "../rlp" }
|
||||||
|
path = { path = "../path" }
|
||||||
|
ethcore-logger = { path ="../../logger" }
|
||||||
|
ipnetwork = "0.12.6"
|
||||||
|
keccak-hash = { path = "../hash" }
|
||||||
|
snappy = { git = "https://github.com/paritytech/rust-snappy" }
|
||||||
|
serde = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
error-chain = { version = "0.11", default-features = false }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempdir = "0.3"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
@ -36,7 +36,7 @@ use rcrypto::buffer::*;
|
|||||||
use tiny_keccak::Keccak;
|
use tiny_keccak::Keccak;
|
||||||
use bytes::{Buf, BufMut};
|
use bytes::{Buf, BufMut};
|
||||||
use crypto;
|
use crypto;
|
||||||
use error::{Error, ErrorKind};
|
use network::{Error, ErrorKind};
|
||||||
|
|
||||||
const ENCRYPTED_HEADER_LEN: usize = 32;
|
const ENCRYPTED_HEADER_LEN: usize = 32;
|
||||||
const RECIEVE_PAYLOAD_TIMEOUT: u64 = 30000;
|
const RECIEVE_PAYLOAD_TIMEOUT: u64 = 30000;
|
@ -27,10 +27,10 @@ use time;
|
|||||||
use ethereum_types::{H256, H520};
|
use ethereum_types::{H256, H520};
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use node_table::*;
|
use node_table::*;
|
||||||
use error::{Error, ErrorKind};
|
use network::{Error, ErrorKind};
|
||||||
use io::{StreamToken, IoContext};
|
use io::{StreamToken, IoContext};
|
||||||
use ethkey::{Secret, KeyPair, sign, recover};
|
use ethkey::{Secret, KeyPair, sign, recover};
|
||||||
use IpFilter;
|
use network::IpFilter;
|
||||||
|
|
||||||
use PROTOCOL_VERSION;
|
use PROTOCOL_VERSION;
|
||||||
|
|
@ -22,13 +22,12 @@ use ethereum_types::{H256, H520};
|
|||||||
use ethcore_bytes::Bytes;
|
use ethcore_bytes::Bytes;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use connection::{Connection};
|
use connection::{Connection};
|
||||||
use host::{HostInfo};
|
|
||||||
use node_table::NodeId;
|
use node_table::NodeId;
|
||||||
use stats::NetworkStats;
|
use stats::NetworkStats;
|
||||||
use io::{IoContext, StreamToken};
|
use io::{IoContext, StreamToken};
|
||||||
use ethkey::{KeyPair, Public, Secret, recover, sign, Generator, Random};
|
use ethkey::{KeyPair, Public, Secret, recover, sign, Generator, Random};
|
||||||
use crypto::{ecdh, ecies};
|
use crypto::{ecdh, ecies};
|
||||||
use error::{Error, ErrorKind};
|
use network::{Error, ErrorKind, HostInfo};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
enum HandshakeState {
|
enum HandshakeState {
|
@ -31,17 +31,20 @@ use mio::deprecated::{EventLoop};
|
|||||||
use mio::tcp::*;
|
use mio::tcp::*;
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use session::{Session, SessionInfo, SessionData};
|
use session::{Session, SessionData};
|
||||||
use io::*;
|
use io::*;
|
||||||
use {NetworkProtocolHandler, NonReservedPeerMode, PROTOCOL_VERSION, IpFilter};
|
use PROTOCOL_VERSION;
|
||||||
use node_table::*;
|
use node_table::*;
|
||||||
|
use network::{NetworkConfiguration, NetworkIoMessage, ProtocolId, PeerId, PacketId};
|
||||||
|
use network::{NonReservedPeerMode, NetworkContext as NetworkContextTrait};
|
||||||
|
use network::HostInfo as HostInfoTrait;
|
||||||
|
use network::{SessionInfo, Error, ErrorKind, DisconnectReason, NetworkProtocolHandler};
|
||||||
use stats::NetworkStats;
|
use stats::NetworkStats;
|
||||||
use discovery::{Discovery, TableUpdates, NodeEntry};
|
use discovery::{Discovery, TableUpdates, NodeEntry};
|
||||||
use ip_utils::{map_external_address, select_public_address};
|
use ip_utils::{map_external_address, select_public_address};
|
||||||
use path::restrict_permissions_owner;
|
use path::restrict_permissions_owner;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use connection_filter::{ConnectionFilter, ConnectionDirection};
|
use connection_filter::{ConnectionFilter, ConnectionDirection};
|
||||||
use error::{Error, ErrorKind, DisconnectReason};
|
|
||||||
|
|
||||||
type Slab<T> = ::slab::Slab<T, usize>;
|
type Slab<T> = ::slab::Slab<T, usize>;
|
||||||
|
|
||||||
@ -72,132 +75,6 @@ const DISCOVERY_ROUND_TIMEOUT: u64 = 300;
|
|||||||
// for NODE_TABLE TimerToken
|
// for NODE_TABLE TimerToken
|
||||||
const NODE_TABLE_TIMEOUT: u64 = 300_000;
|
const NODE_TABLE_TIMEOUT: u64 = 300_000;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
/// Network service configuration
|
|
||||||
pub struct NetworkConfiguration {
|
|
||||||
/// Directory path to store general network configuration. None means nothing will be saved
|
|
||||||
pub config_path: Option<String>,
|
|
||||||
/// Directory path to store network-specific configuration. None means nothing will be saved
|
|
||||||
pub net_config_path: Option<String>,
|
|
||||||
/// IP address to listen for incoming connections. Listen to all connections by default
|
|
||||||
pub listen_address: Option<SocketAddr>,
|
|
||||||
/// IP address to advertise. Detected automatically if none.
|
|
||||||
pub public_address: Option<SocketAddr>,
|
|
||||||
/// Port for UDP connections, same as TCP by default
|
|
||||||
pub udp_port: Option<u16>,
|
|
||||||
/// Enable NAT configuration
|
|
||||||
pub nat_enabled: bool,
|
|
||||||
/// Enable discovery
|
|
||||||
pub discovery_enabled: bool,
|
|
||||||
/// List of initial node addresses
|
|
||||||
pub boot_nodes: Vec<String>,
|
|
||||||
/// Use provided node key instead of default
|
|
||||||
pub use_secret: Option<Secret>,
|
|
||||||
/// Minimum number of connected peers to maintain
|
|
||||||
pub min_peers: u32,
|
|
||||||
/// Maximum allowed number of peers
|
|
||||||
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.
|
|
||||||
pub reserved_nodes: Vec<String>,
|
|
||||||
/// The non-reserved peer mode.
|
|
||||||
pub non_reserved_mode: NonReservedPeerMode,
|
|
||||||
/// IP filter
|
|
||||||
pub ip_filter: IpFilter,
|
|
||||||
/// Client identifier
|
|
||||||
pub client_version: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for NetworkConfiguration {
|
|
||||||
fn default() -> Self {
|
|
||||||
NetworkConfiguration::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NetworkConfiguration {
|
|
||||||
/// Create a new instance of default settings.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
NetworkConfiguration {
|
|
||||||
config_path: None,
|
|
||||||
net_config_path: None,
|
|
||||||
listen_address: None,
|
|
||||||
public_address: None,
|
|
||||||
udp_port: None,
|
|
||||||
nat_enabled: true,
|
|
||||||
discovery_enabled: true,
|
|
||||||
boot_nodes: Vec::new(),
|
|
||||||
use_secret: None,
|
|
||||||
min_peers: 25,
|
|
||||||
max_peers: 50,
|
|
||||||
max_handshakes: 64,
|
|
||||||
reserved_protocols: HashMap::new(),
|
|
||||||
ip_filter: IpFilter::default(),
|
|
||||||
reserved_nodes: Vec::new(),
|
|
||||||
non_reserved_mode: NonReservedPeerMode::Accept,
|
|
||||||
client_version: "Parity-network".into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new default configuration with sepcified listen port.
|
|
||||||
pub fn new_with_port(port: u16) -> NetworkConfiguration {
|
|
||||||
let mut config = NetworkConfiguration::new();
|
|
||||||
config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port)));
|
|
||||||
config
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create new default configuration for localhost-only connection with random port (usefull for testing)
|
|
||||||
pub fn new_local() -> NetworkConfiguration {
|
|
||||||
let mut config = NetworkConfiguration::new();
|
|
||||||
config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0)));
|
|
||||||
config.nat_enabled = false;
|
|
||||||
config
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Protocol handler level packet id
|
|
||||||
pub type PacketId = u8;
|
|
||||||
/// Protocol / handler id
|
|
||||||
pub type ProtocolId = [u8; 3];
|
|
||||||
|
|
||||||
/// Messages used to communitate with the event loop from other threads.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum NetworkIoMessage {
|
|
||||||
/// Register a new protocol handler.
|
|
||||||
AddHandler {
|
|
||||||
/// Handler shared instance.
|
|
||||||
handler: Arc<NetworkProtocolHandler + Sync>,
|
|
||||||
/// Protocol Id.
|
|
||||||
protocol: ProtocolId,
|
|
||||||
/// Supported protocol versions.
|
|
||||||
versions: Vec<u8>,
|
|
||||||
/// Number of packet IDs reserved by the protocol.
|
|
||||||
packet_count: u8,
|
|
||||||
},
|
|
||||||
/// Register a new protocol timer
|
|
||||||
AddTimer {
|
|
||||||
/// Protocol Id.
|
|
||||||
protocol: ProtocolId,
|
|
||||||
/// Timer token.
|
|
||||||
token: TimerToken,
|
|
||||||
/// Timer delay in milliseconds.
|
|
||||||
delay: u64,
|
|
||||||
},
|
|
||||||
/// Initliaze public interface.
|
|
||||||
InitPublicInterface,
|
|
||||||
/// Disconnect a peer.
|
|
||||||
Disconnect(PeerId),
|
|
||||||
/// Disconnect and temporary disable peer.
|
|
||||||
DisablePeer(PeerId),
|
|
||||||
/// Network has been started with the host as the given enode.
|
|
||||||
NetworkStarted(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Local (temporary) peer session ID.
|
|
||||||
pub type PeerId = usize;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
/// Protocol info
|
/// Protocol info
|
||||||
pub struct CapabilityInfo {
|
pub struct CapabilityInfo {
|
||||||
@ -248,14 +125,14 @@ impl<'s> NetworkContext<'s> {
|
|||||||
_ => self.sessions.read().get(peer).cloned(),
|
_ => self.sessions.read().get(peer).cloned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send a packet over the network to another peer.
|
impl<'s> NetworkContextTrait for NetworkContext<'s> {
|
||||||
pub fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
self.send_protocol(self.protocol, peer, packet_id, data)
|
self.send_protocol(self.protocol, peer, packet_id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a packet over the network to another peer using specified protocol.
|
fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
pub fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
|
||||||
let session = self.resolve_session(peer);
|
let session = self.resolve_session(peer);
|
||||||
if let Some(session) = session {
|
if let Some(session) = session {
|
||||||
session.lock().send_packet(self.io, Some(protocol), packet_id as u8, &data)?;
|
session.lock().send_packet(self.io, Some(protocol), packet_id as u8, &data)?;
|
||||||
@ -265,36 +142,30 @@ impl<'s> NetworkContext<'s> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Respond to a current network message. Panics if no there is no packet in the context. If the session is expired returns nothing.
|
fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
pub fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
|
||||||
assert!(self.session.is_some(), "Respond called without network context");
|
assert!(self.session.is_some(), "Respond called without network context");
|
||||||
self.session_id.map_or_else(|| Err(ErrorKind::Expired.into()), |id| self.send(id, packet_id, data))
|
self.session_id.map_or_else(|| Err(ErrorKind::Expired.into()), |id| self.send(id, packet_id, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an IoChannel.
|
fn io_channel(&self) -> IoChannel<NetworkIoMessage> {
|
||||||
pub fn io_channel(&self) -> IoChannel<NetworkIoMessage> {
|
|
||||||
self.io.channel()
|
self.io.channel()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnect a peer and prevent it from connecting again.
|
fn disable_peer(&self, peer: PeerId) {
|
||||||
pub fn disable_peer(&self, peer: PeerId) {
|
|
||||||
self.io.message(NetworkIoMessage::DisablePeer(peer))
|
self.io.message(NetworkIoMessage::DisablePeer(peer))
|
||||||
.unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e));
|
.unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnect peer. Reconnect can be attempted later.
|
fn disconnect_peer(&self, peer: PeerId) {
|
||||||
pub fn disconnect_peer(&self, peer: PeerId) {
|
|
||||||
self.io.message(NetworkIoMessage::Disconnect(peer))
|
self.io.message(NetworkIoMessage::Disconnect(peer))
|
||||||
.unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e));
|
.unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the session is still active.
|
fn is_expired(&self) -> bool {
|
||||||
pub fn is_expired(&self) -> bool {
|
|
||||||
self.session.as_ref().map_or(false, |s| s.lock().expired())
|
self.session.as_ref().map_or(false, |s| s.lock().expired())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a new IO timer. 'IoHandler::timeout' will be called with the token.
|
fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), Error> {
|
||||||
pub fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), Error> {
|
|
||||||
self.io.message(NetworkIoMessage::AddTimer {
|
self.io.message(NetworkIoMessage::AddTimer {
|
||||||
token: token,
|
token: token,
|
||||||
delay: ms,
|
delay: ms,
|
||||||
@ -303,24 +174,20 @@ impl<'s> NetworkContext<'s> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns peer identification string
|
fn peer_client_version(&self, peer: PeerId) -> String {
|
||||||
pub fn peer_client_version(&self, peer: PeerId) -> String {
|
|
||||||
self.resolve_session(peer).map_or("unknown".to_owned(), |s| s.lock().info.client_version.clone())
|
self.resolve_session(peer).map_or("unknown".to_owned(), |s| s.lock().info.client_version.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns information on p2p session
|
fn session_info(&self, peer: PeerId) -> Option<SessionInfo> {
|
||||||
pub fn session_info(&self, peer: PeerId) -> Option<SessionInfo> {
|
|
||||||
self.resolve_session(peer).map(|s| s.lock().info.clone())
|
self.resolve_session(peer).map(|s| s.lock().info.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns max version for a given protocol.
|
fn protocol_version(&self, protocol: ProtocolId, peer: PeerId) -> Option<u8> {
|
||||||
pub fn protocol_version(&self, protocol: ProtocolId, peer: PeerId) -> Option<u8> {
|
|
||||||
let session = self.resolve_session(peer);
|
let session = self.resolve_session(peer);
|
||||||
session.and_then(|s| s.lock().capability_version(protocol))
|
session.and_then(|s| s.lock().capability_version(protocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns this object's subprotocol name.
|
fn subprotocol_name(&self) -> ProtocolId { self.protocol }
|
||||||
pub fn subprotocol_name(&self) -> ProtocolId { self.protocol }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared host information
|
/// Shared host information
|
||||||
@ -341,24 +208,21 @@ pub struct HostInfo {
|
|||||||
pub public_endpoint: Option<NodeEndpoint>,
|
pub public_endpoint: Option<NodeEndpoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostInfo {
|
impl HostInfoTrait for HostInfo {
|
||||||
/// Returns public key
|
fn id(&self) -> &NodeId {
|
||||||
pub fn id(&self) -> &NodeId {
|
|
||||||
self.keys.public()
|
self.keys.public()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns secret key
|
fn secret(&self) -> &Secret {
|
||||||
pub fn secret(&self) -> &Secret {
|
|
||||||
self.keys.secret()
|
self.keys.secret()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Increments and returns connection nonce.
|
fn next_nonce(&mut self) -> H256 {
|
||||||
pub fn next_nonce(&mut self) -> H256 {
|
|
||||||
self.nonce = keccak(&self.nonce);
|
self.nonce = keccak(&self.nonce);
|
||||||
self.nonce
|
self.nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_version(&self) -> &str {
|
fn client_version(&self) -> &str {
|
||||||
&self.config.client_version
|
&self.config.client_version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +242,7 @@ pub struct Host {
|
|||||||
sessions: Arc<RwLock<Slab<SharedSession>>>,
|
sessions: Arc<RwLock<Slab<SharedSession>>>,
|
||||||
discovery: Mutex<Option<Discovery>>,
|
discovery: Mutex<Option<Discovery>>,
|
||||||
nodes: RwLock<NodeTable>,
|
nodes: RwLock<NodeTable>,
|
||||||
handlers: RwLock<HashMap<ProtocolId, Arc<NetworkProtocolHandler>>>,
|
handlers: RwLock<HashMap<ProtocolId, Arc<NetworkProtocolHandler + Sync>>>,
|
||||||
timers: RwLock<HashMap<TimerToken, ProtocolTimer>>,
|
timers: RwLock<HashMap<TimerToken, ProtocolTimer>>,
|
||||||
timer_counter: RwLock<usize>,
|
timer_counter: RwLock<usize>,
|
||||||
stats: Arc<NetworkStats>,
|
stats: Arc<NetworkStats>,
|
||||||
@ -1006,14 +870,14 @@ impl Host {
|
|||||||
self.nodes.write().update(node_changes, &*self.reserved_nodes.read());
|
self.nodes.write().update(node_changes, &*self.reserved_nodes.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_context<F>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) where F: FnOnce(&NetworkContext) {
|
pub fn with_context<F>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) where F: FnOnce(&NetworkContextTrait) {
|
||||||
let reserved = { self.reserved_nodes.read() };
|
let reserved = { self.reserved_nodes.read() };
|
||||||
|
|
||||||
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
|
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
|
||||||
action(&context);
|
action(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_context_eval<F, T>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) -> T where F: FnOnce(&NetworkContext) -> T {
|
pub fn with_context_eval<F, T>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) -> T where F: FnOnce(&NetworkContextTrait) -> T {
|
||||||
let reserved = { self.reserved_nodes.read() };
|
let reserved = { self.reserved_nodes.read() };
|
||||||
|
|
||||||
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
|
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
|
118
util/network-devp2p/src/lib.rs
Normal file
118
util/network-devp2p/src/lib.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Network and general IO module.
|
||||||
|
//!
|
||||||
|
//! Example usage for creating a network service and adding an IO handler:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! extern crate ethcore_network as net;
|
||||||
|
//! extern crate ethcore_network_devp2p as devp2p;
|
||||||
|
//! use net::*;
|
||||||
|
//! use devp2p::NetworkService;
|
||||||
|
//! use std::sync::Arc;
|
||||||
|
//!
|
||||||
|
//! struct MyHandler;
|
||||||
|
//!
|
||||||
|
//! impl NetworkProtocolHandler for MyHandler {
|
||||||
|
//! fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
||||||
|
//! io.register_timer(0, 1000);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||||
|
//! println!("Received {} ({} bytes) from {}", packet_id, data.len(), peer);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
|
//! println!("Connected {}", peer);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
|
//! println!("Disconnected {}", peer);
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn main () {
|
||||||
|
//! let mut service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service");
|
||||||
|
//! service.start().expect("Error starting service");
|
||||||
|
//! service.register_protocol(Arc::new(MyHandler), *b"myp", 1, &[1u8]);
|
||||||
|
//!
|
||||||
|
//! // Wait for quit condition
|
||||||
|
//! // ...
|
||||||
|
//! // Drop the service
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
//TODO: use Poll from mio
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
extern crate ethcore_io as io;
|
||||||
|
extern crate ethcore_bytes;
|
||||||
|
extern crate ethereum_types;
|
||||||
|
extern crate parking_lot;
|
||||||
|
extern crate mio;
|
||||||
|
extern crate tiny_keccak;
|
||||||
|
extern crate crypto as rcrypto;
|
||||||
|
extern crate rand;
|
||||||
|
extern crate time;
|
||||||
|
extern crate ansi_term; //TODO: remove this
|
||||||
|
extern crate rustc_hex;
|
||||||
|
extern crate igd;
|
||||||
|
extern crate libc;
|
||||||
|
extern crate slab;
|
||||||
|
extern crate ethkey;
|
||||||
|
extern crate ethcrypto as crypto;
|
||||||
|
extern crate rlp;
|
||||||
|
extern crate bytes;
|
||||||
|
extern crate path;
|
||||||
|
extern crate ethcore_logger;
|
||||||
|
extern crate ethcore_network as network;
|
||||||
|
extern crate ipnetwork;
|
||||||
|
extern crate keccak_hash as hash;
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
extern crate snappy;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate error_chain;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate tempdir;
|
||||||
|
|
||||||
|
mod host;
|
||||||
|
mod connection;
|
||||||
|
mod handshake;
|
||||||
|
mod session;
|
||||||
|
mod discovery;
|
||||||
|
mod service;
|
||||||
|
mod node_table;
|
||||||
|
mod stats;
|
||||||
|
mod ip_utils;
|
||||||
|
mod connection_filter;
|
||||||
|
|
||||||
|
pub use service::NetworkService;
|
||||||
|
pub use stats::NetworkStats;
|
||||||
|
pub use connection_filter::{ConnectionFilter, ConnectionDirection};
|
||||||
|
pub use host::NetworkContext;
|
||||||
|
|
||||||
|
pub use io::TimerToken;
|
||||||
|
pub use node_table::{validate_node_url, NodeId};
|
||||||
|
|
||||||
|
const PROTOCOL_VERSION: u32 = 5;
|
@ -23,8 +23,7 @@ use std::str::FromStr;
|
|||||||
use std::{fs, mem, slice};
|
use std::{fs, mem, slice};
|
||||||
use ethereum_types::H512;
|
use ethereum_types::H512;
|
||||||
use rlp::*;
|
use rlp::*;
|
||||||
use error::{Error, ErrorKind};
|
use network::{Error, ErrorKind, AllowIP, IpFilter};
|
||||||
use {AllowIP, IpFilter};
|
|
||||||
use discovery::{TableUpdates, NodeEntry};
|
use discovery::{TableUpdates, NodeEntry};
|
||||||
use ip_utils::*;
|
use ip_utils::*;
|
||||||
use serde_json;
|
use serde_json;
|
@ -14,9 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use {NetworkProtocolHandler, NetworkConfiguration, NonReservedPeerMode};
|
use network::{Error, NetworkConfiguration, NetworkProtocolHandler, NonReservedPeerMode};
|
||||||
use error::Error;
|
use network::{NetworkContext, PeerId, ProtocolId, NetworkIoMessage};
|
||||||
use host::{Host, NetworkContext, NetworkIoMessage, PeerId, ProtocolId};
|
use host::Host;
|
||||||
use stats::NetworkStats;
|
use stats::NetworkStats;
|
||||||
use io::*;
|
use io::*;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
use std::{str, io};
|
use std::{str, io};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
@ -28,7 +27,8 @@ use rlp::*;
|
|||||||
use connection::{EncryptedConnection, Packet, Connection, MAX_PAYLOAD_SIZE};
|
use connection::{EncryptedConnection, Packet, Connection, MAX_PAYLOAD_SIZE};
|
||||||
use handshake::Handshake;
|
use handshake::Handshake;
|
||||||
use io::{IoContext, StreamToken};
|
use io::{IoContext, StreamToken};
|
||||||
use error::{Error, ErrorKind, DisconnectReason};
|
use network::{Error, ErrorKind, DisconnectReason, SessionInfo, ProtocolId, PeerCapabilityInfo};
|
||||||
|
use network::{SessionCapabilityInfo, HostInfo as HostInfoTrait};
|
||||||
use host::*;
|
use host::*;
|
||||||
use node_table::NodeId;
|
use node_table::NodeId;
|
||||||
use stats::NetworkStats;
|
use stats::NetworkStats;
|
||||||
@ -90,81 +90,6 @@ pub enum SessionData {
|
|||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared session information
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct SessionInfo {
|
|
||||||
/// Peer public key
|
|
||||||
pub id: Option<NodeId>,
|
|
||||||
/// Peer client ID
|
|
||||||
pub client_version: String,
|
|
||||||
/// Peer RLPx protocol version
|
|
||||||
pub protocol_version: u32,
|
|
||||||
/// Session protocol capabilities
|
|
||||||
pub capabilities: Vec<SessionCapabilityInfo>,
|
|
||||||
/// Peer protocol capabilities
|
|
||||||
pub peer_capabilities: Vec<PeerCapabilityInfo>,
|
|
||||||
/// Peer ping delay in milliseconds
|
|
||||||
pub ping_ms: Option<u64>,
|
|
||||||
/// True if this session was originated by us.
|
|
||||||
pub originated: bool,
|
|
||||||
/// Remote endpoint address of the session
|
|
||||||
pub remote_address: String,
|
|
||||||
/// Local endpoint address of the session
|
|
||||||
pub local_address: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct PeerCapabilityInfo {
|
|
||||||
pub protocol: ProtocolId,
|
|
||||||
pub version: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decodable for PeerCapabilityInfo {
|
|
||||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
||||||
let p: Vec<u8> = rlp.val_at(0)?;
|
|
||||||
if p.len() != 3 {
|
|
||||||
return Err(DecoderError::Custom("Invalid subprotocol string length. Should be 3"));
|
|
||||||
}
|
|
||||||
let mut p2: ProtocolId = [0u8; 3];
|
|
||||||
p2.clone_from_slice(&p);
|
|
||||||
Ok(PeerCapabilityInfo {
|
|
||||||
protocol: p2,
|
|
||||||
version: rlp.val_at(1)?
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for PeerCapabilityInfo {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
format!("{}/{}", str::from_utf8(&self.protocol[..]).unwrap_or("???"), self.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct SessionCapabilityInfo {
|
|
||||||
pub protocol: [u8; 3],
|
|
||||||
pub version: u8,
|
|
||||||
pub packet_count: u8,
|
|
||||||
pub id_offset: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for SessionCapabilityInfo {
|
|
||||||
fn partial_cmp(&self, other: &SessionCapabilityInfo) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for SessionCapabilityInfo {
|
|
||||||
fn cmp(&self, b: &SessionCapabilityInfo) -> Ordering {
|
|
||||||
// By protocol id first
|
|
||||||
if self.protocol != b.protocol {
|
|
||||||
return self.protocol.cmp(&b.protocol);
|
|
||||||
}
|
|
||||||
// By version
|
|
||||||
self.version.cmp(&b.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const PACKET_HELLO: u8 = 0x80;
|
const PACKET_HELLO: u8 = 0x80;
|
||||||
const PACKET_DISCONNECT: u8 = 0x01;
|
const PACKET_DISCONNECT: u8 = 0x01;
|
||||||
const PACKET_PING: u8 = 0x02;
|
const PACKET_PING: u8 = 0x02;
|
@ -21,6 +21,7 @@ extern crate ethcore_bytes;
|
|||||||
extern crate ethcore_io as io;
|
extern crate ethcore_io as io;
|
||||||
extern crate ethcore_logger;
|
extern crate ethcore_logger;
|
||||||
extern crate ethcore_network;
|
extern crate ethcore_network;
|
||||||
|
extern crate ethcore_network_devp2p;
|
||||||
extern crate ethkey;
|
extern crate ethkey;
|
||||||
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
|
||||||
@ -30,6 +31,7 @@ use std::time::*;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use ethcore_bytes::Bytes;
|
use ethcore_bytes::Bytes;
|
||||||
use ethcore_network::*;
|
use ethcore_network::*;
|
||||||
|
use ethcore_network_devp2p::NetworkService;
|
||||||
use ethkey::{Random, Generator};
|
use ethkey::{Random, Generator};
|
||||||
use io::TimerToken;
|
use io::TimerToken;
|
||||||
|
|
@ -7,37 +7,11 @@ version = "1.11.0"
|
|||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
|
||||||
mio = "0.6.8"
|
|
||||||
bytes = "0.4"
|
|
||||||
rand = "0.4"
|
|
||||||
time = "0.1.34"
|
|
||||||
tiny-keccak = "1.3"
|
|
||||||
rust-crypto = "0.2.34"
|
|
||||||
slab = "0.2"
|
|
||||||
igd = "0.6"
|
|
||||||
libc = "0.2.7"
|
|
||||||
parking_lot = "0.5"
|
|
||||||
ansi_term = "0.10"
|
|
||||||
rustc-hex = "1.0"
|
|
||||||
ethcore-io = { path = "../io" }
|
ethcore-io = { path = "../io" }
|
||||||
ethcore-bytes = { path = "../bytes" }
|
|
||||||
ethereum-types = "0.2"
|
ethereum-types = "0.2"
|
||||||
ethkey = { path = "../../ethkey" }
|
ethkey = { path = "../../ethkey" }
|
||||||
ethcrypto = { path = "../../ethcrypto" }
|
ethcrypto = { path = "../../ethcrypto" }
|
||||||
rlp = { path = "../rlp" }
|
rlp = { path = "../rlp" }
|
||||||
path = { path = "../path" }
|
|
||||||
ethcore-logger = { path ="../../logger" }
|
|
||||||
ipnetwork = "0.12.6"
|
ipnetwork = "0.12.6"
|
||||||
keccak-hash = { path = "../hash" }
|
|
||||||
snappy = { git = "https://github.com/paritytech/rust-snappy" }
|
snappy = { git = "https://github.com/paritytech/rust-snappy" }
|
||||||
serde = "1.0"
|
|
||||||
serde_json = "1.0"
|
|
||||||
serde_derive = "1.0"
|
|
||||||
error-chain = { version = "0.11", default-features = false }
|
error-chain = { version = "0.11", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempdir = "0.3"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||||
// This file is part of Parity.
|
// This file is part of Parity.
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
@ -14,111 +14,338 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Network and general IO module.
|
|
||||||
//!
|
|
||||||
//! Example usage for craeting a network service and adding an IO handler:
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! extern crate ethcore_network as net;
|
|
||||||
//! use net::*;
|
|
||||||
//! use std::sync::Arc;
|
|
||||||
//!
|
|
||||||
//! struct MyHandler;
|
|
||||||
//!
|
|
||||||
//! impl NetworkProtocolHandler for MyHandler {
|
|
||||||
//! fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
|
||||||
//! io.register_timer(0, 1000);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
|
||||||
//! println!("Received {} ({} bytes) from {}", packet_id, data.len(), peer);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
|
||||||
//! println!("Connected {}", peer);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
|
|
||||||
//! println!("Disconnected {}", peer);
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! fn main () {
|
|
||||||
//! let mut service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service");
|
|
||||||
//! service.start().expect("Error starting service");
|
|
||||||
//! service.register_protocol(Arc::new(MyHandler), *b"myp", 1, &[1u8]);
|
|
||||||
//!
|
|
||||||
//! // Wait for quit condition
|
|
||||||
//! // ...
|
|
||||||
//! // Drop the service
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
//TODO: use Poll from mio
|
|
||||||
#![allow(deprecated)]
|
|
||||||
#![recursion_limit="128"]
|
#![recursion_limit="128"]
|
||||||
|
|
||||||
extern crate ethcore_io as io;
|
extern crate ethcore_io as io;
|
||||||
extern crate ethcore_bytes;
|
|
||||||
extern crate ethereum_types;
|
|
||||||
extern crate parking_lot;
|
|
||||||
extern crate mio;
|
|
||||||
extern crate tiny_keccak;
|
|
||||||
extern crate crypto as rcrypto;
|
|
||||||
extern crate rand;
|
|
||||||
extern crate time;
|
|
||||||
extern crate ansi_term; //TODO: remove this
|
|
||||||
extern crate rustc_hex;
|
|
||||||
extern crate igd;
|
|
||||||
extern crate libc;
|
|
||||||
extern crate slab;
|
|
||||||
extern crate ethkey;
|
|
||||||
extern crate ethcrypto as crypto;
|
extern crate ethcrypto as crypto;
|
||||||
|
extern crate ethereum_types;
|
||||||
|
extern crate ethkey;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate bytes;
|
|
||||||
extern crate path;
|
|
||||||
extern crate ethcore_logger;
|
|
||||||
extern crate ipnetwork;
|
extern crate ipnetwork;
|
||||||
extern crate keccak_hash as hash;
|
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_json;
|
|
||||||
extern crate snappy;
|
extern crate snappy;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate error_chain;
|
extern crate error_chain;
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate tempdir;
|
|
||||||
|
|
||||||
mod host;
|
|
||||||
mod connection;
|
|
||||||
mod handshake;
|
|
||||||
mod session;
|
|
||||||
mod discovery;
|
|
||||||
mod service;
|
|
||||||
mod error;
|
mod error;
|
||||||
mod node_table;
|
|
||||||
mod stats;
|
|
||||||
mod ip_utils;
|
|
||||||
mod connection_filter;
|
|
||||||
|
|
||||||
pub use host::{HostInfo, PeerId, PacketId, ProtocolId, NetworkContext, NetworkIoMessage, NetworkConfiguration};
|
|
||||||
pub use service::NetworkService;
|
|
||||||
pub use error::{Error, ErrorKind};
|
|
||||||
pub use stats::NetworkStats;
|
|
||||||
pub use session::SessionInfo;
|
|
||||||
pub use connection_filter::{ConnectionFilter, ConnectionDirection};
|
|
||||||
|
|
||||||
pub use io::TimerToken;
|
pub use io::TimerToken;
|
||||||
pub use node_table::{validate_node_url, NodeId};
|
pub use error::{Error, ErrorKind, DisconnectReason};
|
||||||
use ipnetwork::{IpNetwork, IpNetworkError};
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
const PROTOCOL_VERSION: u32 = 5;
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
|
||||||
|
use std::str::{self, FromStr};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use ipnetwork::{IpNetwork, IpNetworkError};
|
||||||
|
use io::IoChannel;
|
||||||
|
use ethkey::Secret;
|
||||||
|
use ethereum_types::{H256, H512};
|
||||||
|
use rlp::{Decodable, DecoderError, UntrustedRlp};
|
||||||
|
|
||||||
|
/// Protocol handler level packet id
|
||||||
|
pub type PacketId = u8;
|
||||||
|
/// Protocol / handler id
|
||||||
|
pub type ProtocolId = [u8; 3];
|
||||||
|
|
||||||
|
/// Node public key
|
||||||
|
pub type NodeId = H512;
|
||||||
|
|
||||||
|
/// Local (temporary) peer session ID.
|
||||||
|
pub type PeerId = usize;
|
||||||
|
|
||||||
|
/// Messages used to communitate with the event loop from other threads.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum NetworkIoMessage {
|
||||||
|
/// Register a new protocol handler.
|
||||||
|
AddHandler {
|
||||||
|
/// Handler shared instance.
|
||||||
|
handler: Arc<NetworkProtocolHandler + Sync>,
|
||||||
|
/// Protocol Id.
|
||||||
|
protocol: ProtocolId,
|
||||||
|
/// Supported protocol versions.
|
||||||
|
versions: Vec<u8>,
|
||||||
|
/// Number of packet IDs reserved by the protocol.
|
||||||
|
packet_count: u8,
|
||||||
|
},
|
||||||
|
/// Register a new protocol timer
|
||||||
|
AddTimer {
|
||||||
|
/// Protocol Id.
|
||||||
|
protocol: ProtocolId,
|
||||||
|
/// Timer token.
|
||||||
|
token: TimerToken,
|
||||||
|
/// Timer delay in milliseconds.
|
||||||
|
delay: u64,
|
||||||
|
},
|
||||||
|
/// Initliaze public interface.
|
||||||
|
InitPublicInterface,
|
||||||
|
/// Disconnect a peer.
|
||||||
|
Disconnect(PeerId),
|
||||||
|
/// Disconnect and temporary disable peer.
|
||||||
|
DisablePeer(PeerId),
|
||||||
|
/// Network has been started with the host as the given enode.
|
||||||
|
NetworkStarted(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shared session information
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SessionInfo {
|
||||||
|
/// Peer public key
|
||||||
|
pub id: Option<NodeId>,
|
||||||
|
/// Peer client ID
|
||||||
|
pub client_version: String,
|
||||||
|
/// Peer RLPx protocol version
|
||||||
|
pub protocol_version: u32,
|
||||||
|
/// Session protocol capabilities
|
||||||
|
pub capabilities: Vec<SessionCapabilityInfo>,
|
||||||
|
/// Peer protocol capabilities
|
||||||
|
pub peer_capabilities: Vec<PeerCapabilityInfo>,
|
||||||
|
/// Peer ping delay in milliseconds
|
||||||
|
pub ping_ms: Option<u64>,
|
||||||
|
/// True if this session was originated by us.
|
||||||
|
pub originated: bool,
|
||||||
|
/// Remote endpoint address of the session
|
||||||
|
pub remote_address: String,
|
||||||
|
/// Local endpoint address of the session
|
||||||
|
pub local_address: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct PeerCapabilityInfo {
|
||||||
|
pub protocol: ProtocolId,
|
||||||
|
pub version: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decodable for PeerCapabilityInfo {
|
||||||
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||||
|
let p: Vec<u8> = rlp.val_at(0)?;
|
||||||
|
if p.len() != 3 {
|
||||||
|
return Err(DecoderError::Custom("Invalid subprotocol string length. Should be 3"));
|
||||||
|
}
|
||||||
|
let mut p2: ProtocolId = [0u8; 3];
|
||||||
|
p2.clone_from_slice(&p);
|
||||||
|
Ok(PeerCapabilityInfo {
|
||||||
|
protocol: p2,
|
||||||
|
version: rlp.val_at(1)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for PeerCapabilityInfo {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("{}/{}", str::from_utf8(&self.protocol[..]).unwrap_or("???"), self.version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct SessionCapabilityInfo {
|
||||||
|
pub protocol: [u8; 3],
|
||||||
|
pub version: u8,
|
||||||
|
pub packet_count: u8,
|
||||||
|
pub id_offset: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for SessionCapabilityInfo {
|
||||||
|
fn partial_cmp(&self, other: &SessionCapabilityInfo) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for SessionCapabilityInfo {
|
||||||
|
fn cmp(&self, b: &SessionCapabilityInfo) -> Ordering {
|
||||||
|
// By protocol id first
|
||||||
|
if self.protocol != b.protocol {
|
||||||
|
return self.protocol.cmp(&b.protocol);
|
||||||
|
}
|
||||||
|
// By version
|
||||||
|
self.version.cmp(&b.version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Network service configuration
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct NetworkConfiguration {
|
||||||
|
/// Directory path to store general network configuration. None means nothing will be saved
|
||||||
|
pub config_path: Option<String>,
|
||||||
|
/// Directory path to store network-specific configuration. None means nothing will be saved
|
||||||
|
pub net_config_path: Option<String>,
|
||||||
|
/// IP address to listen for incoming connections. Listen to all connections by default
|
||||||
|
pub listen_address: Option<SocketAddr>,
|
||||||
|
/// IP address to advertise. Detected automatically if none.
|
||||||
|
pub public_address: Option<SocketAddr>,
|
||||||
|
/// Port for UDP connections, same as TCP by default
|
||||||
|
pub udp_port: Option<u16>,
|
||||||
|
/// Enable NAT configuration
|
||||||
|
pub nat_enabled: bool,
|
||||||
|
/// Enable discovery
|
||||||
|
pub discovery_enabled: bool,
|
||||||
|
/// List of initial node addresses
|
||||||
|
pub boot_nodes: Vec<String>,
|
||||||
|
/// Use provided node key instead of default
|
||||||
|
pub use_secret: Option<Secret>,
|
||||||
|
/// Minimum number of connected peers to maintain
|
||||||
|
pub min_peers: u32,
|
||||||
|
/// Maximum allowed number of peers
|
||||||
|
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.
|
||||||
|
pub reserved_nodes: Vec<String>,
|
||||||
|
/// The non-reserved peer mode.
|
||||||
|
pub non_reserved_mode: NonReservedPeerMode,
|
||||||
|
/// IP filter
|
||||||
|
pub ip_filter: IpFilter,
|
||||||
|
/// Client identifier
|
||||||
|
pub client_version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NetworkConfiguration {
|
||||||
|
fn default() -> Self {
|
||||||
|
NetworkConfiguration::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NetworkConfiguration {
|
||||||
|
/// Create a new instance of default settings.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
NetworkConfiguration {
|
||||||
|
config_path: None,
|
||||||
|
net_config_path: None,
|
||||||
|
listen_address: None,
|
||||||
|
public_address: None,
|
||||||
|
udp_port: None,
|
||||||
|
nat_enabled: true,
|
||||||
|
discovery_enabled: true,
|
||||||
|
boot_nodes: Vec::new(),
|
||||||
|
use_secret: None,
|
||||||
|
min_peers: 25,
|
||||||
|
max_peers: 50,
|
||||||
|
max_handshakes: 64,
|
||||||
|
reserved_protocols: HashMap::new(),
|
||||||
|
ip_filter: IpFilter::default(),
|
||||||
|
reserved_nodes: Vec::new(),
|
||||||
|
non_reserved_mode: NonReservedPeerMode::Accept,
|
||||||
|
client_version: "Parity-network".into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new default configuration with sepcified listen port.
|
||||||
|
pub fn new_with_port(port: u16) -> NetworkConfiguration {
|
||||||
|
let mut config = NetworkConfiguration::new();
|
||||||
|
config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port)));
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new default configuration for localhost-only connection with random port (usefull for testing)
|
||||||
|
pub fn new_local() -> NetworkConfiguration {
|
||||||
|
let mut config = NetworkConfiguration::new();
|
||||||
|
config.listen_address = Some(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0)));
|
||||||
|
config.nat_enabled = false;
|
||||||
|
config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem.
|
||||||
|
pub trait NetworkContext {
|
||||||
|
/// Send a packet over the network to another peer.
|
||||||
|
fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Send a packet over the network to another peer using specified protocol.
|
||||||
|
fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Respond to a current network message. Panics if no there is no packet in the context. If the session is expired returns nothing.
|
||||||
|
fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Get an IoChannel.
|
||||||
|
fn io_channel(&self) -> IoChannel<NetworkIoMessage>;
|
||||||
|
|
||||||
|
/// Disconnect a peer and prevent it from connecting again.
|
||||||
|
fn disable_peer(&self, peer: PeerId);
|
||||||
|
|
||||||
|
/// Disconnect peer. Reconnect can be attempted later.
|
||||||
|
fn disconnect_peer(&self, peer: PeerId);
|
||||||
|
|
||||||
|
/// Check if the session is still active.
|
||||||
|
fn is_expired(&self) -> bool;
|
||||||
|
|
||||||
|
/// Register a new IO timer. 'IoHandler::timeout' will be called with the token.
|
||||||
|
fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Returns peer identification string
|
||||||
|
fn peer_client_version(&self, peer: PeerId) -> String;
|
||||||
|
|
||||||
|
/// Returns information on p2p session
|
||||||
|
fn session_info(&self, peer: PeerId) -> Option<SessionInfo>;
|
||||||
|
|
||||||
|
/// Returns max version for a given protocol.
|
||||||
|
fn protocol_version(&self, protocol: ProtocolId, peer: PeerId) -> Option<u8>;
|
||||||
|
|
||||||
|
/// Returns this object's subprotocol name.
|
||||||
|
fn subprotocol_name(&self) -> ProtocolId;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext {
|
||||||
|
fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
|
(**self).send(peer, packet_id, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
|
(**self).send_protocol(protocol, peer, packet_id, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> {
|
||||||
|
(**self).respond(packet_id, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn io_channel(&self) -> IoChannel<NetworkIoMessage> {
|
||||||
|
(**self).io_channel()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disable_peer(&self, peer: PeerId) {
|
||||||
|
(**self).disable_peer(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disconnect_peer(&self, peer: PeerId) {
|
||||||
|
(**self).disconnect_peer(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_expired(&self) -> bool {
|
||||||
|
(**self).is_expired()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), Error> {
|
||||||
|
(**self).register_timer(token, ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peer_client_version(&self, peer: PeerId) -> String {
|
||||||
|
(**self).peer_client_version(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn session_info(&self, peer: PeerId) -> Option<SessionInfo> {
|
||||||
|
(**self).session_info(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn protocol_version(&self, protocol: ProtocolId, peer: PeerId) -> Option<u8> {
|
||||||
|
(**self).protocol_version(protocol, peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subprotocol_name(&self) -> ProtocolId {
|
||||||
|
(**self).subprotocol_name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait HostInfo {
|
||||||
|
/// Returns public key
|
||||||
|
fn id(&self) -> &NodeId;
|
||||||
|
/// Returns secret key
|
||||||
|
fn secret(&self) -> &Secret;
|
||||||
|
/// Increments and returns connection nonce.
|
||||||
|
fn next_nonce(&mut self) -> H256;
|
||||||
|
/// Returns the client version.
|
||||||
|
fn client_version(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
/// Network IO protocol handler. This needs to be implemented for each new subprotocol.
|
/// Network IO protocol handler. This needs to be implemented for each new subprotocol.
|
||||||
/// All the handler function are called from within IO event loop.
|
/// All the handler function are called from within IO event loop.
|
||||||
@ -157,7 +384,6 @@ impl NonReservedPeerMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "ipc", binary)]
|
|
||||||
pub struct IpFilter {
|
pub struct IpFilter {
|
||||||
pub predefined: AllowIP,
|
pub predefined: AllowIP,
|
||||||
pub custom_allow: Vec<IpNetwork>,
|
pub custom_allow: Vec<IpNetwork>,
|
||||||
|
@ -392,7 +392,7 @@ pub trait Context {
|
|||||||
fn send(&self, PeerId, u8, Vec<u8>);
|
fn send(&self, PeerId, u8, Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context for NetworkContext<'a> {
|
impl<T> Context for T where T: ?Sized + NetworkContext {
|
||||||
fn disconnect_peer(&self, peer: PeerId) {
|
fn disconnect_peer(&self, peer: PeerId) {
|
||||||
NetworkContext::disconnect_peer(self, peer);
|
NetworkContext::disconnect_peer(self, peer);
|
||||||
}
|
}
|
||||||
@ -437,7 +437,7 @@ impl<T> Network<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Post a message to the whisper network to be relayed.
|
/// Post a message to the whisper network to be relayed.
|
||||||
pub fn post_message<C: Context>(&self, message: Message, context: &C) -> bool
|
pub fn post_message<C: ?Sized + Context>(&self, message: Message, context: &C) -> bool
|
||||||
where T: MessageHandler
|
where T: MessageHandler
|
||||||
{
|
{
|
||||||
let ok = self.messages.write().insert(message);
|
let ok = self.messages.write().insert(message);
|
||||||
@ -452,7 +452,7 @@ impl<T> Network<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: MessageHandler> Network<T> {
|
impl<T: MessageHandler> Network<T> {
|
||||||
fn rally<C: Context>(&self, io: &C) {
|
fn rally<C: ?Sized + Context>(&self, io: &C) {
|
||||||
// cannot be greater than 16MB (protocol limitation)
|
// cannot be greater than 16MB (protocol limitation)
|
||||||
const MAX_MESSAGES_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
const MAX_MESSAGES_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
||||||
|
|
||||||
@ -627,7 +627,7 @@ impl<T: MessageHandler> Network<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_connect<C: Context>(&self, io: &C, peer: &PeerId) {
|
fn on_connect<C: ?Sized + Context>(&self, io: &C, peer: &PeerId) {
|
||||||
trace!(target: "whisper", "Connecting peer {}", peer);
|
trace!(target: "whisper", "Connecting peer {}", peer);
|
||||||
|
|
||||||
let node_key = match io.node_key(*peer) {
|
let node_key = match io.node_key(*peer) {
|
||||||
@ -660,7 +660,7 @@ impl<T: MessageHandler> Network<T> {
|
|||||||
io.send(*peer, packet::STATUS, ::rlp::EMPTY_LIST_RLP.to_vec());
|
io.send(*peer, packet::STATUS, ::rlp::EMPTY_LIST_RLP.to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_packet<C: Context>(&self, io: &C, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
fn on_packet<C: ?Sized + Context>(&self, io: &C, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||||
let rlp = UntrustedRlp::new(data);
|
let rlp = UntrustedRlp::new(data);
|
||||||
let res = match packet_id {
|
let res = match packet_id {
|
||||||
packet::STATUS => self.on_status(peer, rlp),
|
packet::STATUS => self.on_status(peer, rlp),
|
||||||
@ -708,7 +708,7 @@ impl<T: MessageHandler> ::network::NetworkProtocolHandler for Network<T> {
|
|||||||
// rally with each peer and handle timeouts.
|
// rally with each peer and handle timeouts.
|
||||||
match timer {
|
match timer {
|
||||||
RALLY_TOKEN => self.rally(io),
|
RALLY_TOKEN => self.rally(io),
|
||||||
other => debug!(target: "whisper", "Timout triggered on unknown token {}", other),
|
other => debug!(target: "whisper", "Timeout triggered on unknown token {}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user