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

Discovery protocol updates #1706

Merged
merged 35 commits into from
May 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e9dfa86
compiles (v4 endpoint changes)
subtly Apr 21, 2015
0850c7a
update tests (v4 endpoint)
subtly Apr 21, 2015
c70f21a
update net tests (v4 endpoint)
subtly Apr 21, 2015
d76dfef
update peer host test. support unspecified ip.
subtly Apr 21, 2015
c71d431
more test updates (v4 endpoints. #1557, #1558)
subtly Apr 21, 2015
862452a
Merge branch 'develop' into discovery
subtly Apr 23, 2015
50f5c96
handle new endpoint properties for ping
subtly Apr 23, 2015
eb2ca75
Merge branch 'develop' into discovery
subtly Apr 23, 2015
b3ba7d3
Merge branch 'develop' into discovery
subtly Apr 23, 2015
b3f4e77
Minor semantic updates. Support unspecified address for NodeIPEndpoint.
subtly Apr 23, 2015
e606ef9
check node discovery timestamps.
subtly Apr 24, 2015
9c541f9
simple endpoint update
subtly Apr 24, 2015
6dd5b57
Merge branch 'develop' into discovery
subtly Apr 24, 2015
12fbcc8
cleanup
subtly Apr 24, 2015
eb946bb
cleanup
subtly Apr 24, 2015
00cbab8
fix for insensitive windows compiler which reserves 'inline'. default…
subtly Apr 24, 2015
52213f2
encapsulate IP endpoint address as byte string
subtly Apr 27, 2015
235ee3c
Merge branch 'develop' into discovery
subtly Apr 27, 2015
8759657
Merge branch 'develop' into discovery
subtly Apr 27, 2015
52a219c
revert code from timestamps back to cache timers
subtly Apr 28, 2015
30acd13
Windows keyword error for _inline.
subtly Apr 28, 2015
41ded89
Merge branch 'develop' into discovery
subtly Apr 28, 2015
fdefc0e
Merge branch 'develop' into discovery
subtly Apr 29, 2015
c84d5f3
update pong encoding
subtly Apr 30, 2015
f176a1c
add missing const
subtly Apr 30, 2015
c5e6c7d
Merge branch 'develop' into discovery
subtly Apr 30, 2015
3ebaffa
revert assumption that node exists in nodetable when noteactivenode i…
subtly Apr 30, 2015
e541c23
Merge branch 'develop' into discovery
subtly May 3, 2015
c27ff03
Merge branch 'develop' into discovery
subtly May 6, 2015
9046e4f
Merge branch 'develop' into discovery
subtly May 6, 2015
d46bd2b
Missed in merge.
subtly May 6, 2015
03db500
Merge stash into discovery.
subtly May 6, 2015
4ac289b
fix restore network to support both old and new network file format
subtly May 6, 2015
5f1b711
Merge branch 'develop' into discovery
subtly May 6, 2015
d651501
Fix network-snapshot method when there's a lot of node activity (dere…
subtly May 7, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion libp2p/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ using namespace std;
using namespace dev;
using namespace dev::p2p;

const unsigned dev::p2p::c_protocolVersion = 3;
const unsigned dev::p2p::c_protocolVersion = 4;
const unsigned dev::p2p::c_defaultIPPort = 30303;
static_assert(dev::p2p::c_protocolVersion == 4, "Replace v3 compatbility with v4 compatibility before updating network version.");

const dev::p2p::NodeIPEndpoint dev::p2p::UnspecifiedNodeIPEndpoint = NodeIPEndpoint(bi::address(), 0, 0);
const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeId(), UnspecifiedNodeIPEndpoint);
Expand Down Expand Up @@ -144,6 +145,31 @@ std::string p2p::reasonOf(DisconnectReason _r)
}
}

void NodeIPEndpoint::streamRLP(RLPStream& _s, RLPAppend _append) const
{
if (_append == StreamList)
_s.appendList(3);
if (address.is_v4())
_s << bytesConstRef(&address.to_v4().to_bytes()[0], 4);
else if (address.is_v6())
_s << bytesConstRef(&address.to_v6().to_bytes()[0], 16);
else
_s << bytes();
_s << udpPort << tcpPort;
}

