Add a node-specific ip echo service to remove dependency on ifconfig.co (#4137)
This commit is contained in:
parent
c8ed41167a
commit
7fe3c75c6b
|
@ -1056,11 +1056,6 @@ dependencies = [
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ipnetwork"
|
|
||||||
version = "0.12.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.7.11"
|
version = "0.7.11"
|
||||||
|
@ -1633,33 +1628,6 @@ name = "pkg-config"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pnet_base"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pnet_datalink"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"pnet_base 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"pnet_sys 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pnet_sys"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -2587,14 +2555,14 @@ dependencies = [
|
||||||
name = "solana-netutil"
|
name = "solana-netutil"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pnet_datalink 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-logger 0.15.0",
|
"solana-logger 0.15.0",
|
||||||
|
"tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3532,7 +3500,6 @@ dependencies = [
|
||||||
"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c"
|
"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c"
|
||||||
"checksum influx_db_client 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1af8df5705f0b30bcb504bafc9396d995a555c4d6bd6f9097729ad47b8a49a38"
|
"checksum influx_db_client 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1af8df5705f0b30bcb504bafc9396d995a555c4d6bd6f9097729ad47b8a49a38"
|
||||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||||
"checksum ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)" = "70783119ac90828aaba91eae39db32c6c1b8838deea3637e5238efa0130801ab"
|
|
||||||
"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
|
||||||
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
||||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||||
|
@ -3596,9 +3563,6 @@ dependencies = [
|
||||||
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
|
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
|
||||||
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
|
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
|
||||||
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||||
"checksum pnet_base 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "948dbdd36f46888ada1d497703e6cae53d227ab0e8871638aba492ad1e4a76dc"
|
|
||||||
"checksum pnet_datalink 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d3b3dd76a11ad99d92fef54b2489f76f4045ebd5251bd1af485d55a7e13db6"
|
|
||||||
"checksum pnet_sys 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "963b9109a05c3ac370abc3fda61bff20d03743c2947942173871b9cac2b9acb0"
|
|
||||||
"checksum predicates 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa984b7cd021a0bf5315bcce4c4ae61d2a535db2a8d288fc7578638690a7b7c3"
|
"checksum predicates 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa984b7cd021a0bf5315bcce4c4ae61d2a535db2a8d288fc7578638690a7b7c3"
|
||||||
"checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178"
|
"checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178"
|
||||||
"checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124"
|
"checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124"
|
||||||
|
|
|
@ -119,20 +119,20 @@ Then the following command will start a new validator node.
|
||||||
If this is a `solana-install`-installation:
|
If this is a `solana-install`-installation:
|
||||||
```bash
|
```bash
|
||||||
$ clear-fullnode-config.sh
|
$ clear-fullnode-config.sh
|
||||||
$ fullnode.sh --public-address --poll-for-new-genesis-block testnet.solana.com
|
$ fullnode.sh --poll-for-new-genesis-block testnet.solana.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, the `solana-install run` command can be used to run the validator
|
Alternatively, the `solana-install run` command can be used to run the validator
|
||||||
node while periodically checking for and applying software updates:
|
node while periodically checking for and applying software updates:
|
||||||
```bash
|
```bash
|
||||||
$ clear-fullnode-config.sh
|
$ clear-fullnode-config.sh
|
||||||
$ solana-install run fullnode.sh -- --public-address --poll-for-new-genesis-block testnet.solana.com
|
$ solana-install run fullnode.sh -- --poll-for-new-genesis-block testnet.solana.com
|
||||||
```
|
```
|
||||||
|
|
||||||
If you built from source:
|
If you built from source:
|
||||||
```bash
|
```bash
|
||||||
$ USE_INSTALL=1 ./multinode-demo/clear-fullnode-config.sh
|
$ USE_INSTALL=1 ./multinode-demo/clear-fullnode-config.sh
|
||||||
$ USE_INSTALL=1 ./multinode-demo/fullnode.sh --public-address --poll-for-new-genesis-block testnet.solana.com
|
$ USE_INSTALL=1 ./multinode-demo/fullnode.sh --poll-for-new-genesis-block testnet.solana.com
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Controlling local network port allocation
|
#### Controlling local network port allocation
|
||||||
|
|
12
ci/nits.sh
12
ci/nits.sh
|
@ -18,14 +18,14 @@ declare prints=(
|
||||||
# Parts of the tree that are expected to be print free
|
# Parts of the tree that are expected to be print free
|
||||||
declare print_free_tree=(
|
declare print_free_tree=(
|
||||||
'core/src'
|
'core/src'
|
||||||
'drone'
|
'drone/src'
|
||||||
'metrics'
|
'metrics/src'
|
||||||
'netutil'
|
'netutil/src'
|
||||||
'runtime'
|
'runtime/src'
|
||||||
'sdk'
|
'sdk/src'
|
||||||
)
|
)
|
||||||
|
|
||||||
if _ git grep "${prints[@]/#/-e }" -- "${print_free_tree[@]}"; then
|
if _ git grep --max-depth=0 "${prints[@]/#/-e }" -- "${print_free_tree[@]}"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::signature::{Signable, Signature};
|
use solana_sdk::signature::{Signable, Signature};
|
||||||
use solana_sdk::timing::timestamp;
|
use solana_sdk::timing::timestamp;
|
||||||
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
|
||||||
/// Structure representing a node on the network
|
/// Structure representing a node on the network
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
@ -56,7 +56,7 @@ impl Eq for ContactInfo {}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! socketaddr {
|
macro_rules! socketaddr {
|
||||||
($ip:expr, $port:expr) => {
|
($ip:expr, $port:expr) => {
|
||||||
std::net::SocketAddr::from((Ipv4Addr::from($ip), $port))
|
std::net::SocketAddr::from((std::net::Ipv4Addr::from($ip), $port))
|
||||||
};
|
};
|
||||||
($str:expr) => {{
|
($str:expr) => {{
|
||||||
let a: std::net::SocketAddr = $str.parse().unwrap();
|
let a: std::net::SocketAddr = $str.parse().unwrap();
|
||||||
|
|
|
@ -74,6 +74,7 @@ pub struct Fullnode {
|
||||||
poh_service: PohService,
|
poh_service: PohService,
|
||||||
tpu: Tpu,
|
tpu: Tpu,
|
||||||
tvu: Tvu,
|
tvu: Tvu,
|
||||||
|
ip_echo_server: solana_netutil::IpEchoServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fullnode {
|
impl Fullnode {
|
||||||
|
@ -159,6 +160,9 @@ impl Fullnode {
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ip_echo_server =
|
||||||
|
solana_netutil::ip_echo_server(node.sockets.gossip.local_addr().unwrap().port());
|
||||||
|
|
||||||
let subscriptions = Arc::new(RpcSubscriptions::default());
|
let subscriptions = Arc::new(RpcSubscriptions::default());
|
||||||
let rpc_pubsub_service = if node.info.rpc_pubsub.port() == 0 {
|
let rpc_pubsub_service = if node.info.rpc_pubsub.port() == 0 {
|
||||||
None
|
None
|
||||||
|
@ -270,6 +274,7 @@ impl Fullnode {
|
||||||
exit,
|
exit,
|
||||||
poh_service,
|
poh_service,
|
||||||
poh_recorder,
|
poh_recorder,
|
||||||
|
ip_echo_server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +334,7 @@ impl Service for Fullnode {
|
||||||
self.gossip_service.join()?;
|
self.gossip_service.join()?;
|
||||||
self.tpu.join()?;
|
self.tpu.join()?;
|
||||||
self.tvu.join()?;
|
self.tvu.join()?;
|
||||||
|
self.ip_echo_server.shutdown_now();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -618,7 +618,7 @@ mod tests {
|
||||||
use solana_sdk::system_transaction;
|
use solana_sdk::system_transaction;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::net::{Ipv4Addr, SocketAddr, UdpSocket};
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_packets_set_addr() {
|
fn test_packets_set_addr() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use solana::contact_info::ContactInfo;
|
||||||
use solana::fullnode::{Fullnode, FullnodeConfig};
|
use solana::fullnode::{Fullnode, FullnodeConfig};
|
||||||
use solana::local_vote_signer_service::LocalVoteSignerService;
|
use solana::local_vote_signer_service::LocalVoteSignerService;
|
||||||
use solana::service::Service;
|
use solana::service::Service;
|
||||||
|
use solana::socketaddr;
|
||||||
use solana_netutil::parse_port_range;
|
use solana_netutil::parse_port_range;
|
||||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -131,16 +132,10 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Comma separated persistent accounts location"),
|
.help("Comma separated persistent accounts location"),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
clap::Arg::with_name("public_address")
|
|
||||||
.long("public-address")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Advertise public machine address in gossip. By default the local machine address is advertised"),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::with_name("gossip_port")
|
clap::Arg::with_name("gossip_port")
|
||||||
.long("gossip-port")
|
.long("gossip-port")
|
||||||
.value_name("PORT")
|
.value_name("HOST:PORT")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Gossip port number for the node"),
|
.help("Gossip port number for the node"),
|
||||||
)
|
)
|
||||||
|
@ -195,19 +190,14 @@ fn main() {
|
||||||
let dynamic_port_range = parse_port_range(matches.value_of("dynamic_port_range").unwrap())
|
let dynamic_port_range = parse_port_range(matches.value_of("dynamic_port_range").unwrap())
|
||||||
.expect("invalid dynamic_port_range");
|
.expect("invalid dynamic_port_range");
|
||||||
|
|
||||||
let gossip_addr = {
|
let mut gossip_addr = solana_netutil::parse_port_or_addr(
|
||||||
let mut addr = solana_netutil::parse_port_or_addr(
|
|
||||||
matches.value_of("gossip_port"),
|
matches.value_of("gossip_port"),
|
||||||
|
socketaddr!(
|
||||||
|
[127, 0, 0, 1],
|
||||||
solana_netutil::find_available_port_in_range(dynamic_port_range)
|
solana_netutil::find_available_port_in_range(dynamic_port_range)
|
||||||
.expect("unable to allocate gossip_port"),
|
.expect("unable to find an available gossip port")
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if matches.is_present("public_address") {
|
|
||||||
addr.set_ip(solana_netutil::get_public_ip_addr().unwrap());
|
|
||||||
} else {
|
|
||||||
addr.set_ip(solana_netutil::get_ip_addr(false).unwrap());
|
|
||||||
}
|
|
||||||
addr
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(paths) = matches.value_of("accounts") {
|
if let Some(paths) = matches.value_of("accounts") {
|
||||||
fullnode_config.account_paths = Some(paths.to_string());
|
fullnode_config.account_paths = Some(paths.to_string());
|
||||||
|
@ -215,9 +205,11 @@ fn main() {
|
||||||
fullnode_config.account_paths = None;
|
fullnode_config.account_paths = None;
|
||||||
}
|
}
|
||||||
let cluster_entrypoint = matches.value_of("network").map(|network| {
|
let cluster_entrypoint = matches.value_of("network").map(|network| {
|
||||||
let gossip_addr =
|
let entrypoint_addr =
|
||||||
solana_netutil::parse_host_port(network).expect("failed to parse network address");
|
solana_netutil::parse_host_port(network).expect("failed to parse network address");
|
||||||
ContactInfo::new_gossip_entry_point(&gossip_addr)
|
gossip_addr.set_ip(solana_netutil::get_public_ip_addr(&entrypoint_addr).unwrap());
|
||||||
|
|
||||||
|
ContactInfo::new_gossip_entry_point(&entrypoint_addr)
|
||||||
});
|
});
|
||||||
let (_signer_service, _signer_addr) = if let Some(signer_addr) = matches.value_of("signer") {
|
let (_signer_service, _signer_addr) = if let Some(signer_addr) = matches.value_of("signer") {
|
||||||
(
|
(
|
||||||
|
|
|
@ -9,7 +9,6 @@ use solana::gossip_service::discover;
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
|
@ -42,12 +41,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
SubCommand::with_name("spy")
|
SubCommand::with_name("spy")
|
||||||
.about("Monitor the gossip network")
|
.about("Monitor the gossip network")
|
||||||
.setting(AppSettings::DisableVersion)
|
.setting(AppSettings::DisableVersion)
|
||||||
.arg(
|
|
||||||
clap::Arg::with_name("public_address")
|
|
||||||
.long("public-address")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Advertise public machine address in gossip. By default the local machine address is advertised"),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
clap::Arg::with_name("pull_only")
|
clap::Arg::with_name("pull_only")
|
||||||
.long("pull-only")
|
.long("pull-only")
|
||||||
|
@ -131,11 +124,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut addr = socketaddr_any!();
|
let mut addr = socketaddr_any!();
|
||||||
if matches.is_present("public_address") {
|
addr.set_ip(
|
||||||
addr.set_ip(solana_netutil::get_public_ip_addr().unwrap());
|
solana_netutil::get_public_ip_addr(&network_addr).unwrap_or_else(|err| {
|
||||||
} else {
|
eprintln!("failed to contact {}: {}", network_addr, err);
|
||||||
addr.set_ip(solana_netutil::get_ip_addr(false).unwrap());
|
exit(1)
|
||||||
}
|
}),
|
||||||
|
);
|
||||||
Some(addr)
|
Some(addr)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,17 +44,18 @@ bootstrap_leader_vote_id_path="$SOLANA_CONFIG_DIR"/bootstrap-leader-vote-id.json
|
||||||
bootstrap_leader_vote_id=$($solana_keygen pubkey "$bootstrap_leader_vote_id_path")
|
bootstrap_leader_vote_id=$($solana_keygen pubkey "$bootstrap_leader_vote_id_path")
|
||||||
|
|
||||||
trap 'kill "$pid" && wait "$pid"' INT TERM ERR
|
trap 'kill "$pid" && wait "$pid"' INT TERM ERR
|
||||||
$program \
|
|
||||||
--identity "$bootstrap_leader_id_path" \
|
default_fullnode_arg --identity "$bootstrap_leader_id_path"
|
||||||
--voting-keypair "$bootstrap_leader_vote_id_path" \
|
default_fullnode_arg --voting-keypair "$bootstrap_leader_vote_id_path"
|
||||||
--vote-account "$bootstrap_leader_vote_id" \
|
default_fullnode_arg --vote-account "$bootstrap_leader_vote_id"
|
||||||
--ledger "$SOLANA_CONFIG_DIR"/bootstrap-leader-ledger \
|
default_fullnode_arg --ledger "$SOLANA_CONFIG_DIR"/bootstrap-leader-ledger
|
||||||
--accounts "$SOLANA_CONFIG_DIR"/bootstrap-leader-accounts \
|
default_fullnode_arg --accounts "$SOLANA_CONFIG_DIR"/bootstrap-leader-accounts
|
||||||
--gossip-port 8001 \
|
default_fullnode_arg --rpc-port 8899
|
||||||
--rpc-port 8899 \
|
default_fullnode_arg --rpc-drone-address 127.0.0.1:9900
|
||||||
--rpc-drone-address 127.0.0.1:9900 \
|
default_fullnode_arg --gossip-port 8001
|
||||||
"${extra_fullnode_args[@]}" \
|
|
||||||
> >($bootstrap_leader_logger) 2>&1 &
|
echo "$PS4 $program ${extra_fullnode_args[*]}"
|
||||||
|
$program "${extra_fullnode_args[@]}" > >($bootstrap_leader_logger) 2>&1 &
|
||||||
pid=$!
|
pid=$!
|
||||||
oom_score_adj "$pid" 1000
|
oom_score_adj "$pid" 1000
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,6 @@ Start a full node
|
||||||
--label LABEL - Append the given label to the fullnode configuration files, useful when running
|
--label LABEL - Append the given label to the fullnode configuration files, useful when running
|
||||||
multiple fullnodes from the same filesystem location
|
multiple fullnodes from the same filesystem location
|
||||||
--stake LAMPORTS - Number of lamports to stake
|
--stake LAMPORTS - Number of lamports to stake
|
||||||
--public-address - advertise public machine address in gossip. By default the local machine address is advertised
|
|
||||||
--no-voting - start node without vote signer
|
--no-voting - start node without vote signer
|
||||||
--rpc-port port - custom RPC port for this node
|
--rpc-port port - custom RPC port for this node
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@ while [[ ${1:0:1} = - ]]; do
|
||||||
elif [[ $1 = --init-complete-file ]]; then
|
elif [[ $1 = --init-complete-file ]]; then
|
||||||
extra_fullnode_args+=("$1" "$2")
|
extra_fullnode_args+=("$1" "$2")
|
||||||
shift 2
|
shift 2
|
||||||
elif [[ $1 = --public-address ]]; then
|
|
||||||
extra_fullnode_args+=("$1")
|
|
||||||
shift
|
|
||||||
elif [[ $1 = --stake ]]; then
|
elif [[ $1 = --stake ]]; then
|
||||||
stake="$2"
|
stake="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
@ -64,3 +61,20 @@ done
|
||||||
if [[ -n $3 ]]; then
|
if [[ -n $3 ]]; then
|
||||||
fullnode_usage "$@"
|
fullnode_usage "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
default_fullnode_arg() {
|
||||||
|
declare name=$1
|
||||||
|
declare value=$2
|
||||||
|
|
||||||
|
for arg in "${extra_fullnode_args[@]}"; do
|
||||||
|
if [[ $arg = "$name" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n $value ]]; then
|
||||||
|
extra_fullnode_args+=("$name" "$value")
|
||||||
|
else
|
||||||
|
extra_fullnode_args+=("$name")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
|
@ -164,23 +164,21 @@ while true; do
|
||||||
if ((stake)); then
|
if ((stake)); then
|
||||||
setup_vote_account "${leader_address%:*}" "$fullnode_id_path" "$fullnode_vote_id_path" "$stake"
|
setup_vote_account "${leader_address%:*}" "$fullnode_id_path" "$fullnode_vote_id_path" "$stake"
|
||||||
fi
|
fi
|
||||||
|
set +x
|
||||||
|
|
||||||
$program \
|
default_fullnode_arg --identity "$fullnode_id_path"
|
||||||
--identity "$fullnode_id_path" \
|
default_fullnode_arg --voting-keypair "$fullnode_vote_id_path"
|
||||||
--voting-keypair "$fullnode_vote_id_path" \
|
default_fullnode_arg --vote-account "$fullnode_vote_id"
|
||||||
--vote-account "$fullnode_vote_id" \
|
default_fullnode_arg --network "$leader_address"
|
||||||
--network "$leader_address" \
|
default_fullnode_arg --ledger "$ledger_config_dir"
|
||||||
--ledger "$ledger_config_dir" \
|
default_fullnode_arg --accounts "$accounts_config_dir"
|
||||||
--accounts "$accounts_config_dir" \
|
default_fullnode_arg --rpc-drone-address "${leader_address%:*}:9900"
|
||||||
--rpc-drone-address "${leader_address%:*}:9900" \
|
echo "$PS4 $program ${extra_fullnode_args[*]}"
|
||||||
"${extra_fullnode_args[@]}" \
|
$program "${extra_fullnode_args[@]}" > >($fullnode_logger) 2>&1 &
|
||||||
> >($fullnode_logger) 2>&1 &
|
|
||||||
pid=$!
|
pid=$!
|
||||||
oom_score_adj "$pid" 1000
|
oom_score_adj "$pid" 1000
|
||||||
|
|
||||||
set +x
|
|
||||||
while true; do
|
while true; do
|
||||||
|
|
||||||
if ! kill -0 "$pid"; then
|
if ! kill -0 "$pid"; then
|
||||||
wait "$pid"
|
wait "$pid"
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -350,7 +350,7 @@ EOF
|
||||||
echo "Waiting for $name to finish booting..."
|
echo "Waiting for $name to finish booting..."
|
||||||
(
|
(
|
||||||
set -x +e
|
set -x +e
|
||||||
for i in $(seq 1 30); do
|
for i in $(seq 1 60); do
|
||||||
timeout --preserve-status --foreground 20s ssh "${sshOptions[@]}" "$publicIp" "ls -l /.instance-startup-complete"
|
timeout --preserve-status --foreground 20s ssh "${sshOptions[@]}" "$publicIp" "ls -l /.instance-startup-complete"
|
||||||
ret=$?
|
ret=$?
|
||||||
if [[ $ret -eq 0 ]]; then
|
if [[ $ret -eq 0 ]]; then
|
||||||
|
|
|
@ -290,7 +290,6 @@ startBootstrapLeader() {
|
||||||
"./solana/net/remote/remote-node.sh \
|
"./solana/net/remote/remote-node.sh \
|
||||||
$deployMethod \
|
$deployMethod \
|
||||||
bootstrap-leader \
|
bootstrap-leader \
|
||||||
$publicNetwork \
|
|
||||||
$entrypointIp \
|
$entrypointIp \
|
||||||
$((${#fullnodeIpList[@]} + ${#blockstreamerIpList[@]})) \
|
$((${#fullnodeIpList[@]} + ${#blockstreamerIpList[@]})) \
|
||||||
\"$RUST_LOG\" \
|
\"$RUST_LOG\" \
|
||||||
|
@ -319,7 +318,6 @@ startNode() {
|
||||||
"./solana/net/remote/remote-node.sh \
|
"./solana/net/remote/remote-node.sh \
|
||||||
$deployMethod \
|
$deployMethod \
|
||||||
$nodeType \
|
$nodeType \
|
||||||
$publicNetwork \
|
|
||||||
$entrypointIp \
|
$entrypointIp \
|
||||||
$((${#fullnodeIpList[@]} + ${#blockstreamerIpList[@]})) \
|
$((${#fullnodeIpList[@]} + ${#blockstreamerIpList[@]})) \
|
||||||
\"$RUST_LOG\" \
|
\"$RUST_LOG\" \
|
||||||
|
|
|
@ -6,13 +6,12 @@ cd "$(dirname "$0")"/../..
|
||||||
set -x
|
set -x
|
||||||
deployMethod="$1"
|
deployMethod="$1"
|
||||||
nodeType="$2"
|
nodeType="$2"
|
||||||
publicNetwork="$3"
|
entrypointIp="$3"
|
||||||
entrypointIp="$4"
|
numNodes="$4"
|
||||||
numNodes="$5"
|
RUST_LOG="$5"
|
||||||
RUST_LOG="$6"
|
skipSetup="$6"
|
||||||
skipSetup="$7"
|
leaderRotation="$7"
|
||||||
leaderRotation="$8"
|
failOnValidatorBootupFailure="$8"
|
||||||
failOnValidatorBootupFailure="$9"
|
|
||||||
set +x
|
set +x
|
||||||
export RUST_LOG
|
export RUST_LOG
|
||||||
|
|
||||||
|
@ -31,7 +30,6 @@ missing() {
|
||||||
|
|
||||||
[[ -n $deployMethod ]] || missing deployMethod
|
[[ -n $deployMethod ]] || missing deployMethod
|
||||||
[[ -n $nodeType ]] || missing nodeType
|
[[ -n $nodeType ]] || missing nodeType
|
||||||
[[ -n $publicNetwork ]] || missing publicNetwork
|
|
||||||
[[ -n $entrypointIp ]] || missing entrypointIp
|
[[ -n $entrypointIp ]] || missing entrypointIp
|
||||||
[[ -n $numNodes ]] || missing numNodes
|
[[ -n $numNodes ]] || missing numNodes
|
||||||
[[ -n $skipSetup ]] || missing skipSetup
|
[[ -n $skipSetup ]] || missing skipSetup
|
||||||
|
@ -84,11 +82,10 @@ local|tar)
|
||||||
fi
|
fi
|
||||||
./multinode-demo/drone.sh > drone.log 2>&1 &
|
./multinode-demo/drone.sh > drone.log 2>&1 &
|
||||||
|
|
||||||
args=()
|
args=(
|
||||||
if $publicNetwork; then
|
--enable-rpc-exit
|
||||||
args+=(--public-address)
|
--gossip-port "$entrypointIp":8001
|
||||||
fi
|
)
|
||||||
args+=(--enable-rpc-exit)
|
|
||||||
|
|
||||||
./multinode-demo/bootstrap-leader.sh "${args[@]}" > bootstrap-leader.log 2>&1 &
|
./multinode-demo/bootstrap-leader.sh "${args[@]}" > bootstrap-leader.log 2>&1 &
|
||||||
ln -sTf bootstrap-leader.log fullnode.log
|
ln -sTf bootstrap-leader.log fullnode.log
|
||||||
|
@ -102,9 +99,6 @@ local|tar)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
args=()
|
args=()
|
||||||
if $publicNetwork; then
|
|
||||||
args+=("--public-address")
|
|
||||||
fi
|
|
||||||
if [[ $nodeType = blockstreamer ]]; then
|
if [[ $nodeType = blockstreamer ]]; then
|
||||||
args+=(
|
args+=(
|
||||||
--blockstream /tmp/solana-blockstream.sock
|
--blockstream /tmp/solana-blockstream.sock
|
||||||
|
|
|
@ -9,16 +9,22 @@ homepage = "https://solana.com/"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bincode = "1.1.3"
|
||||||
|
clap = "2.33.0"
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
ipnetwork = "0.12.7"
|
|
||||||
nix = "0.12.0"
|
nix = "0.12.0"
|
||||||
pnet_datalink = "0.21.0"
|
|
||||||
rand = "0.6.1"
|
rand = "0.6.1"
|
||||||
reqwest = "0.9.0"
|
|
||||||
socket2 = "0.3.8"
|
socket2 = "0.3.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
solana-logger = { path = "../logger", version = "0.15.0" }
|
solana-logger = { path = "../logger", version = "0.15.0" }
|
||||||
|
tokio = "0.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "solana_netutil"
|
name = "solana_netutil"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "solana-ip-address"
|
||||||
|
path = "src/bin/ip_address.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "solana-ip-address-server"
|
||||||
|
path = "src/bin/ip_address_server.rs"
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
use clap::{crate_version, App, Arg};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
solana_logger::setup();
|
||||||
|
let matches = App::new("solana-ip-address")
|
||||||
|
.version(crate_version!())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("host_port")
|
||||||
|
.index(1)
|
||||||
|
.required(true)
|
||||||
|
.help("Host:port to connect to"),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
let host_port = matches.value_of("host_port").unwrap();
|
||||||
|
let addr = solana_netutil::parse_host_port(host_port)
|
||||||
|
.unwrap_or_else(|_| panic!("failed to parse {}", host_port));
|
||||||
|
|
||||||
|
match solana_netutil::get_public_ip_addr(&addr) {
|
||||||
|
Ok(ip) => println!("{}", ip),
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}: {}", addr, err);
|
||||||
|
std::process::exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
use clap::{crate_version, App, Arg};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
solana_logger::setup();
|
||||||
|
let matches = App::new("solana-ip-address-server")
|
||||||
|
.version(crate_version!())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("port")
|
||||||
|
.index(1)
|
||||||
|
.required(true)
|
||||||
|
.help("TCP port to bind to"),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
let port = matches.value_of("port").unwrap();
|
||||||
|
let port = port
|
||||||
|
.parse()
|
||||||
|
.unwrap_or_else(|_| panic!("Unable to parse {}", port));
|
||||||
|
let _runtime = solana_netutil::ip_echo_server(port);
|
||||||
|
loop {
|
||||||
|
std::thread::park();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
use log::*;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use tokio;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tokio::prelude::{Future, Stream};
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
pub type IpEchoServer = Runtime;
|
||||||
|
|
||||||
|
/// Starts a simple TCP server on the given port that echos the IP address of any peer that
|
||||||
|
/// connects. Used by |get_public_ip_addr|
|
||||||
|
pub fn ip_echo_server(port: u16) -> IpEchoServer {
|
||||||
|
let bind_addr = SocketAddr::from(([0, 0, 0, 0], port));
|
||||||
|
let tcp =
|
||||||
|
TcpListener::bind(&bind_addr).unwrap_or_else(|_| panic!("Unable to bind to {}", bind_addr));
|
||||||
|
info!("bound to {:?}", bind_addr);
|
||||||
|
|
||||||
|
let server = tcp
|
||||||
|
.incoming()
|
||||||
|
.map_err(|err| warn!("accept failed: {:?}", err))
|
||||||
|
.for_each(move |socket| {
|
||||||
|
let ip = socket
|
||||||
|
.peer_addr()
|
||||||
|
.and_then(|peer_addr| {
|
||||||
|
bincode::serialize(&peer_addr.ip()).map_err(|err| {
|
||||||
|
std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
format!("Failed to serialize: {:?}", err),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|_| vec![]);
|
||||||
|
|
||||||
|
let write_future = tokio::io::write_all(socket, ip)
|
||||||
|
.map_err(|err| warn!("write error: {:?}", err))
|
||||||
|
.map(|_| ());
|
||||||
|
|
||||||
|
tokio::spawn(write_future)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut rt = Runtime::new().expect("Failed to create Runtime");
|
||||||
|
rt.spawn(server);
|
||||||
|
rt
|
||||||
|
}
|
|
@ -1,14 +1,16 @@
|
||||||
//! The `netutil` module assists with networking
|
//! The `netutil` module assists with networking
|
||||||
use log::*;
|
|
||||||
use nix::sys::socket::setsockopt;
|
use nix::sys::socket::setsockopt;
|
||||||
use nix::sys::socket::sockopt::{ReuseAddr, ReusePort};
|
use nix::sys::socket::sockopt::{ReuseAddr, ReusePort};
|
||||||
use pnet_datalink as datalink;
|
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use reqwest;
|
|
||||||
use socket2::{Domain, SockAddr, Socket, Type};
|
use socket2::{Domain, SockAddr, Socket, Type};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, ToSocketAddrs, UdpSocket};
|
use std::io::Read;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
mod ip_echo_server;
|
||||||
|
pub use ip_echo_server::*;
|
||||||
|
|
||||||
/// A data type representing a public Udp socket
|
/// A data type representing a public Udp socket
|
||||||
pub struct UdpSocketPair {
|
pub struct UdpSocketPair {
|
||||||
|
@ -19,34 +21,43 @@ pub struct UdpSocketPair {
|
||||||
|
|
||||||
pub type PortRange = (u16, u16);
|
pub type PortRange = (u16, u16);
|
||||||
|
|
||||||
/// Tries to determine the public IP address of this machine
|
/// Determine the public IP address of this machine by asking an ip_echo_server at the given
|
||||||
pub fn get_public_ip_addr() -> Result<IpAddr, String> {
|
/// address
|
||||||
let body = reqwest::get("http://ifconfig.co/ip")
|
pub fn get_public_ip_addr(ip_echo_server_addr: &SocketAddr) -> Result<IpAddr, String> {
|
||||||
.map_err(|err| err.to_string())?
|
let mut data = Vec::new();
|
||||||
.text()
|
|
||||||
.map_err(|err| err.to_string())?;
|
|
||||||
|
|
||||||
match body.lines().next() {
|
let timeout = Duration::new(5, 0);
|
||||||
Some(ip) => Result::Ok(ip.parse().unwrap()),
|
TcpStream::connect_timeout(ip_echo_server_addr, timeout)
|
||||||
None => Result::Err("Empty response body".to_string()),
|
.and_then(|mut stream| {
|
||||||
}
|
stream
|
||||||
|
.set_read_timeout(Some(Duration::new(10, 0)))
|
||||||
|
.expect("set_read_timeout");
|
||||||
|
stream.read_to_end(&mut data)
|
||||||
|
})
|
||||||
|
.and_then(|_| {
|
||||||
|
bincode::deserialize(&data).map_err(|err| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("Failed to deserialize: {:?}", err),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map_err(|err| err.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_port_or_addr(optstr: Option<&str>, default_port: u16) -> SocketAddr {
|
pub fn parse_port_or_addr(optstr: Option<&str>, default_addr: SocketAddr) -> SocketAddr {
|
||||||
let daddr = SocketAddr::from(([0, 0, 0, 0], default_port));
|
|
||||||
|
|
||||||
if let Some(addrstr) = optstr {
|
if let Some(addrstr) = optstr {
|
||||||
if let Ok(port) = addrstr.parse() {
|
if let Ok(port) = addrstr.parse() {
|
||||||
let mut addr = daddr;
|
let mut addr = default_addr;
|
||||||
addr.set_port(port);
|
addr.set_port(port);
|
||||||
addr
|
addr
|
||||||
} else if let Ok(addr) = addrstr.parse() {
|
} else if let Ok(addr) = addrstr.parse() {
|
||||||
addr
|
addr
|
||||||
} else {
|
} else {
|
||||||
daddr
|
default_addr
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
daddr
|
default_addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,67 +106,6 @@ pub fn parse_host_port(host_port: &str) -> Result<SocketAddr, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_eth0ish_ip_addr(
|
|
||||||
ifaces: &mut Vec<datalink::NetworkInterface>,
|
|
||||||
enable_ipv6: bool,
|
|
||||||
) -> Option<IpAddr> {
|
|
||||||
// put eth0 and wifi0, etc. up front of our list of candidates
|
|
||||||
ifaces.sort_by(|a, b| {
|
|
||||||
a.name
|
|
||||||
.chars()
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.cmp(&b.name.chars().last().unwrap())
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut lo = None;
|
|
||||||
for iface in ifaces.clone() {
|
|
||||||
trace!("get_ip_addr considering iface {}", iface.name);
|
|
||||||
for p in iface.ips {
|
|
||||||
trace!(" ip {}", p);
|
|
||||||
if p.ip().is_multicast() {
|
|
||||||
trace!(" multicast");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
match p.ip() {
|
|
||||||
IpAddr::V4(addr) => {
|
|
||||||
if addr.is_link_local() {
|
|
||||||
trace!(" link local");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if p.ip().is_loopback() {
|
|
||||||
// Fall back to loopback if no better option exists
|
|
||||||
// (local development and test)
|
|
||||||
trace!(" loopback");
|
|
||||||
lo = Some(p.ip());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
trace!(" picked {}", p.ip());
|
|
||||||
return Some(p.ip());
|
|
||||||
}
|
|
||||||
IpAddr::V6(_addr) => {
|
|
||||||
// Select an ipv6 address if requested
|
|
||||||
if enable_ipv6 {
|
|
||||||
if p.ip().is_loopback() {
|
|
||||||
trace!(" loopback");
|
|
||||||
lo = Some(p.ip());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return Some(p.ip());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trace!(" picked {:?}", lo);
|
|
||||||
lo
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_ip_addr(enable_ipv6: bool) -> Option<IpAddr> {
|
|
||||||
let mut ifaces = datalink::interfaces();
|
|
||||||
find_eth0ish_ip_addr(&mut ifaces, enable_ipv6)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn udp_socket(reuseaddr: bool) -> io::Result<Socket> {
|
fn udp_socket(reuseaddr: bool) -> io::Result<Socket> {
|
||||||
let sock = Socket::new(Domain::ipv4(), Type::dgram(), None)?;
|
let sock = Socket::new(Domain::ipv4(), Type::dgram(), None)?;
|
||||||
let sock_fd = sock.as_raw_fd();
|
let sock_fd = sock.as_raw_fd();
|
||||||
|
@ -252,101 +202,16 @@ pub fn find_available_port_in_range(range: PortRange) -> io::Result<u16> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ipnetwork::IpNetwork;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_find_eth0ish_ip_addr() {
|
|
||||||
solana_logger::setup();
|
|
||||||
|
|
||||||
macro_rules! mock_interface {
|
|
||||||
($name:ident, $ip_mask:expr) => {
|
|
||||||
datalink::NetworkInterface {
|
|
||||||
name: stringify!($name).to_string(),
|
|
||||||
index: 0,
|
|
||||||
mac: None,
|
|
||||||
ips: vec![IpNetwork::V4($ip_mask.parse().unwrap())],
|
|
||||||
flags: 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// loopback bad when alternatives exist
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(
|
|
||||||
&mut vec![
|
|
||||||
mock_interface!(eth0, "192.168.137.1/8"),
|
|
||||||
mock_interface!(lo, "127.0.0.1/24")
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
Some(mock_interface!(eth0, "192.168.137.1/8").ips[0].ip())
|
|
||||||
);
|
|
||||||
// find loopback as a last resort
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(&mut vec![mock_interface!(lo, "127.0.0.1/24")], false),
|
|
||||||
Some(mock_interface!(lo, "127.0.0.1/24").ips[0].ip()),
|
|
||||||
);
|
|
||||||
// multicast bad
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(&mut vec![mock_interface!(eth0, "224.0.1.5/24")], false),
|
|
||||||
None
|
|
||||||
);
|
|
||||||
|
|
||||||
// finds "wifi0"
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(
|
|
||||||
&mut vec![
|
|
||||||
mock_interface!(eth0, "224.0.1.5/24"),
|
|
||||||
mock_interface!(eth2, "192.168.137.1/8"),
|
|
||||||
mock_interface!(eth3, "10.0.75.1/8"),
|
|
||||||
mock_interface!(eth4, "172.22.140.113/4"),
|
|
||||||
mock_interface!(lo, "127.0.0.1/24"),
|
|
||||||
mock_interface!(wifi0, "192.168.1.184/8"),
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
Some(mock_interface!(wifi0, "192.168.1.184/8").ips[0].ip())
|
|
||||||
);
|
|
||||||
// finds "wifi0" in the middle
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(
|
|
||||||
&mut vec![
|
|
||||||
mock_interface!(eth0, "224.0.1.5/24"),
|
|
||||||
mock_interface!(eth2, "192.168.137.1/8"),
|
|
||||||
mock_interface!(eth3, "10.0.75.1/8"),
|
|
||||||
mock_interface!(wifi0, "192.168.1.184/8"),
|
|
||||||
mock_interface!(eth4, "172.22.140.113/4"),
|
|
||||||
mock_interface!(lo, "127.0.0.1/24"),
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
Some(mock_interface!(wifi0, "192.168.1.184/8").ips[0].ip())
|
|
||||||
);
|
|
||||||
// picks "eth2", is lowest valid "eth"
|
|
||||||
assert_eq!(
|
|
||||||
find_eth0ish_ip_addr(
|
|
||||||
&mut vec![
|
|
||||||
mock_interface!(eth0, "224.0.1.5/24"),
|
|
||||||
mock_interface!(eth2, "192.168.137.1/8"),
|
|
||||||
mock_interface!(eth3, "10.0.75.1/8"),
|
|
||||||
mock_interface!(eth4, "172.22.140.113/4"),
|
|
||||||
mock_interface!(lo, "127.0.0.1/24"),
|
|
||||||
],
|
|
||||||
false
|
|
||||||
),
|
|
||||||
Some(mock_interface!(eth2, "192.168.137.1/8").ips[0].ip())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_port_or_addr() {
|
fn test_parse_port_or_addr() {
|
||||||
let p1 = parse_port_or_addr(Some("9000"), 1);
|
let p1 = parse_port_or_addr(Some("9000"), SocketAddr::from(([1, 2, 3, 4], 1)));
|
||||||
assert_eq!(p1.port(), 9000);
|
assert_eq!(p1.port(), 9000);
|
||||||
let p2 = parse_port_or_addr(Some("127.0.0.1:7000"), 1);
|
let p2 = parse_port_or_addr(Some("127.0.0.1:7000"), SocketAddr::from(([1, 2, 3, 4], 1)));
|
||||||
assert_eq!(p2.port(), 7000);
|
assert_eq!(p2.port(), 7000);
|
||||||
let p2 = parse_port_or_addr(Some("hi there"), 1);
|
let p2 = parse_port_or_addr(Some("hi there"), SocketAddr::from(([1, 2, 3, 4], 1)));
|
||||||
assert_eq!(p2.port(), 1);
|
assert_eq!(p2.port(), 1);
|
||||||
let p3 = parse_port_or_addr(None, 1);
|
let p3 = parse_port_or_addr(None, SocketAddr::from(([1, 2, 3, 4], 1)));
|
||||||
assert_eq!(p3.port(), 1);
|
assert_eq!(p3.port(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@ use solana::contact_info::ContactInfo;
|
||||||
use solana::replicator::Replicator;
|
use solana::replicator::Replicator;
|
||||||
use solana::socketaddr;
|
use solana::socketaddr;
|
||||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
|
|
||||||
let matches = App::new(crate_name!()).about(crate_description!())
|
let matches = App::new(crate_name!())
|
||||||
|
.about(crate_description!())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("identity")
|
Arg::with_name("identity")
|
||||||
|
@ -39,12 +39,6 @@ fn main() {
|
||||||
.required(true)
|
.required(true)
|
||||||
.help("use DIR as persistent ledger location"),
|
.help("use DIR as persistent ledger location"),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
clap::Arg::with_name("public_address")
|
|
||||||
.long("public-address")
|
|
||||||
.takes_value(false)
|
|
||||||
.help("Advertise public machine address in gossip. By default the local machine address is advertised"),
|
|
||||||
)
|
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let ledger_path = matches.value_of("ledger").unwrap();
|
let ledger_path = matches.value_of("ledger").unwrap();
|
||||||
|
@ -58,13 +52,16 @@ fn main() {
|
||||||
Keypair::new()
|
Keypair::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let network_addr = matches
|
||||||
|
.value_of("network")
|
||||||
|
.map(|network| {
|
||||||
|
solana_netutil::parse_host_port(network).expect("failed to parse network address")
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let gossip_addr = {
|
let gossip_addr = {
|
||||||
let mut addr = socketaddr!([127, 0, 0, 1], 8700);
|
let mut addr = socketaddr!([127, 0, 0, 1], 8700);
|
||||||
if matches.is_present("public_address") {
|
addr.set_ip(solana_netutil::get_public_ip_addr(&network_addr).unwrap());
|
||||||
addr.set_ip(solana_netutil::get_public_ip_addr().unwrap());
|
|
||||||
} else {
|
|
||||||
addr.set_ip(solana_netutil::get_ip_addr(false).unwrap());
|
|
||||||
}
|
|
||||||
addr
|
addr
|
||||||
};
|
};
|
||||||
let node =
|
let node =
|
||||||
|
@ -76,13 +73,6 @@ fn main() {
|
||||||
gossip_addr
|
gossip_addr
|
||||||
);
|
);
|
||||||
|
|
||||||
let network_addr = matches
|
|
||||||
.value_of("network")
|
|
||||||
.map(|network| {
|
|
||||||
solana_netutil::parse_host_port(network).expect("failed to parse network address")
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let leader_info = ContactInfo::new_gossip_entry_point(&network_addr);
|
let leader_info = ContactInfo::new_gossip_entry_point(&network_addr);
|
||||||
let storage_keypair = Arc::new(Keypair::new());
|
let storage_keypair = Arc::new(Keypair::new());
|
||||||
let mut replicator = Replicator::new(
|
let mut replicator = Replicator::new(
|
||||||
|
|
Loading…
Reference in New Issue