improved support for multi-homed clients

This commit is contained in:
Arvid Norberg 2010-07-17 07:13:14 +00:00
parent 9a9c121ec0
commit 1e70456f58
7 changed files with 61 additions and 15 deletions

View File

@ -1,3 +1,4 @@
* improved support for multi-homed clients
* added feature to not count downloaded bytes from web seeds in stats * added feature to not count downloaded bytes from web seeds in stats
* added alert for incoming local service discovery messages * added alert for incoming local service discovery messages
* added option to set file priorities when adding torrents * added option to set file priorities when adding torrents

View File

@ -2744,8 +2744,10 @@ use_interface()
``use_interface()`` sets the network interface this torrent will use when it opens outgoing ``use_interface()`` sets the network interface this torrent will use when it opens outgoing
connections. By default, it uses the same interface as the session_ uses to listen on. The connections. By default, it uses the same interface as the session_ uses to listen on. The
parameter must be a string containing an ip-address (either an IPv4 or IPv6 address). If parameter must be a string containing one or more, comma separated, ip-address (either an
the string does not conform to this format and exception is thrown. IPv4 or IPv6 address). When specifying multiple interfaces, the torrent will round-robin
which interface to use for each outgoing conneciton. This is useful for clients that are
multi-homed.
info_hash() info_hash()
@ -3485,6 +3487,8 @@ It contains the following fields::
float progress; float progress;
int progress_ppm; int progress_ppm;
tcp::endpoint local_endpoint;
}; };
The ``flags`` attribute tells you in which state the peer is. It is set to The ``flags`` attribute tells you in which state the peer is. It is set to
@ -3710,6 +3714,11 @@ floating point operations are diabled, instead use ``progress_ppm``.
``progress_ppm`` indicates the download progress of the peer in the range [0, 1000000] ``progress_ppm`` indicates the download progress of the peer in the range [0, 1000000]
(parts per million). (parts per million).
``local_endpoint`` is the IP and port pair the socket is bound to locally. i.e. the IP
address of the interface it's going out over. This may be useful for multi-homed
clients with multiple interfaces to the internet.
session customization session customization
===================== =====================

View File

