policy now has a map of peers instead of a flat list, makes it more efficient to do lookups

This commit is contained in:
Arvid Norberg 2007-10-02 19:11:04 +00:00
parent 18a87916e6
commit 3dcae188fb
5 changed files with 127 additions and 154 deletions

View File

@ -692,13 +692,13 @@ int main(int ac, char* av[])
handles_t handles; handles_t handles;
session ses; session ses;
// UPnP port mapping // UPnP port mapping
ses.start_upnp(); // ses.start_upnp();
// NAT-PMP port mapping // NAT-PMP port mapping
ses.start_natpmp(); // ses.start_natpmp();
// Local service discovery (finds peers on the local network) // Local service discovery (finds peers on the local network)
ses.start_lsd(); // ses.start_lsd();
ses.add_extension(&create_metadata_plugin); // ses.add_extension(&create_metadata_plugin);
ses.add_extension(&create_ut_pex_plugin); // ses.add_extension(&create_ut_pex_plugin);
ses.set_max_uploads(upload_slots_limit); ses.set_max_uploads(upload_slots_limit);
ses.set_max_half_open_connections(half_open_limit); ses.set_max_half_open_connections(half_open_limit);
@ -721,7 +721,7 @@ int main(int ac, char* av[])
ses.set_severity_level(alert::info); ses.set_severity_level(alert::info);
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
settings.use_dht_as_fallback = false; /* settings.use_dht_as_fallback = false;
boost::filesystem::ifstream dht_state_file(".dht_state" boost::filesystem::ifstream dht_state_file(".dht_state"
, std::ios_base::binary); , std::ios_base::binary);
@ -741,6 +741,7 @@ int main(int ac, char* av[])
, 6881)); , 6881));
ses.add_dht_router(std::make_pair(std::string("router.bitcomet.com") ses.add_dht_router(std::make_pair(std::string("router.bitcomet.com")
, 6881)); , 6881));
*/
#endif #endif
// look for ipfilter.dat // look for ipfilter.dat
@ -1154,11 +1155,12 @@ int main(int ac, char* av[])
} }
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
dht_state = ses.dht_state(); /* dht_state = ses.dht_state();
boost::filesystem::ofstream out(".dht_state" boost::filesystem::ofstream out(".dht_state"
, std::ios_base::binary); , std::ios_base::binary);
out.unsetf(std::ios_base::skipws); out.unsetf(std::ios_base::skipws);
bencode(std::ostream_iterator<char>(out), dht_state); bencode(std::ostream_iterator<char>(out), dht_state);
*/
#endif #endif
} }
catch (std::exception& e) catch (std::exception& e)

View File

@ -212,8 +212,8 @@ namespace libtorrent
int num_peers() const { return m_peers.size(); } int num_peers() const { return m_peers.size(); }
typedef std::list<peer>::iterator iterator; typedef std::multimap<address, peer>::iterator iterator;
typedef std::list<peer>::const_iterator const_iterator; typedef std::multimap<address, peer>::const_iterator const_iterator;
iterator begin_peer() { return m_peers.begin(); } iterator begin_peer() { return m_peers.begin(); }
iterator end_peer() { return m_peers.end(); } iterator end_peer() { return m_peers.end(); }
@ -237,7 +237,7 @@ namespace libtorrent
iterator find_disconnect_candidate(); iterator find_disconnect_candidate();
iterator find_connect_candidate(); iterator find_connect_candidate();
std::list<peer> m_peers; std::multimap<address, peer> m_peers;
torrent* m_torrent; torrent* m_torrent;

View File