void NodeIPEndpoint::interpretRLP(RLP const& _r)
{
if (_r[0].size() == 4)
address = bi::address_v4(*(bi::address_v4::bytes_type*)_r[0].toBytes().data());
else if (_r[0].size() == 16)
address = bi::address_v6(*(bi::address_v6::bytes_type*)_r[0].toBytes().data());
else
address = bi::address();
udpPort = _r[1].toInt<uint16_t>();
tcpPort = _r[2].toInt<uint16_t>();
}

namespace dev {

std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep)
Expand Down
13 changes: 12 additions & 1 deletion libp2p/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <libdevcrypto/Common.h>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/RLP.h>
namespace ba = boost::asio;
namespace bi = boost::asio::ip;

Expand Down Expand Up @@ -162,10 +163,17 @@ using PeerSessionInfos = std::vector<PeerSessionInfo>;
*/
struct NodeIPEndpoint
{
enum RLPAppend
{
StreamList,
StreamInline
};

/// Setting true causes isAllowed to return true for all addresses. (Used by test fixtures)
static bool test_allowLocal;

NodeIPEndpoint(bi::address _addr, uint16_t _udp, uint16_t _tcp): address(_addr), udpPort(_udp), tcpPort(_tcp) {}
NodeIPEndpoint(RLP const& _r) { interpretRLP(_r); }

bi::address address;
uint16_t udpPort;
Expand All @@ -177,11 +185,14 @@ struct NodeIPEndpoint
operator bool() const { return !address.is_unspecified() && udpPort > 0 && tcpPort > 0; }

bool isAllowed() const { return NodeIPEndpoint::test_allowLocal ? !address.is_unspecified() : isPublicAddress(address); }

void streamRLP(RLPStream& _s, RLPAppend _append = StreamList) const;
void interpretRLP(RLP const& _r);
};

