changes to ut_pex, added support for seed flag in pex messages

This commit is contained in:
Arvid Norberg 2007-03-28 01:06:15 +00:00
parent 72fd437ff0
commit f1af5dc637
5 changed files with 97 additions and 57 deletions

View File

@ -86,7 +86,8 @@ namespace libtorrent
// this is called once for every peer we get from
// the tracker
void peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid);
void peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, char flags = 0);
// called when an incoming connection is accepted
void new_connection(peer_connection& c);
@ -101,7 +102,10 @@ namespace libtorrent
// is called when a peer is believed to have
// sent invalid data
void ban_peer(const peer_connection& c);
void ban_peer(peer_connection const& c);
// is called on peers that become seeds
void set_seed(peer_connection const& c);
// the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c);
@ -144,6 +148,9 @@ namespace libtorrent
tcp::endpoint ip;
connection_type type;
// this is true if the peer is a seed
bool seed;
// the time when this peer was optimistically unchoked
// the last time.
boost::posix_time::ptime last_optimistically_unchoked;

View File

@ -678,9 +678,13 @@ namespace libtorrent
t->get_policy().peer_is_interesting(*this);
}
if (t->is_seed() && is_seed())
if (is_seed())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
t->get_policy().set_seed(*this);
if (t->is_seed())
{
throw protocol_error("seed to seed connection redundant, disconnecting");
}
}
}
}
@ -751,6 +755,7 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " *** THIS IS A SEED ***\n";
#endif
t->get_policy().set_seed(*this);
// if we're a seed too, disconnect
if (t->is_seed())
{

View File

@ -512,9 +512,10 @@ namespace libtorrent
for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); ++i)
{
if(i->connection) continue;
if(i->banned) continue;
if(i->type == peer::not_connectable) continue;
if (i->connection) continue;
if (i->banned) continue;
if (i->type == peer::not_connectable) continue;
if (i->seed && m_torrent->is_seed()) continue;
assert(i->connected <= local_time);
@ -857,7 +858,7 @@ namespace libtorrent
}
}
void policy::ban_peer(const peer_connection& c)
void policy::ban_peer(peer_connection const& c)
{
INVARIANT_CHECK;
@ -881,6 +882,21 @@ namespace libtorrent
i->banned = true;
}
void policy::set_seed(peer_connection const& c)
{
INVARIANT_CHECK;
std::vector<peer>::iterator i = std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_connection(c));
// it might be an http-seed
if (i == m_peers.end()) return;
i->seed = true;
}
void policy::new_connection(peer_connection& c)
{
assert(!c.is_local());
@ -974,7 +990,8 @@ namespace libtorrent
m_last_optimistic_disconnect = second_clock::universal_time();
}
void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid)
void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, char flags)
{
INVARIANT_CHECK;
@ -1012,6 +1029,7 @@ namespace libtorrent
// the iterator is invalid
// because of the push_back()
i = m_peers.end() - 1;
if (flags & 0x02) p.seed = true;
just_added = true;
}
else
@ -1022,6 +1040,7 @@ namespace libtorrent
// not known, so save it. Client may also have changed port
// for some reason.
i->ip = remote;
if (flags & 0x02) i->seed = true;
if (i->connection)
{
@ -1386,7 +1405,8 @@ namespace libtorrent
#endif
policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t)
: ip(ip_)
: seed(false)
, ip(ip_)
, type(t)
, last_optimistically_unchoked(
boost::gregorian::date(1970,boost::gregorian::Jan,1))

View File

@ -519,7 +519,7 @@ namespace libtorrent
get_handle(), peers.size(), "Got peers from DHT"));
}
std::for_each(peers.begin(), peers.end(), bind(
&policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0)));
&policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0), 0));
}
#endif

View File

