2003-10-23 01:00:57 +02:00
|
|
|
/*
|
|
|
|
|
2016-01-18 00:57:46 +01:00
|
|
|
Copyright (c) 2003-2016, Arvid Norberg
|
2003-10-23 01:00:57 +02:00
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TORRENT_POLICY_HPP_INCLUDED
|
|
|
|
#define TORRENT_POLICY_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include <algorithm>
|
2009-06-03 09:22:43 +02:00
|
|
|
#include <deque>
|
2012-08-26 17:26:17 +02:00
|
|
|
#include "libtorrent/string_util.hpp" // for allocate_string_copy
|
2015-04-21 06:30:34 +02:00
|
|
|
#include "libtorrent/request_blocks.hpp" // for source_rank
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
#include "libtorrent/torrent_peer.hpp"
|
2003-10-24 04:18:11 +02:00
|
|
|
#include "libtorrent/piece_picker.hpp"
|
2004-01-12 04:05:10 +01:00
|
|
|
#include "libtorrent/socket.hpp"
|
2009-11-23 09:38:50 +01:00
|
|
|
#include "libtorrent/address.hpp"
|
2005-08-18 22:38:03 +02:00
|
|
|
#include "libtorrent/invariant_check.hpp"
|
2016-12-04 21:58:51 +01:00
|
|
|
#include "libtorrent/ip_voter.hpp"
|
2005-11-01 19:30:39 +01:00
|
|
|
#include "libtorrent/config.hpp"
|
2014-07-06 21:18:00 +02:00
|
|
|
#include "libtorrent/debug.hpp"
|
|
|
|
#include "libtorrent/peer_connection_interface.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
namespace libtorrent
|
|
|
|
{
|
2014-07-06 21:18:00 +02:00
|
|
|
struct ip_filter;
|
|
|
|
class port_filter;
|
|
|
|
struct torrent_peer_allocator_interface;
|
|
|
|
|
|
|
|
// this object is used to communicate torrent state and
|
2014-10-26 08:34:31 +01:00
|
|
|
// some configuration to the peer_list object. This make
|
|
|
|
// the peer_list type not depend on the torrent type directly.
|
2014-07-06 21:18:00 +02:00
|
|
|
struct torrent_state
|
2005-09-27 10:07:24 +02:00
|
|
|
{
|
2014-07-06 21:18:00 +02:00
|
|
|
torrent_state()
|
2015-04-12 08:39:16 +02:00
|
|
|
: is_paused(false)
|
|
|
|
, is_finished(false)
|
2014-07-06 21:18:00 +02:00
|
|
|
, allow_multiple_connections_per_ip(false)
|
|
|
|
, first_time_seen(false)
|
|
|
|
, max_peerlist_size(1000)
|
|
|
|
, min_reconnect_time(60)
|
|
|
|
, loop_counter(0)
|
2016-12-04 21:58:51 +01:00
|
|
|
, port(0)
|
2015-01-20 07:26:22 +01:00
|
|
|
, max_failcount(3)
|
2016-06-20 17:32:06 +02:00
|
|
|
, peer_allocator(nullptr)
|
2014-07-06 21:18:00 +02:00
|
|
|
{}
|
|
|
|
bool is_paused;
|
|
|
|
bool is_finished;
|
|
|
|
bool allow_multiple_connections_per_ip;
|
|
|
|
|
2014-10-26 08:34:31 +01:00
|
|
|
// this is set by peer_list::add_peer to either true or false
|
2014-07-06 21:18:00 +02:00
|
|
|
// true means the peer we just added was new, false means
|
|
|
|
// we already knew about the peer
|
|
|
|
bool first_time_seen;
|
|
|
|
|
|
|
|
int max_peerlist_size;
|
|
|
|
int min_reconnect_time;
|
|
|
|
|
|
|
|
// the number of iterations over the peer list for this operation
|
|
|
|
int loop_counter;
|
|
|
|
|
|
|
|
// these are used only by find_connect_candidates in order
|
|
|
|
// to implement peer ranking. See:
|
|
|
|
// http://blog.libtorrent.org/2012/12/swarm-connectivity/
|
2016-12-04 21:58:51 +01:00
|
|
|
external_ip ip;
|
2014-07-06 21:18:00 +02:00
|
|
|
int port;
|
|
|
|
|
2015-01-20 07:26:22 +01:00
|
|
|
// the number of times a peer must fail before it's no longer considered
|
|
|
|
// a connect candidate
|
|
|
|
int max_failcount;
|
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
// this must be set to a torrent_peer allocator
|
|
|
|
torrent_peer_allocator_interface* peer_allocator;
|
|
|
|
|
|
|
|
// if any peer were removed during this call, they are returned in
|
|
|
|
// this vector. The caller would want to make sure there are no
|
|
|
|
// references to these torrent_peers anywhere
|
|
|
|
std::vector<torrent_peer*> erased;
|
2005-09-27 10:07:24 +02:00
|
|
|
};
|
|
|
|
|
2014-10-26 08:34:31 +01:00
|
|
|
class TORRENT_EXTRA_EXPORT peer_list : single_threaded
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2014-10-26 08:34:31 +01:00
|
|
|
peer_list();
|
2009-08-20 05:19:12 +02:00
|
|
|
|
|
|
|
#if TORRENT_USE_I2P
|
2014-07-06 21:18:00 +02:00
|
|
|
torrent_peer* add_i2p_peer(char const* destination, int src, char flags
|
|
|
|
, torrent_state* state);
|
2009-08-20 05:19:12 +02:00
|
|
|
#endif
|
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
// these flags match the flags passed in ut_pex
|
|
|
|
// messages
|
|
|
|
flag_encryption = 0x1,
|
|
|
|
flag_seed = 0x2,
|
|
|
|
flag_utp = 0x4,
|
2015-04-24 07:37:17 +02:00
|
|
|
flag_holepunch = 0x8
|
2014-07-06 21:18:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// this is called once for every torrent_peer we get from
|
2007-04-10 23:23:13 +02:00
|
|
|
// the tracker, pex, lsd or dht.
|
2014-07-06 21:18:00 +02:00
|
|
|
torrent_peer* add_peer(const tcp::endpoint& remote
|
|
|
|
, int source, char flags, torrent_state* state);
|
2008-01-07 02:10:46 +01:00
|
|
|
|
|
|
|
// false means duplicate connection
|
2014-07-06 21:18:00 +02:00
|
|
|
bool update_peer_port(int port, torrent_peer* p, int src, torrent_state* state);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2004-01-14 17:18:53 +01:00
|
|
|
// called when an incoming connection is accepted
|
2008-01-07 02:10:46 +01:00
|
|
|
// false means the connection was refused or failed
|
2014-07-06 21:18:00 +02:00
|
|
|
bool new_connection(peer_connection_interface& c, int session_time, torrent_state* state);
|
2004-01-14 17:18:53 +01:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// the given connection was just closed
|
2015-04-13 02:50:55 +02:00
|
|
|
void connection_closed(const peer_connection_interface& c
|
|
|
|
, int session_time, torrent_state* state);
|
2009-06-18 18:16:41 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
bool ban_peer(torrent_peer* p);
|
|
|
|
void set_connection(torrent_peer* p, peer_connection_interface* c);
|
|
|
|
void set_failcount(torrent_peer* p, int f);
|
|
|
|
void inc_failcount(torrent_peer* p);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2015-01-21 00:56:45 +01:00
|
|
|
void apply_ip_filter(ip_filter const& filter, torrent_state* state
|
|
|
|
, std::vector<address>& banned);
|
|
|
|
void apply_port_filter(port_filter const& filter, torrent_state* state
|
|
|
|
, std::vector<address>& banned);
|
2007-07-26 09:04:35 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
void set_seed(torrent_peer* p, bool s);
|
2009-06-13 06:14:41 +02:00
|
|
|
|
2014-01-23 04:31:36 +01:00
|
|
|
// this clears all cached peer priorities. It's called when
|
|
|
|
// our external IP changes
|
|
|
|
void clear_peer_prio();
|
|
|
|
|
2014-01-19 20:45:50 +01:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2014-07-06 21:18:00 +02:00
|
|
|
bool has_connection(const peer_connection_interface* p);
|
2011-05-08 11:04:59 +02:00
|
|
|
#endif
|
2014-01-21 20:26:09 +01:00
|
|
|
#if TORRENT_USE_INVARIANT_CHECKS
|
2004-05-10 08:12:29 +02:00
|
|
|
void check_invariant() const;
|
2003-12-01 06:01:40 +01:00
|
|
|
#endif
|
|
|
|
|
2014-11-29 02:53:22 +01:00
|
|
|
int num_peers() const { return int(m_peers.size()); }
|
2004-03-21 03:03:37 +01:00
|
|
|
|
2016-05-08 00:46:42 +02:00
|
|
|
using peers_t = std::deque<torrent_peer*>;
|
|
|
|
using iterator = peers_t::iterator;
|
|
|
|
using const_iterator = peers_t::const_iterator;
|
2016-06-01 07:05:17 +02:00
|
|
|
iterator begin() { return m_peers.begin(); }
|
|
|
|
iterator end() { return m_peers.end(); }
|
|
|
|
const_iterator begin() const { return m_peers.begin(); }
|
|
|
|
const_iterator end() const { return m_peers.end(); }
|
2009-05-11 22:23:47 +02:00
|
|
|
|
2009-02-25 06:53:24 +01:00
|
|
|
std::pair<iterator, iterator> find_peers(address const& a)
|
2009-05-07 00:36:24 +02:00
|
|
|
{
|
2015-06-21 03:03:35 +02:00
|
|
|
#if TORRENT_USE_I2P
|
|
|
|
if (a == address())
|
|
|
|
return std::pair<iterator, iterator>(m_peers.end(), m_peers.end());
|
|
|
|
#endif
|
2009-05-25 12:15:35 +02:00
|
|
|
return std::equal_range(
|
|
|
|
m_peers.begin(), m_peers.end(), a, peer_address_compare());
|
2009-05-11 22:23:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<const_iterator, const_iterator> find_peers(address const& a) const
|
|
|
|
{
|
2009-05-25 12:15:35 +02:00
|
|
|
return std::equal_range(
|
|
|
|
m_peers.begin(), m_peers.end(), a, peer_address_compare());
|
2009-05-07 00:36:24 +02:00
|
|
|
}
|
2004-10-29 15:21:09 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
torrent_peer* connect_one_peer(int session_time, torrent_state* state);
|
2007-05-05 02:29:33 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
bool has_peer(torrent_peer const* p) const;
|
2007-12-27 21:57:58 +01:00
|
|
|
|
2016-11-20 03:14:16 +01:00
|
|
|
int num_seeds() const { return int(m_num_seeds); }
|
2008-03-29 19:47:24 +01:00
|
|
|
int num_connect_candidates() const { return m_num_connect_candidates; }
|
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
void erase_peer(torrent_peer* p, torrent_state* state);
|
|
|
|
void erase_peer(iterator i, torrent_state* state);
|
2008-04-24 09:49:23 +02:00
|
|
|
|
2015-01-20 07:26:22 +01:00
|
|
|
void set_max_failcount(torrent_state* st);
|
|
|
|
|
2004-01-15 17:45:34 +01:00
|
|
|
private:
|
2008-03-29 19:47:24 +01:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
void recalculate_connect_candidates(torrent_state* state);
|
|
|
|
|
|
|
|
void update_connect_candidates(int delta);
|
|
|
|
|
|
|
|
void update_peer(torrent_peer* p, int src, int flags
|
2009-08-20 05:19:12 +02:00
|
|
|
, tcp::endpoint const& remote, char const* destination);
|
2014-07-06 21:18:00 +02:00
|
|
|
bool insert_peer(torrent_peer* p, iterator iter, int flags, torrent_state* state);
|
2009-08-20 05:19:12 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
bool compare_peer_erase(torrent_peer const& lhs, torrent_peer const& rhs) const;
|
|
|
|
bool compare_peer(torrent_peer const* lhs, torrent_peer const* rhs
|
2013-01-02 00:12:16 +01:00
|
|
|
, external_ip const& external, int source_port) const;
|
2008-04-24 09:49:23 +02:00
|
|
|
|
2015-01-20 07:26:22 +01:00
|
|
|
void find_connect_candidates(std::vector<torrent_peer*>& peers
|
|
|
|
, int session_time, torrent_state* state);
|
2004-01-14 17:18:53 +01:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
bool is_connect_candidate(torrent_peer const& p) const;
|
|
|
|
bool is_erase_candidate(torrent_peer const& p) const;
|
|
|
|
bool is_force_erase_candidate(torrent_peer const& pe) const;
|
|
|
|
bool should_erase_immediately(torrent_peer const& p) const;
|
2009-05-11 22:23:47 +02:00
|
|
|
|
2011-11-24 18:50:57 +01:00
|
|
|
enum flags_t { force_erase = 1 };
|
2014-07-06 21:18:00 +02:00
|
|
|
void erase_peers(torrent_state* state, int flags = 0);
|
2008-03-29 19:47:24 +01:00
|
|
|
|
2009-04-30 07:49:46 +02:00
|
|
|
peers_t m_peers;
|
2003-12-01 06:01:40 +01:00
|
|
|
|
2016-06-20 17:32:06 +02:00
|
|
|
// this should be nullptr for the most part. It's set
|
2012-11-21 21:42:40 +01:00
|
|
|
// to point to a valid torrent_peer object if that
|
|
|
|
// object needs to be kept alive. If we ever feel
|
|
|
|
// like removing a torrent_peer from m_peers, we
|
|
|
|
// first check if the peer matches this one, and
|
|
|
|
// if so, don't delete it.
|
2014-07-06 21:18:00 +02:00
|
|
|
torrent_peer* m_locked_peer;
|
2012-11-21 21:42:40 +01:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
// the number of seeds in the torrent_peer list
|
2016-06-18 20:01:38 +02:00
|
|
|
std::uint32_t m_num_seeds:31;
|
2009-05-06 09:06:26 +02:00
|
|
|
|
|
|
|
// this was the state of the torrent the
|
|
|
|
// last time we recalculated the number of
|
|
|
|
// connect candidates. Since seeds (or upload
|
|
|
|
// only) peers are not connect candidates
|
|
|
|
// when we're finished, the set depends on
|
|
|
|
// this state. Every time m_torrent->is_finished()
|
|
|
|
// is different from this state, we need to
|
|
|
|
// recalculate the connect candidates.
|
2016-06-18 20:01:38 +02:00
|
|
|
std::uint32_t m_finished:1;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
// since the torrent_peer list can grow too large
|
|
|
|
// to scan all of it, start at this index
|
|
|
|
int m_round_robin;
|
2009-05-24 23:49:19 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
// a list of good connect candidates
|
|
|
|
std::vector<torrent_peer*> m_candidate_cache;
|
2009-05-24 23:49:19 +02:00
|
|
|
|
2014-07-06 21:18:00 +02:00
|
|
|
// The number of peers in our torrent_peer list
|
|
|
|
// that are connect candidates. i.e. they're
|
|
|
|
// not already connected and they have not
|
|
|
|
// yet reached their max try count and they
|
|
|
|
// have the connectable state (we have a listen
|
|
|
|
// port for them).
|
|
|
|
int m_num_connect_candidates;
|
2009-05-24 23:49:19 +02:00
|
|
|
|
2015-01-20 07:26:22 +01:00
|
|
|
// if a peer has failed this many times or more, we don't consider
|
|
|
|
// it a connect candidate anymore.
|
|
|
|
int m_max_failcount;
|
2014-07-06 21:18:00 +02:00
|
|
|
};
|
2009-05-24 23:49:19 +02:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // TORRENT_POLICY_HPP_INCLUDED
|