added support to bind outgoing connections to specific ports (might be useful to do traffic shaping)
This commit is contained in:
parent
e48e52770b
commit
9d3b60edb7
|
@ -1,3 +1,4 @@
|
||||||
|
* Support to bind outgoing connections to specific ports
|
||||||
* Disk cache support.
|
* Disk cache support.
|
||||||
* New, more memory efficient, piece picker with sequential download
|
* New, more memory efficient, piece picker with sequential download
|
||||||
support (instead of the more complicated sequential download threshold).
|
support (instead of the more complicated sequential download threshold).
|
||||||
|
|
|
@ -1143,7 +1143,7 @@ public:
|
||||||
std::vector<std::string> const& url_seeds() const;
|
std::vector<std::string> const& url_seeds() const;
|
||||||
|
|
||||||
size_type total_size() const;
|
size_type total_size() const;
|
||||||
size_type piece_length() const;
|
int piece_length() const;
|
||||||
int num_pieces() const;
|
int num_pieces() const;
|
||||||
sha1_hash const& info_hash() const;
|
sha1_hash const& info_hash() const;
|
||||||
std::string const& name() const;
|
std::string const& name() const;
|
||||||
|
@ -1158,7 +1158,7 @@ public:
|
||||||
|
|
||||||
void print(std::ostream& os) const;
|
void print(std::ostream& os) const;
|
||||||
|
|
||||||
size_type piece_size(unsigned int index) const;
|
int piece_size(unsigned int index) const;
|
||||||
sha1_hash const& hash_for_piece(unsigned int index) const;
|
sha1_hash const& hash_for_piece(unsigned int index) const;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -1432,8 +1432,8 @@ struct announce_entry
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
size_type total_size() const;
|
size_type total_size() const;
|
||||||
size_type piece_length() const;
|
int piece_length() const;
|
||||||
size_type piece_size(unsigned int index) const;
|
int piece_size(unsigned int index) const;
|
||||||
int num_pieces() const;
|
int num_pieces() const;
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
@ -2596,6 +2596,14 @@ struct session_settings
|
||||||
int send_redundant_have;
|
int send_redundant_have;
|
||||||
bool lazy_bitfields;
|
bool lazy_bitfields;
|
||||||
int inactivity_timeout;
|
int inactivity_timeout;
|
||||||
|
int unchoke_interval;
|
||||||
|
int optimistic_unchoke_multiplier;
|
||||||
|
address announce_ip;
|
||||||
|
int num_want;
|
||||||
|
int initial_picker_threshold;
|
||||||
|
int allowed_fast_set_size;
|
||||||
|
int max_outstanding_disk_bytes_per_connection;
|
||||||
|
int handshake_timeout;
|
||||||
bool use_dht_as_fallback;
|
bool use_dht_as_fallback;
|
||||||
bool free_torrent_hashes;
|
bool free_torrent_hashes;
|
||||||
bool upnp_ignore_nonrouters;
|
bool upnp_ignore_nonrouters;
|
||||||
|
@ -2603,6 +2611,7 @@ struct session_settings
|
||||||
bool auto_upload_slots;
|
bool auto_upload_slots;
|
||||||
int cache_size;
|
int cache_size;
|
||||||
int cache_expiry;
|
int cache_expiry;
|
||||||
|
std::pair<int, int> outgoing_ports;
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
<p><tt class="docutils literal"><span class="pre">user_agent</span></tt> this is the client identification to the tracker.
|
<p><tt class="docutils literal"><span class="pre">user_agent</span></tt> this is the client identification to the tracker.
|
||||||
|
@ -2700,6 +2709,30 @@ from seeding.</p>
|
||||||
<p><tt class="docutils literal"><span class="pre">inactivity_timeout</span></tt>, if a peer is uninteresting and uninterested
|
<p><tt class="docutils literal"><span class="pre">inactivity_timeout</span></tt>, if a peer is uninteresting and uninterested
|
||||||
for longer than this number of seconds, it will be disconnected.
|
for longer than this number of seconds, it will be disconnected.
|
||||||
Default is 10 minutes</p>
|
Default is 10 minutes</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">unchoke_interval</span></tt> is the number of seconds between chokes/unchokes.
|
||||||
|
On this interval, peers are re-evaluated for being choked/unchoked. This
|
||||||
|
is defined as 30 seconds in the protocol, and it should be significantly
|
||||||
|
longer than what it takes for TCP to ramp up to it's max rate.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">optimistic_unchoke_multiplier</span></tt> is the number of unchoke intervals between
|
||||||
|
each <em>optimistic</em> unchoke interval. On this timer, the currently optimistically
|
||||||
|
unchoked peer will change.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">announce_ip</span></tt> is the ip address passed along to trackers as the <tt class="docutils literal"><span class="pre">&ip=</span></tt> parameter.
|
||||||
|
If left as the default (default constructed), that parameter is ommited.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">num_want</span></tt> is the number of peers we want from each tracker request. It defines
|
||||||
|
what is sent as the <tt class="docutils literal"><span class="pre">&num_want=</span></tt> parameter to the tracker.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">initial_picker_threshold</span></tt> specifies the number of pieces we need before we
|
||||||
|
switch to rarest first picking. This defaults to 4, which means the 4 first
|
||||||
|
pieces in any torrent are picked at random, the following pieces are picked
|
||||||
|
in rarest first order.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">allowed_fast_set_size</span></tt> is the number of pieces we allow peers to download
|
||||||
|
from us without being unchoked.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">max_outstanding_disk_bytes_per_connection</span></tt> is the number of bytes each
|
||||||
|
connection is allowed to have waiting in the disk I/O queue before it is
|
||||||
|
throttled back. This limit is meant to stop fast internet connections to
|
||||||
|
queue up bufferes indefinitely on slow hard-drives or storage.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">handshake_timeout</span></tt> specifies the number of seconds we allow a peer to
|
||||||
|
delay responding to a protocol handshake. If no response is received within
|
||||||
|
this time, the connection is closed.</p>
|
||||||
<p><tt class="docutils literal"><span class="pre">use_dht_as_fallback</span></tt> determines how the DHT is used. If this is true
|
<p><tt class="docutils literal"><span class="pre">use_dht_as_fallback</span></tt> determines how the DHT is used. If this is true
|
||||||
(which it is by default), the DHT will only be used for torrents where
|
(which it is by default), the DHT will only be used for torrents where
|
||||||
all trackers in its tracker list has failed. Either by an explicit error
|
all trackers in its tracker list has failed. Either by an explicit error
|
||||||
|
@ -2730,6 +2763,11 @@ current number of upload slots, see <tt class="docutils literal"><span class="pr
|
||||||
It defaults to 128 (= 2 MB).</p>
|
It defaults to 128 (= 2 MB).</p>
|
||||||
<p><tt class="docutils literal"><span class="pre">cache_expiry</span></tt> is the number of seconds from the last cached write to a piece
|
<p><tt class="docutils literal"><span class="pre">cache_expiry</span></tt> is the number of seconds from the last cached write to a piece
|
||||||
in the write cache, to when it's forcefully flushed to disk. Default is 60 second.</p>
|
in the write cache, to when it's forcefully flushed to disk. Default is 60 second.</p>
|
||||||
|
<p><tt class="docutils literal"><span class="pre">outgoing_ports</span></tt>, if set to something other than (0, 0) is a range of ports
|
||||||
|
used to bind outgoing sockets to. This may be useful for users whose router
|
||||||
|
allows them to assign QoS classes to traffic based on its local port. It is
|
||||||
|
a range instead of a single port because of the problems with failing to reconnect
|
||||||
|
to peers if a previous socket to that peer and port is in <tt class="docutils literal"><span class="pre">TIME_WAIT</span></tt> state.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h1><a id="pe-settings" name="pe-settings">pe_settings</a></h1>
|
<h1><a id="pe-settings" name="pe-settings">pe_settings</a></h1>
|
||||||
|
|
|
@ -2604,6 +2604,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your
|
||||||
bool auto_upload_slots;
|
bool auto_upload_slots;
|
||||||
int cache_size;
|
int cache_size;
|
||||||
int cache_expiry;
|
int cache_expiry;
|
||||||
|
std::pair<int, int> outgoing_ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
``user_agent`` this is the client identification to the tracker.
|
``user_agent`` this is the client identification to the tracker.
|
||||||
|
@ -2793,6 +2794,12 @@ It defaults to 128 (= 2 MB).
|
||||||
``cache_expiry`` is the number of seconds from the last cached write to a piece
|
``cache_expiry`` is the number of seconds from the last cached write to a piece
|
||||||
in the write cache, to when it's forcefully flushed to disk. Default is 60 second.
|
in the write cache, to when it's forcefully flushed to disk. Default is 60 second.
|
||||||
|
|
||||||
|
``outgoing_ports``, if set to something other than (0, 0) is a range of ports
|
||||||
|
used to bind outgoing sockets to. This may be useful for users whose router
|
||||||
|
allows them to assign QoS classes to traffic based on its local port. It is
|
||||||
|
a range instead of a single port because of the problems with failing to reconnect
|
||||||
|
to peers if a previous socket to that peer and port is in ``TIME_WAIT`` state.
|
||||||
|
|
||||||
|
|
||||||
pe_settings
|
pe_settings
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -582,6 +582,8 @@ int main(int ac, char* av[])
|
||||||
std::string proxy_type;
|
std::string proxy_type;
|
||||||
int poll_interval;
|
int poll_interval;
|
||||||
int wait_retry;
|
int wait_retry;
|
||||||
|
int bind_port_start = 0;
|
||||||
|
int bind_port_end = 0;
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
try
|
try
|
||||||
|
@ -643,6 +645,10 @@ int main(int ac, char* av[])
|
||||||
"proxy. The string should be given in the form: <username>:<password>")
|
"proxy. The string should be given in the form: <username>:<password>")
|
||||||
("proxy-type", po::value<std::string>(&proxy_type)->default_value("socks5")
|
("proxy-type", po::value<std::string>(&proxy_type)->default_value("socks5")
|
||||||
, "Sets the type of proxy to use [socks5 | http] ")
|
, "Sets the type of proxy to use [socks5 | http] ")
|
||||||
|
("bind-port-start", po::value<int>(&bind_port_start)->default_value(0)
|
||||||
|
, "The lower port number that outgoing connections will be bound to")
|
||||||
|
("bind-port-end", po::value<int>(&bind_port_end)->default_value(0)
|
||||||
|
, "The upper port number that outgoing connections will be bound to")
|
||||||
;
|
;
|
||||||
|
|
||||||
po::positional_options_description p;
|
po::positional_options_description p;
|
||||||
|
@ -735,6 +741,9 @@ int main(int ac, char* av[])
|
||||||
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
|
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
|
||||||
settings.urlseed_wait_retry = wait_retry;
|
settings.urlseed_wait_retry = wait_retry;
|
||||||
|
|
||||||
|
settings.outgoing_ports.first = bind_port_start;
|
||||||
|
settings.outgoing_ports.second = bind_port_end;
|
||||||
|
|
||||||
std::deque<std::string> events;
|
std::deque<std::string> events;
|
||||||
|
|
||||||
ptime next_dir_scan = time_now();
|
ptime next_dir_scan = time_now();
|
||||||
|
|
|
@ -375,6 +375,8 @@ namespace libtorrent
|
||||||
void stop_natpmp();
|
void stop_natpmp();
|
||||||
void stop_upnp();
|
void stop_upnp();
|
||||||
|
|
||||||
|
int next_port();
|
||||||
|
|
||||||
// handles delayed alerts
|
// handles delayed alerts
|
||||||
alert_manager m_alerts;
|
alert_manager m_alerts;
|
||||||
|
|
||||||
|
@ -551,6 +553,10 @@ namespace libtorrent
|
||||||
void second_tick(asio::error_code const& e);
|
void second_tick(asio::error_code const& e);
|
||||||
ptime m_last_tick;
|
ptime m_last_tick;
|
||||||
|
|
||||||
|
// when outgoing_ports is configured, this is the
|
||||||
|
// port we'll bind the next outgoing socket to
|
||||||
|
int m_next_port;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
boost::intrusive_ptr<dht::dht_tracker> m_dht;
|
boost::intrusive_ptr<dht::dht_tracker> m_dht;
|
||||||
dht_settings m_dht_settings;
|
dht_settings m_dht_settings;
|
||||||
|
|
|
@ -126,6 +126,7 @@ namespace libtorrent
|
||||||
, auto_upload_slots(true)
|
, auto_upload_slots(true)
|
||||||
, cache_size(512)
|
, cache_size(512)
|
||||||
, cache_expiry(60)
|
, cache_expiry(60)
|
||||||
|
, outgoing_ports(0,0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// this is the user agent that will be sent to the tracker
|
// this is the user agent that will be sent to the tracker
|
||||||
|
@ -332,6 +333,12 @@ namespace libtorrent
|
||||||
// idle in the cache before it's forcefully flushed
|
// idle in the cache before it's forcefully flushed
|
||||||
// to disk. Default is 60 seconds.
|
// to disk. Default is 60 seconds.
|
||||||
int cache_expiry;
|
int cache_expiry;
|
||||||
|
|
||||||
|
// if != (0, 0), this is the range of ports that
|
||||||
|
// outgoing connections will be bound to. This
|
||||||
|
// is useful for users that have routers that
|
||||||
|
// allow QoS settings based on local port.
|
||||||
|
std::pair<int, int> outgoing_ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
|
|
@ -585,7 +585,8 @@ namespace libtorrent
|
||||||
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
|
||||||
if (candidate != m_peers.end())
|
if (candidate != m_peers.end())
|
||||||
{
|
{
|
||||||
(*m_torrent->session().m_logger) << "*** FOUND CONNECTION CANDIDATE ["
|
(*m_torrent->session().m_logger) << time_now_string()
|
||||||
|
<< " *** FOUND CONNECTION CANDIDATE ["
|
||||||
" ip: " << candidate->second.ip <<
|
" ip: " << candidate->second.ip <<
|
||||||
" d: " << min_cidr_distance <<
|
" d: " << min_cidr_distance <<
|
||||||
" external: " << external_ip <<
|
" external: " << external_ip <<
|
||||||
|
|
|
@ -1138,6 +1138,22 @@ namespace detail
|
||||||
m_key = key;
|
m_key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int session_impl::next_port()
|
||||||
|
{
|
||||||
|
std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
|
||||||
|
if (m_next_port < out_ports.first || m_next_port > out_ports.second)
|
||||||
|
m_next_port = out_ports.first;
|
||||||
|
|
||||||
|
int port = m_next_port;
|
||||||
|
++m_next_port;
|
||||||
|
if (m_next_port > out_ports.second) m_next_port = out_ports.first;
|
||||||
|
#if defined TORRENT_LOGGING
|
||||||
|
(*m_logger) << time_now_string() << " *** BINDING OUTGOING CONNECTION [ "
|
||||||
|
"port: " << port << " ]\n";
|
||||||
|
#endif
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
void session_impl::second_tick(asio::error_code const& e) try
|
void session_impl::second_tick(asio::error_code const& e) try
|
||||||
{
|
{
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||||
|
@ -1149,10 +1165,10 @@ namespace detail
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_LOGGING)
|
#if defined TORRENT_LOGGING
|
||||||
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
|
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
|
||||||
#endif
|
#endif
|
||||||
abort();
|
::abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1790,6 +1790,12 @@ namespace libtorrent
|
||||||
// the proxy, without requiring CONNECT support
|
// the proxy, without requiring CONNECT support
|
||||||
s->get<http_stream>().set_no_connect(true);
|
s->get<http_stream>().set_no_connect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<int, int> const& out_ports = m_settings.outgoing_ports;
|
||||||
|
asio::error_code ec;
|
||||||
|
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||||
|
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
||||||
|
|
||||||
boost::intrusive_ptr<peer_connection> c(new web_peer_connection(
|
boost::intrusive_ptr<peer_connection> c(new web_peer_connection(
|
||||||
m_ses, shared_from_this(), s, a, url, 0));
|
m_ses, shared_from_this(), s, a, url, 0));
|
||||||
|
|
||||||
|
@ -2087,6 +2093,10 @@ namespace libtorrent
|
||||||
|
|
||||||
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s);
|
||||||
TORRENT_ASSERT(ret);
|
TORRENT_ASSERT(ret);
|
||||||
|
std::pair<int, int> const& out_ports = m_ses.settings().outgoing_ports;
|
||||||
|
asio::error_code ec;
|
||||||
|
if (out_ports.first > 0 && out_ports.second >= out_ports.first)
|
||||||
|
s->bind(tcp::endpoint(address(), m_ses.next_port()), ec);
|
||||||
|
|
||||||
boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
|
boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
|
||||||
m_ses, shared_from_this(), s, a, peerinfo));
|
m_ses, shared_from_this(), s, a, peerinfo));
|
||||||
|
|
Loading…
Reference in New Issue