send write token if peer is alraedy stored

This commit is contained in:
Steven Siloti 2016-09-20 10:45:13 -07:00
parent e2fefb074a
commit dad0000015
5 changed files with 27 additions and 12 deletions

View File

@ -125,7 +125,7 @@ namespace dht
// for this info_hash.
//
virtual bool get_peers(sha1_hash const& info_hash, udp protocol
, bool noseed, bool scrape
, bool noseed, bool scrape, address const& requester
, entry& peers) const = 0;
// This function is named announce_peer for consistency with the

View File

@ -220,7 +220,7 @@ private:
void send_single_refresh(udp::endpoint const& ep, int bucket
, node_id const& id = node_id());
bool lookup_peers(sha1_hash const& info_hash, entry& reply
, bool noseed, bool scrape) const;
, bool noseed, bool scrape, address const& requester) const;
libtorrent::dht_settings const& m_settings;

View File

@ -186,7 +186,7 @@ namespace
}
bool get_peers(sha1_hash const& info_hash, udp const protocol
, bool const noseed, bool const scrape
, bool const noseed, bool const scrape, address const& requester
, entry& peers) const override
{
auto const i = m_map.find(info_hash);
@ -256,7 +256,19 @@ namespace
++m;
}
}
return int(i->second.peers.size()) >= m_settings.max_peers;
if (int(i->second.peers.size()) < m_settings.max_peers)
return false;
// we're at the max peers stored for this torrent
// only send a write token if the requester is already in the set
// only check for a match on IP because the peer may be announcing
// a different port than the one it is using to send DHT messages
peer_entry requester_entry;
requester_entry.addr.address(requester);
auto requester_iter = i->second.peers.lower_bound(requester_entry);
return requester_iter == i->second.peers.end()
|| requester_iter->addr.address() != requester;
}
void announce_peer(sha1_hash const& info_hash

View File

@ -751,12 +751,12 @@ void node::status(session_status& s)
#endif
bool node::lookup_peers(sha1_hash const& info_hash, entry& reply
, bool noseed, bool scrape) const
, bool noseed, bool scrape, address const& requester) const
{
if (m_observer)
m_observer->get_peers(info_hash);
return m_storage.get_peers(info_hash, protocol(), noseed, scrape, reply);
return m_storage.get_peers(info_hash, protocol(), noseed, scrape, requester, reply);
}
entry write_nodes_entry(std::vector<node_entry> const& nodes)
@ -858,7 +858,10 @@ void node::incoming_request(msg const& m, entry& e)
bool scrape = false;
if (msg_keys[1] && msg_keys[1].int_value() != 0) noseed = true;
if (msg_keys[2] && msg_keys[2].int_value() != 0) scrape = true;
bool full = lookup_peers(info_hash, reply, noseed, scrape);
// If our storage is full we want to withhold the write token so that
// announces will spill over to our neighbors. This widens the
// perimeter of nodes which store peers for this torrent
bool full = lookup_peers(info_hash, reply, noseed, scrape, m.addr.address());
if (!full) reply["token"] = generate_token(m.addr, info_hash);
#ifndef TORRENT_DISABLE_LOGGING

View File

@ -100,7 +100,7 @@ TORRENT_TEST(announce_peer)
std::unique_ptr<dht_storage_interface> s(create_default_dht_storage(sett));
entry peers;
s->get_peers(n1, udp::v4(), false, false, peers);
s->get_peers(n1, udp::v4(), false, false, address(), peers);
TEST_CHECK(peers["n"].string().empty())
TEST_CHECK(peers["values"].list().empty());
@ -112,7 +112,7 @@ TORRENT_TEST(announce_peer)
s->announce_peer(n1, p1, "torrent_name", false);
peers = entry();
s->get_peers(n1, udp::v4(), false, false, peers);
s->get_peers(n1, udp::v4(), false, false, address(), peers);
TEST_EQUAL(peers["n"].string(), "torrent_name")
TEST_EQUAL(peers["values"].list().size(), 1)
@ -120,7 +120,7 @@ TORRENT_TEST(announce_peer)
s->announce_peer(n2, p3, "torrent_name1", false);
s->announce_peer(n3, p4, "torrent_name2", false);
peers = entry();
s->get_peers(n3, udp::v4(), false, false, peers);
s->get_peers(n3, udp::v4(), false, false, address(), peers);
TEST_CHECK(!peers.find_key("values"));
}
@ -142,11 +142,11 @@ TORRENT_TEST(dual_stack)
s->announce_peer(n1, p5, "torrent_name", false);
entry peers4;
s->get_peers(n1, udp::v4(), false, false, peers4);
s->get_peers(n1, udp::v4(), false, false, address(), peers4);
TEST_EQUAL(peers4["values"].list().size(), 3);
entry peers6;
s->get_peers(n1, udp::v6(), false, false, peers6);
s->get_peers(n1, udp::v6(), false, false, address(), peers6);
TEST_EQUAL(peers6["values"].list().size(), 2);
}