@ -329,7 +329,7 @@ int peer_index(libtorrent::tcp::endpoint addr, std::vector<libtorrent::peer_info
void print_peer_info(std::string& out, std::vector<libtorrent::peer_info> const& peers) void print_peer_info(std::string& out, std::vector<libtorrent::peer_info> const& peers)
{ {
using namespace libtorrent; using namespace libtorrent;
if (print_ip) out += "IP "; if (print_ip) out += "IP ";
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
if (print_as) out += "AS "; if (print_as) out += "AS ";
#endif #endif
@ -355,7 +355,8 @@ void print_peer_info(std::string& out, std::vector<libtorrent::peer_info> const&
if (print_ip) if (print_ip)
{ {
error_code ec; error_code ec;
snprintf(str, sizeof(str), "%-22s:%-5d ", i->ip.address().to_string(ec).c_str(), i->ip.port()); snprintf(str, sizeof(str), "%-22s %22s ", print_endpoint(i->ip).c_str()
, print_endpoint(i->local_endpoint).c_str());
out += str; out += str;
} }
@ -511,6 +512,7 @@ int torrent_upload_limit = 0;
int torrent_download_limit = 0; int torrent_download_limit = 0;
std::string monitor_dir; std::string monitor_dir;
std::string bind_to_interface = ""; std::string bind_to_interface = "";
std::string outgoing_interface = "";
int poll_interval = 5; int poll_interval = 5;
int max_connections_per_torrent = 50; int max_connections_per_torrent = 50;
@ -573,6 +575,7 @@ void add_torrent(libtorrent::session& ses
h.set_ratio(preferred_ratio); h.set_ratio(preferred_ratio);
h.set_upload_limit(torrent_upload_limit); h.set_upload_limit(torrent_upload_limit);
h.set_download_limit(torrent_download_limit); h.set_download_limit(torrent_download_limit);
h.use_interface(outgoing_interface.c_str());
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
h.resolve_countries(true); h.resolve_countries(true);
#endif #endif
@ -752,6 +755,8 @@ int main(int argc, char* argv[])
" -m <path> sets the .torrent monitor directory\n" " -m <path> sets the .torrent monitor directory\n"
" -b <IP> sets IP of the interface to bind the\n" " -b <IP> sets IP of the interface to bind the\n"
" listen socket to\n" " listen socket to\n"
" -I <IP> sets the IP of the interface to bind\n"
" outgoing peer connections to\n"
" -w <seconds> sets the retry time for failed web seeds\n" " -w <seconds> sets the retry time for failed web seeds\n"
" -t <seconds> sets the scan interval of the monitor dir\n" " -t <seconds> sets the scan interval of the monitor dir\n"
" -x <file> loads an emule IP-filter file\n" " -x <file> loads an emule IP-filter file\n"
@ -956,6 +961,7 @@ int main(int argc, char* argv[])
#endif #endif
} }
break; break;
case 'I': outgoing_interface = arg; break;
} }
++i; // skip the argument ++i; // skip the argument
} }
@ -999,6 +1005,7 @@ int main(int argc, char* argv[])
h.set_ratio(preferred_ratio); h.set_ratio(preferred_ratio);
h.set_upload_limit(torrent_upload_limit); h.set_upload_limit(torrent_upload_limit);
h.set_download_limit(torrent_download_limit); h.set_download_limit(torrent_download_limit);
h.use_interface(outgoing_interface.c_str());
} }
for (std::vector<std::string>::iterator i = torrents.begin() for (std::vector<std::string>::iterator i = torrents.begin()
@ -1026,6 +1033,7 @@ int main(int argc, char* argv[])
h.set_ratio(preferred_ratio); h.set_ratio(preferred_ratio);
h.set_upload_limit(torrent_upload_limit); h.set_upload_limit(torrent_upload_limit);
h.set_download_limit(torrent_download_limit); h.set_download_limit(torrent_download_limit);
h.use_interface(outgoing_interface.c_str());
continue; continue;
} }

View File

@ -216,6 +216,8 @@ namespace libtorrent
int progress_ppm; // [0, 1000000] int progress_ppm; // [0, 1000000]
int estimated_reciprocation_rate; int estimated_reciprocation_rate;
tcp::endpoint local_endpoint;
}; };
struct TORRENT_EXPORT peer_list_entry struct TORRENT_EXPORT peer_list_entry

View File

@ -309,7 +309,7 @@ namespace libtorrent
void file_progress(std::vector<size_type>& fp, int flags = 0) const; void file_progress(std::vector<size_type>& fp, int flags = 0) const;
void use_interface(std::string net_interface); void use_interface(std::string net_interface);
tcp::endpoint get_interface() const { return m_net_interface; } tcp::endpoint get_interface() const;
void connect_to_url_seed(std::list<web_seed_entry>::iterator url); void connect_to_url_seed(std::list<web_seed_entry>::iterator url);
bool connect_to_peer(policy::peer* peerinfo); bool connect_to_peer(policy::peer* peerinfo);
@ -939,9 +939,10 @@ namespace libtorrent
std::string m_username; std::string m_username;
std::string m_password; std::string m_password;
// the network interface all outgoing connections // the network interfaces outgoing connections
// are opened through // are opened through. If there is more then one,
union_endpoint m_net_interface; // they are used in a round-robin fasion
std::vector<union_endpoint> m_net_interfaces;
std::string m_save_path; std::string m_save_path;
@ -1208,6 +1209,9 @@ namespace libtorrent
// the number of seconds since the last byte was uploaded // the number of seconds since the last byte was uploaded
// from this torrent // from this torrent
boost::uint16_t m_last_upload; boost::uint16_t m_last_upload;
// round-robin index into m_interfaces
mutable boost::uint8_t m_interface_index;
}; };
} }

View File

