Get public address/UPNP refactoring
This commit is contained in:
parent
64913d5009
commit
203947388b
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -214,6 +214,7 @@ dependencies = [
|
||||
"itertools 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"json-tests 0.1.0",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -64,8 +64,8 @@ Options:
|
||||
-d --db-path PATH Specify the database & configuration directory path [default: $HOME/.parity]
|
||||
|
||||
--no-bootstrap Don't bother trying to connect to any nodes initially.
|
||||
--listen-address URL Specify the IP/port on which to listen for peers [default: 0.0.0.0:30304].
|
||||
--public-address URL Specify the IP/port on which peers may connect [default: 0.0.0.0:30304].
|
||||
--listen-address URL Specify the IP/port on which to listen for peers.
|
||||
--public-address URL Specify the IP/port on which peers may connect.
|
||||
--address URL Equivalent to --listen-address URL --public-address URL.
|
||||
--upnp Use UPnP to try to figure out the correct network settings.
|
||||
--node-key KEY Specify node secret key as hex string.
|
||||
@ -79,7 +79,12 @@ Options:
|
||||
-l --logging LOGGING Specify the logging level.
|
||||
-v --version Show information about version.
|
||||
-h --help Show this screen.
|
||||
", flag_cache_pref_size: usize, flag_cache_max_size: usize, flag_address: Option<String>, flag_node_key: Option<String>);
|
||||
", flag_cache_pref_size: usize,
|
||||
flag_cache_max_size: usize,
|
||||
flag_address: Option<String>,
|
||||
flag_listen_address: Option<String>,
|
||||
flag_public_address: Option<String>,
|
||||
flag_node_key: Option<String>);
|
||||
|
||||
fn setup_log(init: &str) {
|
||||
let mut builder = LogBuilder::new();
|
||||
@ -155,21 +160,26 @@ impl Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
fn net_addresses(&self) -> (SocketAddr, SocketAddr) {
|
||||
let listen_address;
|
||||
let public_address;
|
||||
fn net_addresses(&self) -> (Option<SocketAddr>, Option<SocketAddr>) {
|
||||
let mut listen_address = None;
|
||||
let mut public_address = None;
|
||||
|
||||
match self.args.flag_address {
|
||||
None => {
|
||||
listen_address = SocketAddr::from_str(self.args.flag_listen_address.as_ref()).expect("Invalid listen address given with --listen-address");
|
||||
public_address = SocketAddr::from_str(self.args.flag_public_address.as_ref()).expect("Invalid public address given with --public-address");
|
||||
if let Some(ref a) = self.args.flag_address {
|
||||
public_address = Some(SocketAddr::from_str(a.as_ref()).expect("Invalid listen/public address given with --address"));
|
||||
listen_address = public_address;
|
||||
}
|
||||
if let Some(ref a) = self.args.flag_listen_address {
|
||||
if listen_address.is_some() {
|
||||
panic!("Conflicting flags: --address and --listen-address");
|
||||
}
|
||||
Some(ref a) => {
|
||||
public_address = SocketAddr::from_str(a.as_ref()).expect("Invalid listen/public address given with --address");
|
||||
listen_address = public_address;
|
||||
listen_address = Some(SocketAddr::from_str(a.as_ref()).expect("Invalid listen address given with --listen-address"));
|
||||
}
|
||||
if let Some(ref a) = self.args.flag_public_address {
|
||||
if public_address.is_some() {
|
||||
panic!("Conflicting flags: --address and --public-address");
|
||||
}
|
||||
};
|
||||
|
||||
public_address = Some(SocketAddr::from_str(a.as_ref()).expect("Invalid listen address given with --public-address"));
|
||||
}
|
||||
(listen_address, public_address)
|
||||
}
|
||||
}
|
||||
|
@ -30,3 +30,4 @@ clippy = "0.0.41"
|
||||
json-tests = { path = "json-tests" }
|
||||
target_info = "0.1.0"
|
||||
igd = "0.4.2"
|
||||
libc = "0.2.7"
|
||||
|
@ -110,6 +110,7 @@ extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate log as rlog;
|
||||
extern crate igd;
|
||||
extern crate libc;
|
||||
|
||||
pub mod standard;
|
||||
#[macro_use]
|
||||
|
@ -78,7 +78,7 @@ struct Datagramm {
|
||||
pub struct Discovery {
|
||||
id: NodeId,
|
||||
secret: Secret,
|
||||
address: NodeEndpoint,
|
||||
public_endpoint: NodeEndpoint,
|
||||
udp_socket: UdpSocket,
|
||||
token: StreamToken,
|
||||
discovery_round: u16,
|
||||
@ -94,12 +94,12 @@ pub struct TableUpdates {
|
||||
}
|
||||
|
||||
impl Discovery {
|
||||
pub fn new(key: &KeyPair, address: NodeEndpoint, token: StreamToken) -> Discovery {
|
||||
let socket = UdpSocket::bound(&address.udp_address()).expect("Error binding UDP socket");
|
||||
pub fn new(key: &KeyPair, listen: SocketAddr, public: NodeEndpoint, token: StreamToken) -> Discovery {
|
||||
let socket = UdpSocket::bound(&listen).expect("Error binding UDP socket");
|
||||
Discovery {
|
||||
id: key.public().clone(),
|
||||
secret: key.secret().clone(),
|
||||
address: address,
|
||||
public_endpoint: public,
|
||||
token: token,
|
||||
discovery_round: 0,
|
||||
discovery_id: NodeId::new(),
|
||||
@ -199,7 +199,7 @@ impl Discovery {
|
||||
fn ping(&mut self, node: &NodeEndpoint) {
|
||||
let mut rlp = RlpStream::new_list(3);
|
||||
rlp.append(&PROTOCOL_VERSION);
|
||||
self.address.to_rlp_list(&mut rlp);
|
||||
self.public_endpoint.to_rlp_list(&mut rlp);
|
||||
node.to_rlp_list(&mut rlp);
|
||||
trace!(target: "discovery", "Sent Ping to {:?}", &node);
|
||||
self.send_packet(PACKET_PING, &node.udp_address(), &rlp.drain());
|
||||
@ -507,8 +507,8 @@ mod tests {
|
||||
let key2 = KeyPair::create().unwrap();
|
||||
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 mut discovery1 = Discovery::new(&key1, ep1.clone(), 0);
|
||||
let mut discovery2 = Discovery::new(&key2, ep2.clone(), 0);
|
||||
let mut discovery1 = Discovery::new(&key1, ep1.address.clone(), ep1.clone(), 0);
|
||||
let mut discovery2 = Discovery::new(&key2, ep2.address.clone(), ep2.clone(), 0);
|
||||
|
||||
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();
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::net::{SocketAddr};
|
||||
use std::collections::{HashMap};
|
||||
use std::hash::{Hasher};
|
||||
use std::str::{FromStr};
|
||||
@ -39,8 +39,8 @@ use network::{NetworkProtocolHandler, PROTOCOL_VERSION};
|
||||
use network::node_table::*;
|
||||
use network::stats::NetworkStats;
|
||||
use network::error::DisconnectReason;
|
||||
use igd::{PortMappingProtocol, search_gateway};
|
||||
use network::discovery::{Discovery, TableUpdates, NodeEntry};
|
||||
use network::ip_utils::{map_external_address, select_public_address};
|
||||
|
||||
type Slab<T> = ::slab::Slab<T, usize>;
|
||||
|
||||
@ -55,10 +55,12 @@ const MAINTENANCE_TIMEOUT: u64 = 1000;
|
||||
pub struct NetworkConfiguration {
|
||||
/// Directory path to store network configuration. None means nothing will be saved
|
||||
pub config_path: Option<String>,
|
||||
/// IP address to listen for incoming connections
|
||||
pub listen_address: SocketAddr,
|
||||
/// IP address to advertise
|
||||
pub public_address: SocketAddr,
|
||||
/// 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
|
||||
@ -78,8 +80,9 @@ impl NetworkConfiguration {
|
||||
pub fn new() -> NetworkConfiguration {
|
||||
NetworkConfiguration {
|
||||
config_path: None,
|
||||
listen_address: SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
||||
public_address: SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
||||
listen_address: None,
|
||||
public_address: None,
|
||||
udp_port: None,
|
||||
nat_enabled: true,
|
||||
discovery_enabled: true,
|
||||
pin: false,
|
||||
@ -92,48 +95,9 @@ impl NetworkConfiguration {
|
||||
/// Create new default configuration with sepcified listen port.
|
||||
pub fn new_with_port(port: u16) -> NetworkConfiguration {
|
||||
let mut config = NetworkConfiguration::new();
|
||||
config.listen_address = SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap();
|
||||
config.public_address = SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap();
|
||||
config.listen_address = Some(SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap());
|
||||
config
|
||||
}
|
||||
|
||||
/// Conduct NAT if needed.
|
||||
pub fn prepared(self) -> Self {
|
||||
let mut listen = self.listen_address;
|
||||
let mut public = self.public_address;
|
||||
|
||||
if self.nat_enabled {
|
||||
info!("Enabling NAT...");
|
||||
match search_gateway() {
|
||||
Err(ref err) => warn!("Port mapping error: {}", err),
|
||||
Ok(gateway) => {
|
||||
let int_addr = SocketAddrV4::from_str("127.0.0.1:30304").unwrap();
|
||||
match gateway.get_any_address(PortMappingProtocol::TCP, int_addr, 0, "Parity Node/TCP") {
|
||||
Err(ref err) => {
|
||||
warn!("Port mapping error: {}", err);
|
||||
},
|
||||
Ok(ext_addr) => {
|
||||
info!("Local gateway: {}, External ip address: {}", gateway, ext_addr);
|
||||
public = SocketAddr::V4(ext_addr);
|
||||
listen = SocketAddr::V4(int_addr);
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
NetworkConfiguration {
|
||||
config_path: self.config_path,
|
||||
listen_address: listen,
|
||||
public_address: public,
|
||||
nat_enabled: false,
|
||||
discovery_enabled: self.discovery_enabled,
|
||||
pin: self.pin,
|
||||
boot_nodes: self.boot_nodes,
|
||||
use_secret: self.use_secret,
|
||||
ideal_peers: self.ideal_peers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tokens
|
||||
@ -333,16 +297,39 @@ pub struct Host<Message> where Message: Send + Sync + Clone {
|
||||
timers: RwLock<HashMap<TimerToken, ProtocolTimer>>,
|
||||
timer_counter: RwLock<usize>,
|
||||
stats: Arc<NetworkStats>,
|
||||
public_endpoint: NodeEndpoint,
|
||||
}
|
||||
|
||||
impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||
/// Create a new instance
|
||||
pub fn new(config: NetworkConfiguration) -> Host<Message> {
|
||||
let config = config.prepared();
|
||||
let listen_address = match config.listen_address {
|
||||
None => SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
||||
Some(addr) => addr,
|
||||
};
|
||||
|
||||
let udp_port = config.udp_port.unwrap_or(listen_address.port());
|
||||
let public_endpoint = match config.public_address {
|
||||
None => {
|
||||
let public_address = select_public_address(listen_address.port());
|
||||
let local_endpoint = NodeEndpoint { address: public_address, udp_port: udp_port };
|
||||
if config.nat_enabled {
|
||||
match map_external_address(&local_endpoint) {
|
||||
Some(endpoint) => {
|
||||
info!("NAT Mappped to external address {}", endpoint.address);
|
||||
endpoint
|
||||
},
|
||||
None => local_endpoint
|
||||
}
|
||||
} else {
|
||||
local_endpoint
|
||||
}
|
||||
}
|
||||
Some(addr) => NodeEndpoint { address: addr, udp_port: udp_port }
|
||||
};
|
||||
|
||||
let addr = config.listen_address;
|
||||
// Setup the server socket
|
||||
let tcp_listener = TcpListener::bind(&addr).unwrap();
|
||||
let tcp_listener = TcpListener::bind(&listen_address).unwrap();
|
||||
let keys = if let Some(ref secret) = config.use_secret {
|
||||
KeyPair::from_secret(secret.clone()).unwrap()
|
||||
} else {
|
||||
@ -356,8 +343,7 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||
},
|
||||
|s| KeyPair::from_secret(s).expect("Error creating node secret key"))
|
||||
};
|
||||
let endpoint = NodeEndpoint { address: config.public_address.clone(), udp_port: addr.port() };
|
||||
let discovery = Discovery::new(&keys, endpoint, DISCOVERY);
|
||||
let discovery = Discovery::new(&keys, listen_address.clone(), public_endpoint.clone(), DISCOVERY);
|
||||
let path = config.config_path.clone();
|
||||
let mut host = Host::<Message> {
|
||||
info: RwLock::new(HostInfo {
|
||||
@ -378,8 +364,9 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||
timers: RwLock::new(HashMap::new()),
|
||||
timer_counter: RwLock::new(USER_TIMER),
|
||||
stats: Arc::new(NetworkStats::default()),
|
||||
public_endpoint: public_endpoint,
|
||||
};
|
||||
let port = host.info.read().unwrap().config.listen_address.port();
|
||||
let port = listen_address.port();
|
||||
host.info.write().unwrap().deref_mut().listen_port = port;
|
||||
|
||||
let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone();
|
||||
@ -409,8 +396,8 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||
self.info.read().unwrap().client_version.clone()
|
||||
}
|
||||
|
||||
pub fn client_id(&self) -> NodeId {
|
||||
self.info.read().unwrap().id().clone()
|
||||
pub fn client_url(&self) -> String {
|
||||
format!("{}", Node::new(self.info.read().unwrap().id().clone(), self.public_endpoint.clone()))
|
||||
}
|
||||
|
||||
fn maintain_network(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
||||
@ -456,13 +443,15 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||
}
|
||||
|
||||
let handshake_count = self.handshake_count();
|
||||
if handshake_count >= MAX_HANDSHAKES {
|
||||
// allow 16 slots for incoming connections
|
||||
let handshake_limit = MAX_HANDSHAKES - 16;
|
||||
if handshake_count >= handshake_limit {
|
||||
return;
|
||||
}
|
||||
|
||||
let nodes = { self.nodes.read().unwrap().nodes() };
|
||||
for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id))
|
||||
.take(min(MAX_HANDSHAKES_PER_ROUND, MAX_HANDSHAKES - handshake_count)) {
|
||||
.take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) {
|
||||
self.connect_peer(&id, io);
|
||||
}
|
||||
debug!(target: "net", "Connecting peers: {} sessions, {} pending", self.session_count(), self.handshake_count());
|
||||
|
@ -73,6 +73,7 @@ mod service;
|
||||
mod error;
|
||||
mod node_table;
|
||||
mod stats;
|
||||
mod ip_utils;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -42,7 +42,7 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
|
||||
let host = Arc::new(Host::new(config));
|
||||
let stats = host.stats().clone();
|
||||
let host_info = host.client_version();
|
||||
info!("Host ID={:?}", host.client_id());
|
||||
info!("Node URL: {}", host.client_url());
|
||||
try!(io_service.register_handler(host));
|
||||
Ok(NetworkService {
|
||||
io_service: io_service,
|
||||
|
Loading…
Reference in New Issue
Block a user