Add UPnP support for Lighthouse (#1587)

Adding UPnP support will help grow the DHT by allowing NAT traversal for peers with UPnP supported routers.

## Issue Addressed

#927 

## Proposed Changes

Using IGD library: https://docs.rs/igd/0.10.0/igd/

Adding the  the libp2p tcp port and discovery udp port. If this fails it simply logs the attempt and moves on

## Additional Info



Co-authored-by: Age Manning <Age@AgeManning.com>
This commit is contained in:
Sean
2020-10-02 08:47:00 +00:00
parent 2cc20101d4
commit 94b17ce02b
29 changed files with 342 additions and 33 deletions

View File

@@ -67,6 +67,9 @@ pub struct Config {
/// Disables the discovery protocol from starting.
pub disable_discovery: bool,
/// Attempt to construct external port mappings with UPnP.
pub upnp_enabled: bool,
/// List of extra topics to initially subscribe to as strings.
pub topics: Vec<GossipKind>,
}
@@ -136,6 +139,7 @@ impl Default for Config {
trusted_peers: vec![],
client_version: lighthouse_version::version_with_platform(),
disable_discovery: false,
upnp_enabled: true,
topics: Vec::new(),
}
}

View File

@@ -155,7 +155,7 @@ pub struct Discovery<TSpec: EthSpec> {
/// Indicates if the discovery service has been started. When the service is disabled, this is
/// always false.
started: bool,
pub started: bool,
/// Logger for the discovery behaviour.
log: slog::Logger,
@@ -358,6 +358,54 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
}
}
/// Updates the local ENR TCP port.
/// There currently isn't a case to update the address here. We opt for discovery to
/// automatically update the external address.
///
/// If the external address needs to be modified, use `update_enr_udp_socket.
pub fn update_enr_tcp_port(&mut self, port: u16) -> Result<(), String> {
self.discv5
.enr_insert("tcp", port.to_be_bytes().into())
.map_err(|e| format!("{:?}", e))?;
// replace the global version
*self.network_globals.local_enr.write() = self.discv5.local_enr();
// persist modified enr to disk
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
Ok(())
}
/// Updates the local ENR UDP socket.
///
/// This is with caution. Discovery should automatically maintain this. This should only be
/// used when automatic discovery is disabled.
pub fn update_enr_udp_socket(&mut self, socket_addr: SocketAddr) -> Result<(), String> {
match socket_addr {
SocketAddr::V4(socket) => {
self.discv5
.enr_insert("ip", socket.ip().octets().into())
.map_err(|e| format!("{:?}", e))?;
self.discv5
.enr_insert("udp", socket.port().to_be_bytes().into())
.map_err(|e| format!("{:?}", e))?;
}
SocketAddr::V6(socket) => {
self.discv5
.enr_insert("ip6", socket.ip().octets().into())
.map_err(|e| format!("{:?}", e))?;
self.discv5
.enr_insert("udp6", socket.port().to_be_bytes().into())
.map_err(|e| format!("{:?}", e))?;
}
}
// replace the global version
*self.network_globals.local_enr.write() = self.discv5.local_enr();
// persist modified enr to disk
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
Ok(())
}
/// Adds/Removes a subnet from the ENR Bitfield
pub fn update_enr_bitfield(&mut self, subnet_id: SubnetId, value: bool) -> Result<(), String> {
let id = *subnet_id as usize;
@@ -390,9 +438,9 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
.map_err(|_| String::from("Subnet ID out of bounds, could not set subnet ID"))?;
// insert the bitfield into the ENR record
let _ = self
.discv5
.enr_insert(BITFIELD_ENR_KEY, current_bitfield.as_ssz_bytes());
self.discv5
.enr_insert(BITFIELD_ENR_KEY, current_bitfield.as_ssz_bytes())
.map_err(|e| format!("{:?}", e))?;
// replace the global version
*self.network_globals.local_enr.write() = self.discv5.local_enr();