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 // this is called once for every peer we get from
// the tracker // 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 // called when an incoming connection is accepted
void new_connection(peer_connection& c); void new_connection(peer_connection& c);
@ -101,7 +102,10 @@ namespace libtorrent
// is called when a peer is believed to have // is called when a peer is believed to have
// sent invalid data // 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 // the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c); void peer_is_interesting(peer_connection& c);
@ -144,6 +148,9 @@ namespace libtorrent
tcp::endpoint ip; tcp::endpoint ip;
connection_type type; connection_type type;
// this is true if the peer is a seed
bool seed;
// the time when this peer was optimistically unchoked // the time when this peer was optimistically unchoked
// the last time. // the last time.
boost::posix_time::ptime last_optimistically_unchoked; boost::posix_time::ptime last_optimistically_unchoked;

View File

@ -678,9 +678,13 @@ namespace libtorrent
t->get_policy().peer_is_interesting(*this); 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 #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " *** THIS IS A SEED ***\n"; (*m_logger) << " *** THIS IS A SEED ***\n";
#endif #endif
t->get_policy().set_seed(*this);
// if we're a seed too, disconnect // if we're a seed too, disconnect
if (t->is_seed()) if (t->is_seed())
{ {

View File

@ -512,9 +512,10 @@ namespace libtorrent
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
if(i->connection) continue; if (i->connection) continue;
if(i->banned) continue; if (i->banned) continue;
if(i->type == peer::not_connectable) continue; if (i->type == peer::not_connectable) continue;
if (i->seed && m_torrent->is_seed()) continue;
assert(i->connected <= local_time); 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; INVARIANT_CHECK;
@ -881,6 +882,21 @@ namespace libtorrent
i->banned = true; 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) void policy::new_connection(peer_connection& c)
{ {
assert(!c.is_local()); assert(!c.is_local());
@ -974,7 +990,8 @@ namespace libtorrent
m_last_optimistic_disconnect = second_clock::universal_time(); 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; INVARIANT_CHECK;
@ -1012,6 +1029,7 @@ namespace libtorrent
// the iterator is invalid // the iterator is invalid
// because of the push_back() // because of the push_back()
i = m_peers.end() - 1; i = m_peers.end() - 1;
if (flags & 0x02) p.seed = true;
just_added = true; just_added = true;
} }
else else
@ -1022,6 +1040,7 @@ namespace libtorrent
// 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->ip = remote;
if (flags & 0x02) i->seed = true;
if (i->connection) if (i->connection)
{ {
@ -1386,7 +1405,8 @@ namespace libtorrent
#endif #endif
policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t) policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t)
: ip(ip_) : seed(false)
, ip(ip_)
, type(t) , type(t)
, last_optimistically_unchoked( , last_optimistically_unchoked(
boost::gregorian::date(1970,boost::gregorian::Jan,1)) boost::gregorian::date(1970,boost::gregorian::Jan,1))

View File

@ -519,7 +519,7 @@ namespace libtorrent
get_handle(), peers.size(), "Got peers from DHT")); get_handle(), peers.size(), "Got peers from DHT"));
} }
std::for_each(peers.begin(), peers.end(), bind( 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 #endif

View File

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