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
|
// 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;
|
||||||
|
|
|
@ -678,12 +678,16 @@ 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())
|
||||||
|
{
|
||||||
|
t->get_policy().set_seed(*this);
|
||||||
|
if (t->is_seed())
|
||||||
{
|
{
|
||||||
throw protocol_error("seed to seed connection redundant, disconnecting");
|
throw protocol_error("seed to seed connection redundant, disconnecting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// --------- BITFIELD ----------
|
// --------- BITFIELD ----------
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -515,6 +515,7 @@ namespace libtorrent
|
||||||
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))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
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;
|
// don't write too big of a package
|
||||||
detail::write_endpoint(*i, pla_out);
|
if (num_added >= max_peer_entries) continue;
|
||||||
|
|
||||||
|
// i->first was added since the last time
|
||||||
|
detail::write_endpoint(i->first, pla_out);
|
||||||
// no supported flags to set yet
|
// no supported flags to set yet
|
||||||
// 0x01 - peer supports encryption
|
// 0x01 - peer supports encryption
|
||||||
detail::write_uint8(0, plf_out);
|
// 0x02 - peer is a seed
|
||||||
|
int flags = i->second->is_seed() ? 2 : 0;
|
||||||
if (--num_peers == 0) break;
|
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;
|
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
|
||||||
|
|
Loading…
Reference in New Issue