@ -3471,6 +3471,9 @@ namespace libtorrent
int upload_capacity = m_ses.upload_rate_limit(); int upload_capacity = m_ses.upload_rate_limit();
if (upload_capacity == 0) if (upload_capacity == 0)
upload_capacity = (std::max)(20000, m_ses.m_peak_up_rate + 10000); upload_capacity = (std::max)(20000, m_ses.m_peak_up_rate + 10000);
error_code ec;
p.local_endpoint = get_socket()->local_endpoint(ec);
} }
// allocates a disk buffer of size 'disk_buffer_size' and replaces the // allocates a disk buffer of size 'disk_buffer_size' and replaces the

View File

@ -77,6 +77,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/kademlia/dht_tracker.hpp" #include "libtorrent/kademlia/dht_tracker.hpp"
#include "libtorrent/peer_info.hpp" #include "libtorrent/peer_info.hpp"
#include "libtorrent/enum_net.hpp"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <iostream> #include <iostream>
@ -226,7 +227,7 @@ namespace libtorrent
PRINT_OFFSETOF(torrent, m_time_critical_pieces) PRINT_OFFSETOF(torrent, m_time_critical_pieces)
PRINT_OFFSETOF(torrent, m_username) PRINT_OFFSETOF(torrent, m_username)
PRINT_OFFSETOF(torrent, m_password) PRINT_OFFSETOF(torrent, m_password)
PRINT_OFFSETOF(torrent, m_net_interface) PRINT_OFFSETOF(torrent, m_net_interfaces)
PRINT_OFFSETOF(torrent, m_save_path) PRINT_OFFSETOF(torrent, m_save_path)
PRINT_OFFSETOF(torrent, m_verified) PRINT_OFFSETOF(torrent, m_verified)
PRINT_OFFSETOF(torrent, m_error) PRINT_OFFSETOF(torrent, m_error)
@ -323,7 +324,6 @@ namespace libtorrent
, m_tracker_timer(ses.m_io_service) , m_tracker_timer(ses.m_io_service)
, m_ses(ses) , m_ses(ses)
, m_trackers(m_torrent_file->trackers()) , m_trackers(m_torrent_file->trackers())
, m_net_interface(tcp::endpoint(net_interface.address(), 0))
, m_save_path(complete(p.save_path)) , m_save_path(complete(p.save_path))
, m_storage_constructor(p.storage) , m_storage_constructor(p.storage)
, m_ratio(0.f) , m_ratio(0.f)
@ -381,7 +381,10 @@ namespace libtorrent
, m_last_scrape(0) , m_last_scrape(0)
, m_last_download(0) , m_last_download(0)
, m_last_upload(0) , m_last_upload(0)
, m_interface_index(0)
{ {
m_net_interfaces.push_back(net_interface);
if (p.file_priorities) if (p.file_priorities)
m_file_priority = *p.file_priorities; m_file_priority = *p.file_priorities;
@ -1269,14 +1272,30 @@ namespace libtorrent
files_checked(); files_checked();
} }
void torrent::use_interface(std::string net_interface) void torrent::use_interface(std::string net_interfaces)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
m_net_interfaces.clear();
error_code ec; char* str = &net_interfaces[0];
address a(address::from_string(net_interface.c_str(), ec));
if (ec) return; while (str)
m_net_interface = tcp::endpoint(a, 0); {
char* space = strchr(str, ',');
if (space) *space++ = 0;
error_code ec;
address a(address::from_string(str, ec));
str = space;
if (ec) continue;
m_net_interfaces.push_back(tcp::endpoint(a, 0));
}
}
tcp::endpoint torrent::get_interface() const
{
if (m_net_interfaces.empty()) return tcp::endpoint(address_v4(), 0);
if (m_interface_index >= m_net_interfaces.size()) m_interface_index = 0;
return m_net_interfaces[m_interface_index++];
} }
void torrent::on_tracker_announce_disp(boost::weak_ptr<torrent> p void torrent::on_tracker_announce_disp(boost::weak_ptr<torrent> p