struct Node
{
Node(Public _pubk, NodeIPEndpoint _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {}
Node(Public _pubk, NodeIPEndpoint const& _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {}

virtual NodeId const& address() const { return id; }
virtual Public const& publicKey() const { return id; }
Expand Down
101 changes: 65 additions & 36 deletions libp2p/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io

// create session so disconnects are managed
auto ps = make_shared<Session>(this, _io, p, PeerSessionInfo({_id, clientVersion, _endpoint.address().to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet<CapDesc>(), 0, map<string, string>()}));
if (protocolVersion < dev::p2p::c_protocolVersion)
if (protocolVersion < dev::p2p::c_protocolVersion - 1)
{
ps->disconnect(IncompatibleProtocol);
return;
Expand Down Expand Up @@ -696,15 +696,16 @@ bytes Host::saveNetwork() const
int count = 0;
for (auto const& p: peers)
{
// Only save peers which have connected within 2 days, with properly-advertised port and public IP address
// todo: e2e ipv6 support
// todo: ipv6
if (!p.endpoint.address.is_v4())
continue;

if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && p.endpoint.tcpPort > 0 && p.id != id() && (p.required || p.endpoint.isAllowed()))
// Only save peers which have connected within 2 days, with properly-advertised port and public IP address
if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && !!p.endpoint && p.id != id() && (p.required || p.endpoint.isAllowed()))
{
network.appendList(10);
network << p.endpoint.address.to_v4().to_bytes() << p.endpoint.tcpPort << p.id << p.required
network.appendList(11);
p.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline);
network << p.id << p.required
<< chrono::duration_cast<chrono::seconds>(p.m_lastConnected.time_since_epoch()).count()
<< chrono::duration_cast<chrono::seconds>(p.m_lastAttempted.time_since_epoch()).count()
<< p.m_failedAttempts << (unsigned)p.m_lastDisconnect << p.m_score << p.m_rating;
Expand All @@ -718,12 +719,9 @@ bytes Host::saveNetwork() const
state.sort();
for (auto const& entry: state)
{
network.appendList(3);
if (entry.endpoint.address.is_v4())
network << entry.endpoint.address.to_v4().to_bytes();
else
network << entry.endpoint.address.to_v6().to_bytes();
network << entry.endpoint.tcpPort << entry.id;
network.appendList(4);
entry.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline);
network << entry.id;
count++;
}
}
Expand All @@ -739,6 +737,9 @@ bytes Host::saveNetwork() const

void Host::restoreNetwork(bytesConstRef _b)
{
if (!_b.size())
return;

// nodes can only be added if network is added
if (!isStarted())
BOOST_THROW_EXCEPTION(NetworkStartRequired());
Expand All @@ -748,38 +749,66 @@ void Host::restoreNetwork(bytesConstRef _b)

RecursiveGuard l(x_sessions);
RLP r(_b);
if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt<unsigned>() == dev::p2p::c_protocolVersion)
unsigned fileVersion = r[0].toInt<unsigned>();
if (r.itemCount() > 0 && r[0].isInt() && fileVersion >= dev::p2p::c_protocolVersion - 1)
{
// r[0] = version
// r[1] = key
// r[2] = nodes

for (auto i: r[2])
{
if (i[0].itemCount() != 4)
// todo: ipv6
if (i[0].itemCount() != 4 && i[0].size() != 4)
continue;

// todo: ipv6, bi::address_v6(i[0].toArray<byte, 16>()
Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>()));
if (i.itemCount() == 3 && n.endpoint.isAllowed())
m_nodeTable->addNode(n, NodeTable::NodeRelation::Known);
else if (i.itemCount() == 10)

if (i.itemCount() == 4 || i.itemCount() == 11)
{
n.required = i[3].toInt<bool>();
if (!n.endpoint.isAllowed() && !n.required)
continue;
shared_ptr<Peer> p = make_shared<Peer>(n);
p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt<unsigned>()));
p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>()));
p->m_failedAttempts = i[6].toInt<unsigned>();
p->m_lastDisconnect = (DisconnectReason)i[7].toInt<unsigned>();
p->m_score = (int)i[8].toInt<unsigned>();
p->m_rating = (int)i[9].toInt<unsigned>();
m_peers[p->id] = p;
if (p->required)
requirePeer(p->id, n.endpoint);
else
m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);
Node n((NodeId)i[3], NodeIPEndpoint(i));
if (i.itemCount() == 4 && n.endpoint.isAllowed())
m_nodeTable->addNode(n);
else if (i.itemCount() == 11)
{
n.required = i[4].toInt<bool>();
if (!n.endpoint.isAllowed() && !n.required)
continue;
shared_ptr<Peer> p = make_shared<Peer>(n);
p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>()));
p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[6].toInt<unsigned>()));
p->m_failedAttempts = i[7].toInt<unsigned>();
p->m_lastDisconnect = (DisconnectReason)i[8].toInt<unsigned>();
p->m_score = (int)i[9].toInt<unsigned>();
p->m_rating = (int)i[10].toInt<unsigned>();
m_peers[p->id] = p;
if (p->required)
requirePeer(p->id, n.endpoint);
else
m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);
}
}
else if (i.itemCount() == 3 || i.itemCount() == 10)
{
Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>()));
if (i.itemCount() == 3 && n.endpoint.isAllowed())
m_nodeTable->addNode(n);
else if (i.itemCount() == 10)
{
n.required = i[3].toInt<bool>();
if (!n.endpoint.isAllowed() && !n.required)
continue;
shared_ptr<Peer> p = make_shared<Peer>(n);
p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt<unsigned>()));
p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>()));
p->m_failedAttempts = i[6].toInt<unsigned>();
p->m_lastDisconnect = (DisconnectReason)i[7].toInt<unsigned>();
p->m_score = (int)i[8].toInt<unsigned>();
p->m_rating = (int)i[9].toInt<unsigned>();
m_peers[p->id] = p;
if (p->required)
requirePeer(p->id, n.endpoint);
else
m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);
}
}
}
}
Expand All @@ -788,7 +817,7 @@ void Host::restoreNetwork(bytesConstRef _b)
KeyPair Host::networkAlias(bytesConstRef _b)
{
RLP r(_b);
if (r.itemCount() == 3 && r[0].isInt() && r[0].toInt<unsigned>() == dev::p2p::c_protocolVersion)
if (r.itemCount() == 3 && r[0].isInt() && r[0].toInt<unsigned>() >= 3)
return move(KeyPair(move(Secret(r[1].toBytes()))));
else
return move(KeyPair::create());
Expand Down
Loading