Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
Update ENR at program start in case new public address is found
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed May 15, 2019
1 parent b4b70a9 commit 351a38d
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 18 deletions.
44 changes: 31 additions & 13 deletions libp2p/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ Host::Host(
m_tcp4Acceptor(m_ioService),
m_runTimer(m_ioService),
m_alias{_secretAndENR.first},
m_enr{_secretAndENR.second},
m_restoredENR{_secretAndENR.second},
m_lastPing(chrono::steady_clock::time_point::min()),
m_capabilityHost(createCapabilityHost(*this)),
m_lastPeerLogMessage(chrono::steady_clock::time_point::min())
{
cnetnote << "Id: " << id();
cnetnote << "ENR: " << m_enr;
LOG(m_infoLogger) << "Id: " << id();
LOG(m_infoLogger) << "ENR: " << m_restoredENR;
}

Host::Host(string const& _clientVersion, NetworkConfig const& _n, bytesConstRef _restoreNetwork)
Expand Down Expand Up @@ -433,10 +433,10 @@ bool Host::isHandshaking(NodeID const& _id) const
return false;
}

void Host::determinePublic()
bi::tcp::endpoint Host::determinePublic() const
{
// set m_tcpPublic := listenIP (if public) > public > upnp > unspecified address.
// return listenIP (if public) > public > upnp > unspecified address.

auto ifAddresses = Network::getInterfaceAddresses();
auto laddr = m_netConfig.listenIPAddress.empty() ? bi::address() : bi::address::from_string(m_netConfig.listenIPAddress);
auto lset = !laddr.is_unspecified();
Expand Down Expand Up @@ -478,7 +478,24 @@ void Host::determinePublic()
else if (pset)
ep.address(paddr);

m_tcpPublic = ep;
return ep;
}

ENR Host::updateENR(
ENR const& _restoredENR, bi::tcp::endpoint const& _tcpPublic, uint16_t const& _listenPort)
{
IdentityV4Info const info = IdentitySchemeV4::info(m_restoredENR);

auto const address = _tcpPublic.address().is_unspecified() ? info.ip : _tcpPublic.address();

if (info.ip == address && info.tcpPort == _listenPort && info.udpPort == _listenPort)
return _restoredENR;

ENR const newENR = IdentitySchemeV4::updateENR(
_restoredENR, m_alias.secret(), address, _listenPort, _listenPort);
LOG(m_infoLogger) << "ENR updated: " << newENR;

return newENR;
}

void Host::runAcceptor()
Expand Down Expand Up @@ -825,10 +842,12 @@ void Host::startedWorking()
else
m_listenPort = m_netConfig.listenPort;

determinePublic();
m_tcpPublic = determinePublic();
ENR const enr = updateENR(m_restoredENR, m_tcpPublic, listenPort());

auto nodeTable = make_shared<NodeTable>(m_ioService, m_alias,
NodeIPEndpoint(bi::address::from_string(listenAddress()), listenPort(), listenPort()),
m_enr, m_netConfig.discovery, m_netConfig.allowLocalDiscovery);
NodeIPEndpoint(bi::address::from_string(listenAddress()), listenPort(), listenPort()), enr,
m_netConfig.discovery, m_netConfig.allowLocalDiscovery);

// Don't set an event handler if we don't have capabilities, because no capabilities
// means there's no host state to update in response to node table events
Expand Down Expand Up @@ -968,7 +987,7 @@ bytes Host::saveNetwork() const

ret.appendList(2);
ret << m_alias.secret().ref();
m_enr.streamRLP(ret);
enr().streamRLP(ret);

ret.appendList(count);
if (!!count)
Expand Down Expand Up @@ -1062,11 +1081,10 @@ std::pair<Secret, ENR> Host::restoreENR(bytesConstRef _b, NetworkConfig const& _
secret = KeyPair::create().secret();
}

// TODO(gumb0): update ENR in case new address given in config
// https://github.com/ethereum/aleth/issues/5551
auto const address = _netConfig.publicIPAddress.empty() ?
bi::address{} :
bi::address::from_string(_netConfig.publicIPAddress);

return make_pair(secret,
IdentitySchemeV4::createENR(secret, address, _netConfig.listenPort, _netConfig.listenPort));
}
Expand Down
16 changes: 12 additions & 4 deletions libp2p/Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,11 @@ class Host: public Worker
p2p::NodeInfo nodeInfo() const { return NodeInfo(id(), (networkConfig().publicIPAddress.empty() ? m_tcpPublic.address().to_string() : networkConfig().publicIPAddress), m_tcpPublic.port(), m_clientVersion); }

/// Get Ethereum Node Record of the host
ENR enr() const { return m_enr; }
ENR enr() const
{
Guard l(x_nodeTable);
return m_nodeTable ? m_nodeTable->hostENR() : m_restoredENR;
}

/// Apply function to each session
void forEachPeer(
Expand Down Expand Up @@ -262,8 +266,11 @@ class Host: public Worker

bool isHandshaking(NodeID const& _id) const;

/// Determines and sets m_tcpPublic to publicly advertised address.
void determinePublic();
/// Determines publicly advertised address.
bi::tcp::endpoint determinePublic() const;

ENR updateENR(
ENR const& _restoredENR, bi::tcp::endpoint const& _tcpPublic, uint16_t const& _listenPort);

void connect(std::shared_ptr<Peer> const& _p);

Expand Down Expand Up @@ -343,7 +350,8 @@ class Host: public Worker
bi::tcp::endpoint m_tcpPublic; ///< Our public listening endpoint.
/// Alias for network communication.
KeyPair m_alias;
ENR m_enr;
/// Host's Ethereum Node Record restored from network.rlp
ENR m_restoredENR;
std::shared_ptr<NodeTable> m_nodeTable; ///< Node table (uses kademlia-like discovery).
mutable std::mutex x_nodeTable;
std::shared_ptr<NodeTable> nodeTable() const { Guard l(x_nodeTable); return m_nodeTable; }
Expand Down
1 change: 1 addition & 0 deletions libp2p/NodeTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ NodeTable::NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint
m_hostNodeIDHash{sha3(m_hostNodeID)},
m_hostNodeEndpoint{_endpoint},
m_hostENR{_enr},
m_hostENRInfo{IdentitySchemeV4::info(m_hostENR)},
m_secret{_alias.secret()},
m_socket{make_shared<NodeSocket>(
_io, static_cast<UDPSocketEvents&>(*this), (bi::udp::endpoint)m_hostNodeEndpoint)},
Expand Down
10 changes: 9 additions & 1 deletion libp2p/NodeTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ class NodeTable : UDPSocketEvents
/// Returns the Node to the corresponding node id or the empty Node if that id is not found.
Node node(NodeID const& _id);

ENR hostENR() const
{
Guard l(m_hostENRMutex);
return m_hostENR;
}

// protected only for derived classes in tests
protected:
/**
Expand Down Expand Up @@ -330,7 +336,9 @@ class NodeTable : UDPSocketEvents
NodeID const m_hostNodeID;
h256 const m_hostNodeIDHash;
NodeIPEndpoint m_hostNodeEndpoint;
ENR const m_hostENR;
ENR m_hostENR;
mutable Mutex m_hostENRMutex;
IdentityV4Info m_hostENRInfo;
Secret m_secret; ///< This nodes secret key.

mutable Mutex x_nodes; ///< LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const.
Expand Down

0 comments on commit 351a38d

Please sign in to comment.