@ -1580,13 +1580,13 @@ namespace libtorrent
: m_id(id), m_pc(pc) : m_id(id), m_pc(pc)
{ assert(pc); } { assert(pc); }
bool operator()(policy::peer const& p) const bool operator()(std::pair<const address, policy::peer> const& p) const
{ {
return p.connection != m_pc return p.second.connection != m_pc
&& p.connection && p.second.connection
&& p.connection->pid() == m_id && p.second.connection->pid() == m_id
&& !p.connection->pid().is_all_zeros() && !p.second.connection->pid().is_all_zeros()
&& p.ip.address() == m_pc->remote().address(); && p.second.ip.address() == m_pc->remote().address();
} }
peer_id const& m_id; peer_id const& m_id;
@ -2281,7 +2281,7 @@ namespace libtorrent
, match_peer_id(pid, this)); , match_peer_id(pid, this));
if (i != p.end_peer()) if (i != p.end_peer())
{ {
assert(i->connection->pid() == pid); assert(i->second.connection->pid() == pid);
// we found another connection with the same peer-id // we found another connection with the same peer-id
// which connection should be closed in order to be // which connection should be closed in order to be
// sure that the other end closes the same connection? // sure that the other end closes the same connection?
@ -2291,7 +2291,7 @@ namespace libtorrent
// if not, we should close the outgoing one. // if not, we should close the outgoing one.
if (pid < m_ses.get_peer_id() && is_local()) if (pid < m_ses.get_peer_id() && is_local())
{ {
i->connection->disconnect(); i->second.connection->disconnect();
} }
else else
{ {

View File

@ -138,26 +138,14 @@ namespace
return free_upload; return free_upload;
} }
struct match_peer_address
{
match_peer_address(address const& addr)
: m_addr(addr)
{}
bool operator()(policy::peer const& p) const
{ return p.ip.address() == m_addr; }
address const& m_addr;
};
struct match_peer_endpoint struct match_peer_endpoint
{ {
match_peer_endpoint(tcp::endpoint const& ep) match_peer_endpoint(tcp::endpoint const& ep)
: m_ep(ep) : m_ep(ep)
{} {}
bool operator()(policy::peer const& p) const bool operator()(std::pair<const address, policy::peer> const& p) const
{ return p.ip == m_ep; } { return p.second.ip == m_ep; }
tcp::endpoint const& m_ep; tcp::endpoint const& m_ep;
}; };
@ -168,8 +156,8 @@ namespace
: m_id(id_) : m_id(id_)
{} {}
bool operator()(policy::peer const& p) const bool operator()(std::pair<const address, policy::peer> const& p) const
{ return p.connection && p.connection->pid() == m_id; } { return p.second.connection && p.second.connection->pid() == m_id; }
peer_id const& m_id; peer_id const& m_id;
}; };
@ -180,11 +168,11 @@ namespace
: m_conn(c) : m_conn(c)
{} {}
bool operator()(policy::peer const& p) const bool operator()(std::pair<const address, policy::peer> const& p) const
{ {
return p.connection == &m_conn return p.second.connection == &m_conn
|| (p.ip == m_conn.remote() || (p.second.ip == m_conn.remote()
&& p.type == policy::peer::connectable); && p.second.type == policy::peer::connectable);
} }
peer_connection const& m_conn; peer_connection const& m_conn;
@ -362,35 +350,35 @@ namespace libtorrent
piece_picker* p = 0; piece_picker* p = 0;
if (m_torrent->has_picker()) if (m_torrent->has_picker())
p = &m_torrent->picker(); p = &m_torrent->picker();
for (std::list<peer>::iterator i = m_peers.begin() for (iterator i = m_peers.begin()
, end(m_peers.end()); i != end;) , end(m_peers.end()); i != end;)
{ {
if ((ses.m_ip_filter.access(i->ip.address()) & ip_filter::blocked) == 0) if ((ses.m_ip_filter.access(i->second.ip.address()) & ip_filter::blocked) == 0)
{ {
++i; ++i;
continue; continue;
} }
if (i->connection) if (i->second.connection)
{ {
i->connection->disconnect(); i->second.connection->disconnect();
if (ses.m_alerts.should_post(alert::info)) if (ses.m_alerts.should_post(alert::info))
{ {
ses.m_alerts.post_alert(peer_blocked_alert(i->ip.address() ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address()
, "disconnected blocked peer")); , "disconnected blocked peer"));
} }
assert(i->connection == 0 assert(i->second.connection == 0
|| i->connection->peer_info_struct() == 0); || i->second.connection->peer_info_struct() == 0);
} }
else else
{ {
if (ses.m_alerts.should_post(alert::info)) if (ses.m_alerts.should_post(alert::info))
{ {
ses.m_alerts.post_alert(peer_blocked_alert(i->ip.address() ses.m_alerts.post_alert(peer_blocked_alert(i->second.ip.address()
, "blocked peer removed from peer list")); , "blocked peer removed from peer list"));
} }
} }
if (p) p->clear_peer(&(*i)); if (p) p->clear_peer(&i->second);
m_peers.erase(i++); m_peers.erase(i++);
} }
} }
@ -489,7 +477,7 @@ namespace libtorrent
for (iterator i = m_peers.begin(); for (iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
peer_connection* c = i->connection; peer_connection* c = i->second.connection;
if (c == 0) continue; if (c == 0) continue;
if (c->is_disconnecting()) continue; if (c->is_disconnecting()) continue;
@ -497,13 +485,13 @@ namespace libtorrent
// isn't interesting // isn't interesting
if (disconnect_peer != m_peers.end() if (disconnect_peer != m_peers.end()
&& c->is_interesting() && c->is_interesting()
&& !disconnect_peer->connection->is_interesting()) && !disconnect_peer->second.connection->is_interesting())
continue; continue;
double transferred_amount double transferred_amount
= (double)c->statistics().total_payload_download(); = (double)c->statistics().total_payload_download();
time_duration connected_time = now - i->connected; time_duration connected_time = now - i->second.connected;
double connected_time_in_seconds = total_seconds(connected_time); double connected_time_in_seconds = total_seconds(connected_time);
@ -513,7 +501,7 @@ namespace libtorrent
// prefer to disconnect uninteresting peers, and secondly slow peers // prefer to disconnect uninteresting peers, and secondly slow peers
if (transfer_rate <= slowest_transfer_rate if (transfer_rate <= slowest_transfer_rate
|| (disconnect_peer != m_peers.end() || (disconnect_peer != m_peers.end()
&& disconnect_peer->connection->is_interesting() && disconnect_peer->second.connection->is_interesting()
&& !c->is_interesting())) && !c->is_interesting()))
{ {
slowest_transfer_rate = transfer_rate; slowest_transfer_rate = transfer_rate;
@ -540,21 +528,21 @@ namespace libtorrent
for (iterator i = m_peers.begin(); i != m_peers.end(); ++i) for (iterator i = m_peers.begin(); i != m_peers.end(); ++i)
{ {
if (i->connection) continue; if (i->second.connection) continue;
if (i->banned) continue; if (i->second.banned) continue;
if (i->type == peer::not_connectable) continue; if (i->second.type == peer::not_connectable) continue;
if (i->seed && finished) continue; if (i->second.seed && finished) continue;
if (i->failcount >= max_failcount) continue; if (i->second.failcount >= max_failcount) continue;
if (now - i->connected < seconds(i->failcount * min_reconnect_time)) if (now - i->second.connected < seconds(i->second.failcount * min_reconnect_time))
continue; continue;
if (ses.m_port_filter.access(i->ip.port()) & port_filter::blocked) if (ses.m_port_filter.access(i->second.ip.port()) & port_filter::blocked)
continue; continue;
assert(i->connected <= now); assert(i->second.connected <= now);
if (i->connected <= min_connect_time) if (i->second.connected <= min_connect_time)
{ {
min_connect_time = i->connected; min_connect_time = i->second.connected;
candidate = i; candidate = i;
} }
} }
@ -685,11 +673,11 @@ namespace libtorrent
for (iterator i = m_peers.begin(); i != m_peers.end();) for (iterator i = m_peers.begin(); i != m_peers.end();)
{ {
// this timeout has to be customizable! // this timeout has to be customizable!
if (i->connection == 0 if (i->second.connection == 0
&& i->connected != min_time() && i->second.connected != min_time()
&& now - i->connected > minutes(120)) && now - i->second.connected > minutes(120))
{ {
if (p) p->clear_peer(&(*i)); if (p) p->clear_peer(&i->second);
m_peers.erase(i++); m_peers.erase(i++);
} }
else else
@ -899,12 +887,12 @@ namespace libtorrent
for (const_iterator i = m_peers.begin(); for (const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
if (!i->connection if (!i->second.connection
|| i->connection->is_connecting() || i->second.connection->is_connecting()
|| i->connection->is_disconnecting() || i->second.connection->is_disconnecting()
|| !i->connection->is_peer_interested()) || !i->second.connection->is_peer_interested())
continue; continue;
if (i->connection->is_choked()) ++ret; if (i->second.connection->is_choked()) ++ret;
} }
return ret; return ret;
} }
@ -948,23 +936,20 @@ namespace libtorrent
} }
else else
{ {
i = std::find_if( i = m_peers.find(c.remote().address());
m_peers.begin()
, m_peers.end()
, match_peer_address(c.remote().address()));
} }
if (i != m_peers.end()) if (i != m_peers.end())
{ {
if (i->banned) if (i->second.banned)
throw protocol_error("ip address banned, closing"); throw protocol_error("ip address banned, closing");
if (i->connection != 0) if (i->second.connection != 0)
{ {
assert(i->connection != &c); assert(i->second.connection != &c);
// the new connection is a local (outgoing) connection // the new connection is a local (outgoing) connection
// or the current one is already connected // or the current one is already connected
if (!i->connection->is_connecting() || c.is_local()) if (!i->second.connection->is_connecting() || c.is_local())
{ {
throw protocol_error("duplicate connection, closing"); throw protocol_error("duplicate connection, closing");
} }
@ -975,10 +960,7 @@ namespace libtorrent
" is connecting and this connection is incoming. closing existing " " is connecting and this connection is incoming. closing existing "
"connection in favour of this one"); "connection in favour of this one");
#endif #endif
i->connection->disconnect(); i->second.connection->disconnect();
#ifndef NDEBUG
check_invariant();
#endif
} }
} }
} }
@ -989,23 +971,20 @@ namespace libtorrent
assert(c.remote() == c.get_socket()->remote_endpoint()); assert(c.remote() == c.get_socket()->remote_endpoint());
peer p(c.remote(), peer::not_connectable, 0); peer p(c.remote(), peer::not_connectable, 0);
m_peers.push_back(p); m_peers.insert(std::make_pair(c.remote().address(), p));
i = boost::prior(m_peers.end()); i = boost::prior(m_peers.end());
#ifndef NDEBUG
check_invariant();
#endif
} }
assert(m_torrent->connection_for(c.remote()) == &c); assert(m_torrent->connection_for(c.remote()) == &c);
c.set_peer_info(&*i); c.set_peer_info(&i->second);
assert(i->connection == 0); assert(i->second.connection == 0);
c.add_stat(i->prev_amount_download, i->prev_amount_upload); c.add_stat(i->second.prev_amount_download, i->second.prev_amount_upload);
i->prev_amount_download = 0; i->second.prev_amount_download = 0;
i->prev_amount_upload = 0; i->second.prev_amount_upload = 0;
i->connection = &c; i->second.connection = &c;
assert(i->connection); assert(i->second.connection);
i->connected = time_now(); i->second.connected = time_now();
// m_last_optimistic_disconnect = time_now(); // m_last_optimistic_disconnect = time_now();
} }
@ -1038,23 +1017,15 @@ namespace libtorrent
if (m_torrent->settings().allow_multiple_connections_per_ip) if (m_torrent->settings().allow_multiple_connections_per_ip)
{ {
i = std::find_if( std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
m_peers.begin() i = std::find_if(range.first, range.second, match_peer_endpoint(remote));
, m_peers.end()
, match_peer_endpoint(remote));
if (i == m_peers.end()) if (i == range.second)
i = std::find_if( i = std::find_if(m_peers.begin(), m_peers.end(), match_peer_id(pid));
m_peers.begin()
, m_peers.end()
, match_peer_id(pid));
} }
else else
{ {
i = std::find_if( i = m_peers.find(remote.address());
m_peers.begin()
, m_peers.end()
, match_peer_address(remote.address()));
} }
if (i == m_peers.end()) if (i == m_peers.end())
@ -1073,14 +1044,14 @@ namespace libtorrent
// we don't have any info about this peer. // we don't have any info about this peer.
// add a new entry // add a new entry
peer p(remote, peer::connectable, src); peer p(remote, peer::connectable, src);
m_peers.push_back(p); m_peers.insert(std::make_pair(remote.address(), p));
// the iterator is invalid // the iterator is invalid
// because of the push_back() // because of the push_back()
i = boost::prior(m_peers.end()); i = boost::prior(m_peers.end());
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
if (flags & 0x01) p.pe_support = true; if (flags & 0x01) p.pe_support = true;
#endif #endif
if (flags & 0x02) i->seed = true; if (flags & 0x02) i->second.seed = true;
// try to send a DHT ping to this peer // try to send a DHT ping to this peer
// as well, to figure out if it supports // as well, to figure out if it supports
@ -1093,27 +1064,27 @@ namespace libtorrent
} }
else else
{ {
i->type = peer::connectable; i->second.type = peer::connectable;
// in case we got the ip from a remote connection, port is // in case we got the ip from a remote connection, port is
// not known, so save it. Client may also have changed port // not known, so save it. Client may also have changed port
// for some reason. // for some reason.
i->ip = remote; i->second.ip = remote;
i->source |= src; i->second.source |= src;
// if this peer has failed before, decrease the // if this peer has failed before, decrease the
// counter to allow it another try, since somebody // counter to allow it another try, since somebody
// else is appearantly able to connect to it // else is appearantly able to connect to it
// if it comes from the DHT it might be stale though // if it comes from the DHT it might be stale though
if (i->failcount > 0 && src != peer_info::dht) if (i->second.failcount > 0 && src != peer_info::dht)
--i->failcount; --i->second.failcount;
// if we're connected to this peer // if we're connected to this peer
// we already know if it's a seed or not // we already know if it's a seed or not
// so we don't have to trust this source // so we don't have to trust this source
if ((flags & 0x02) && !i->connection) i->seed = true; if ((flags & 0x02) && !i->second.connection) i->second.seed = true;
if (i->connection) if (i->second.connection)
{ {
// this means we're already connected // this means we're already connected
// to this peer. don't connect to // to this peer. don't connect to
@ -1122,10 +1093,10 @@ namespace libtorrent
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
m_torrent->debug_log("already connected to peer: " + remote.address().to_string() + ":" m_torrent->debug_log("already connected to peer: " + remote.address().to_string() + ":"
+ boost::lexical_cast<std::string>(remote.port()) + " " + boost::lexical_cast<std::string>(remote.port()) + " "
+ boost::lexical_cast<std::string>(i->connection->pid())); + boost::lexical_cast<std::string>(i->second.connection->pid()));
#endif #endif
assert(i->connection->associated_torrent().lock().get() == m_torrent); assert(i->second.connection->associated_torrent().lock().get() == m_torrent);
return; return;
} }
} }
@ -1159,12 +1130,12 @@ namespace libtorrent
for (iterator i = m_peers.begin(); for (iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
if (i->connection == 0) continue; if (i->second.connection == 0) continue;
// if we're not interested, we will not become interested // if we're not interested, we will not become interested
if (!i->connection->is_interesting()) continue; if (!i->second.connection->is_interesting()) continue;
if (!i->connection->has_piece(index)) continue; if (!i->second.connection->has_piece(index)) continue;
i->connection->update_interest(); i->second.connection->update_interest();
} }
} }
} }
@ -1187,8 +1158,8 @@ namespace libtorrent
// INVARIANT_CHECK; // INVARIANT_CHECK;
assert(std::find_if(m_peers.begin(), m_peers.end() assert(std::find_if(m_peers.begin(), m_peers.end()
, boost::bind<bool>(std::equal_to<peer_connection*>(), bind(&peer::connection, _1) , boost::bind<bool>(std::equal_to<peer_connection*>(), bind(&peer::connection
, &c)) != m_peers.end()); , bind(&iterator::value_type::second, _1)), &c)) != m_peers.end());
// if the peer is choked and we have upload slots left, // if the peer is choked and we have upload slots left,
// then unchoke it. Another condition that has to be met // then unchoke it. Another condition that has to be met
@ -1303,23 +1274,23 @@ namespace libtorrent
iterator p = find_connect_candidate(); iterator p = find_connect_candidate();
if (p == m_peers.end()) return false; if (p == m_peers.end()) return false;
assert(!p->banned); assert(!p->second.banned);
assert(!p->connection); assert(!p->second.connection);
assert(p->type == peer::connectable); assert(p->second.type == peer::connectable);
try try
{ {
p->connected = time_now(); p->second.connected = time_now();
p->connection = m_torrent->connect_to_peer(&*p); p->second.connection = m_torrent->connect_to_peer(&p->second);
assert(p->connection == m_torrent->connection_for(p->ip)); assert(p->second.connection == m_torrent->connection_for(p->second.ip));
if (p->connection == 0) if (p->second.connection == 0)
{ {
++p->failcount; ++p->second.failcount;
return false; return false;
} }
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload); p->second.connection->add_stat(p->second.prev_amount_download, p->second.prev_amount_upload);
p->prev_amount_download = 0; p->second.prev_amount_download = 0;
p->prev_amount_upload = 0; p->second.prev_amount_upload = 0;
return true; return true;
} }
catch (std::exception& e) catch (std::exception& e)
@ -1329,7 +1300,7 @@ namespace libtorrent
<< e.what() << "'\n"; << e.what() << "'\n";
#endif #endif
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
++p->failcount; ++p->second.failcount;
return false; return false;
} }
} }
@ -1340,10 +1311,10 @@ namespace libtorrent
if (p == m_peers.end()) if (p == m_peers.end())
return false; return false;
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*p->connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n"; (*p->second.connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n";
#endif #endif
p->connection->disconnect(); p->second.connection->disconnect();
return true; return true;
} }
@ -1425,21 +1396,23 @@ namespace libtorrent
int total_connections = 0; int total_connections = 0;
int nonempty_connections = 0; int nonempty_connections = 0;
std::set<address> unique_test; std::set<tcp::endpoint> unique_test;
// std::set<tcp::endpoint> unique_test2;
for (const_iterator i = m_peers.begin(); for (const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
peer const& p = *i; peer const& p = i->second;
// if (!m_torrent->settings().allow_multiple_connections_per_ip) if (!m_torrent->settings().allow_multiple_connections_per_ip)
// assert(unique_test.find(p.ip.address()) == unique_test.end()); {
// assert(unique_test2.find(p.ip) == unique_test2.end()); assert(m_peers.count(p.ip.address()) == 1);
// unique_test.insert(p.ip.address()); }
// unique_test2.insert(p.ip); else
{
assert(unique_test.count(p.ip) == 0);
unique_test.insert(p.ip);
}
++total_connections; ++total_connections;
if (!p.connection) if (!p.connection)
{ {
// assert(m_torrent->connection_for(p.ip) == 0);
continue; continue;
} }
if (!m_torrent->settings().allow_multiple_connections_per_ip) if (!m_torrent->settings().allow_multiple_connections_per_ip)
@ -1493,10 +1466,8 @@ namespace libtorrent
{ {
policy::peer* p = static_cast<policy::peer*>(*i); policy::peer* p = static_cast<policy::peer*>(*i);
if (p == 0) continue; if (p == 0) continue;
std::list<peer>::const_iterator k = m_peers.begin(); assert(std::find_if(m_peers.begin(), m_peers.end()
for (; k != m_peers.end(); ++k) , match_peer_connection(*p->connection)) != m_peers.end());
if (&(*k) == p) break;
assert(k != m_peers.end());
} }
} }

View File

@ -752,10 +752,10 @@ namespace libtorrent
// so, if the peer is not connectable (i.e. we // so, if the peer is not connectable (i.e. we
// don't know its listen port) or if it has // don't know its listen port) or if it has
// been banned, don't save it. // been banned, don't save it.
if (i->type == policy::peer::not_connectable if (i->second.type == policy::peer::not_connectable
|| i->banned) continue; || i->second.banned) continue;
tcp::endpoint ip = i->ip; tcp::endpoint ip = i->second.ip;
entry peer(entry::dictionary_t); entry peer(entry::dictionary_t);
peer["ip"] = ip.address().to_string(); peer["ip"] = ip.address().to_string();
peer["port"] = ip.port(); peer["port"] = ip.port();