forked from premiere/premiere-libtorrent
changes to ut_pex, added support for seed flag in pex messages
This commit is contained in:
parent
72fd437ff0
commit
f1af5dc637
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
100
src/ut_pex.cpp
100
src/ut_pex.cpp
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue