added support to bind outgoing connections to specific ports (might be useful to do traffic shaping)

This commit is contained in:
Arvid Norberg 2008-02-28 07:34:07 +00:00
parent e48e52770b
commit 9d3b60edb7
9 changed files with 102 additions and 7 deletions

View File

@ -1,3 +1,4 @@
* Support to bind outgoing connections to specific ports
* Disk cache support.
* New, more memory efficient, piece picker with sequential download
support (instead of the more complicated sequential download threshold).

View File

@ -1143,7 +1143,7 @@ public:
std::vector<std::string> const& url_seeds() const;
size_type total_size() const;
size_type piece_length() const;
int piece_length() const;
int num_pieces() const;
sha1_hash const& info_hash() const;
std::string const& name() const;
@ -1158,7 +1158,7 @@ public:
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;
};
</pre>
@ -1432,8 +1432,8 @@ struct announce_entry
<blockquote>
<pre class="literal-block">
size_type total_size() const;
size_type piece_length() const;
size_type piece_size(unsigned int index) const;
int piece_length() const;
int piece_size(unsigned int index) const;
int num_pieces() const;
</pre>
</blockquote>
@ -2596,6 +2596,14 @@ struct session_settings
int send_redundant_have;
bool lazy_bitfields;
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 free_torrent_hashes;
bool upnp_ignore_nonrouters;
@ -2603,6 +2611,7 @@ struct session_settings
bool auto_upload_slots;
int cache_size;
int cache_expiry;
std::pair&lt;int, int&gt; outgoing_ports;
};
</pre>
<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
for longer than this number of seconds, it will be disconnected.
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">&amp;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">&amp;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
(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
@ -2730,6 +2763,11 @@ current number of upload slots, see <tt class="docutils literal"><span class="pr
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
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 class="section">
<h1><a id="pe-settings" name="pe-settings">pe_settings</a></h1>

View File

@ -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;
int cache_size;
int cache_expiry;
std::pair<int, int> outgoing_ports;
};
``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
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
===========

View File

@ -582,6 +582,8 @@ int main(int ac, char* av[])
std::string proxy_type;
int poll_interval;
int wait_retry;
int bind_port_start = 0;
int bind_port_end = 0;
namespace po = boost::program_options;
try
@ -643,6 +645,10 @@ int main(int ac, char* av[])
"proxy. The string should be given in the form: <username>:<password>")
("proxy-type", po::value<std::string>(&proxy_type)->default_value("socks5")
, "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;
@ -735,6 +741,9 @@ int main(int ac, char* av[])
settings.user_agent = "client_test/" LIBTORRENT_VERSION;
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;
ptime next_dir_scan = time_now();

View File

@ -375,6 +375,8 @@ namespace libtorrent
void stop_natpmp();
void stop_upnp();
int next_port();
// handles delayed alerts
alert_manager m_alerts;
@ -551,6 +553,10 @@ namespace libtorrent
void second_tick(asio::error_code const& e);
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
boost::intrusive_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings;

View File

@ -126,6 +126,7 @@ namespace libtorrent
, auto_upload_slots(true)
, cache_size(512)
, cache_expiry(60)
, outgoing_ports(0,0)
{}
// 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
// to disk. Default is 60 seconds.
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

View File

@ -585,7 +585,8 @@ namespace libtorrent
#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING
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 <<
" d: " << min_cidr_distance <<
" external: " << external_ip <<

View File

@ -1138,6 +1138,22 @@ namespace detail
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
{
session_impl::mutex_t::scoped_lock l(m_mutex);
@ -1149,10 +1165,10 @@ namespace detail
if (e)
{
#if defined(TORRENT_LOGGING)
#if defined TORRENT_LOGGING
(*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n";
#endif
abort();
::abort();
return;
}

View File

@ -1790,6 +1790,12 @@ namespace libtorrent
// the proxy, without requiring CONNECT support
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(
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);
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(
m_ses, shared_from_this(), s, a, peerinfo));