@ -81,7 +81,19 @@ namespace libtorrent { namespace
if (++m_1_minute < 60) return;
m_1_minute = 0;
std::list<tcp::endpoint> cs;
entry pex;
std::string& pla = pex["added"].string();
std::string& pld = pex["dropped"].string();
std::string& plf = pex["added.f"].string();
std::back_insert_iterator<std::string> pla_out(pla);
std::back_insert_iterator<std::string> pld_out(pld);
std::back_insert_iterator<std::string> plf_out(plf);
std::set<tcp::endpoint> dropped;
m_old_peers.swap(dropped);
int num_added = 0;
for (torrent::peer_iterator i = m_torrent.begin()
, end(m_torrent.end()); i != end; ++i)
{
@ -90,52 +102,41 @@ namespace libtorrent { namespace
if (!i->second->is_local()) continue;
// don't send out peers that we haven't successfully connected to
if (i->second->is_connecting()) continue;
cs.push_back(i->first);
}
std::list<tcp::endpoint> added_peers, dropped_peers;
// ut pex does not support IPv6
if (!i->first.address().is_v4()) continue;
std::set_difference(cs.begin(), cs.end(), m_old_peers.begin()
, m_old_peers.end(), std::back_inserter(added_peers));
std::set_difference(m_old_peers.begin(), m_old_peers.end()
, cs.begin(), cs.end(), std::back_inserter(dropped_peers));
m_old_peers = cs;
m_old_peers.insert(i->first);
unsigned int num_peers = max_peer_entries;
std::set<tcp::endpoint>::iterator di = dropped.find(i->first);
if (di == dropped.end())
{
// don't write too big of a package
if (num_added >= max_peer_entries) continue;
std::string pla, pld, plf;
std::back_insert_iterator<std::string> pla_out(pla);
std::back_insert_iterator<std::string> pld_out(pld);
std::back_insert_iterator<std::string> plf_out(plf);
// TODO: use random selection in case added_peers.size() > num_peers
for (std::list<tcp::endpoint>::const_iterator i = added_peers.begin()
, end(added_peers.end());i != end; ++i)
{
if (!i->address().is_v4()) continue;
detail::write_endpoint(*i, pla_out);
// no supported flags to set yet
// 0x01 - peer supports encryption
detail::write_uint8(0, plf_out);
if (--num_peers == 0) break;
// i->first was added since the last time
detail::write_endpoint(i->first, pla_out);
// no supported flags to set yet
// 0x01 - peer supports encryption
// 0x02 - peer is a seed
int flags = i->second->is_seed() ? 2 : 0;
detail::write_uint8(flags, plf_out);
++num_added;
}
else
{
// this was in the previous message
// so, it wasn't dropped
dropped.erase(di);
}
}
num_peers = max_peer_entries;
// TODO: use random selection in case dropped_peers.size() > num_peers
for (std::list<tcp::endpoint>::const_iterator i = dropped_peers.begin()
, end(dropped_peers.end());i != end; ++i)
for (std::set<tcp::endpoint>::const_iterator i = dropped.begin()
, end(dropped.end());i != end; ++i)
{
if (!i->address().is_v4()) continue;
detail::write_endpoint(*i, pld_out);
if (--num_peers == 0) break;
}
entry pex(entry::dictionary_t);
pex["added"] = pla;
pex["dropped"] = pld;
pex["added.f"] = plf;
m_ut_pex_msg.clear();
bencode(std::back_inserter(m_ut_pex_msg), pex);
}
@ -143,7 +144,7 @@ namespace libtorrent { namespace
private:
torrent& m_torrent;
std::list<tcp::endpoint> m_old_peers;
std::set<tcp::endpoint> m_old_peers;
int m_1_minute;
std::vector<char> m_ut_pex_msg;
};
@ -182,6 +183,7 @@ namespace libtorrent { namespace
}
virtual bool on_extended(int length, int msg, buffer::const_interval body)
try
{
if (msg != extension_index) return false;
if (m_message_index == 0) return false;
@ -194,26 +196,32 @@ namespace libtorrent { namespace
// in case we are a seed we do not use the peers
// from the pex message to prevent us from
// overloading ourself
if (m_torrent.is_seed()) return true;
entry Pex = bdecode(body.begin, body.end);
entry* PeerList = Pex.find_key("added");
entry pex_msg = bdecode(body.begin, body.end);
std::string const& peers = pex_msg["added"].string();
std::string const& peer_flags = pex_msg["added.f"].string();
if (!PeerList) return true;
std::string const& peers = PeerList->string();
int num_peers = peers.length() / 6;
char const* in = peers.c_str();
char const* fin = peer_flags.c_str();
peer_id pid;
pid.clear();
if (int(peer_flags.size()) != num_peers)
return true;
peer_id pid(0);
policy& p = m_torrent.get_policy();
for (int i = 0; i < num_peers; ++i)
{
tcp::endpoint adr = detail::read_v4_endpoint<tcp::endpoint>(in);
if (!m_torrent.connection_for(adr)) p.peer_from_tracker(adr, pid);
char flags = detail::read_uint8(fin);
p.peer_from_tracker(adr, pid, flags);
}
return true;
}
catch (std::exception&)
{
return true;
}
// the peers second tick
// every minute we send a pex message