From 2d363127e93024dd4902d0432bc5e933ec01492e Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 26 Feb 2004 00:27:06 +0000 Subject: [PATCH] *** empty log message *** --- Jamfile | 21 +++---------- docs/manual.rst | 25 +++++++++++----- examples/client_test.cpp | 5 +++- include/libtorrent/session.hpp | 16 +++++++--- include/libtorrent/socket.hpp | 28 ++++++++++++----- include/libtorrent/stat.hpp | 3 ++ include/libtorrent/torrent.hpp | 5 +++- include/libtorrent/torrent_handle.hpp | 4 +++ src/allocate_resources.cpp | 2 +- src/http_tracker_connection.cpp | 2 +- src/policy.cpp | 2 +- src/session.cpp | 43 +++++++++++++++++---------- src/torrent.cpp | 13 ++++++-- src/torrent_handle.cpp | 31 ++++++++++++++++++- src/udp_tracker_connection.cpp | 2 +- 15 files changed, 139 insertions(+), 63 deletions(-) diff --git a/Jamfile b/Jamfile index e23477f33..577fcdd6b 100755 --- a/Jamfile +++ b/Jamfile @@ -13,14 +13,6 @@ use-project /boost/date_time : $(BOOST_ROOT)/libs/date_time/build ; project torrent : requirements - /boost/thread - /boost/date_time - /boost/filesystem - - /boost/thread - /boost/date_time - /boost/filesystem - : usage-requirements ./include @@ -49,6 +41,7 @@ SOURCES = piece_picker.cpp policy.cpp session.cpp + socket.cpp stat.cpp storage.cpp torrent.cpp @@ -63,15 +56,6 @@ SOURCES = # use different versions of some files for # windows - if [ modules.peek : NT ] - { - SOURCES += socket_win.cpp ; - } - else - { - SOURCES += socket_bsd.cpp ; - } - if [ modules.peek : NT ] && toolset != msvc-6 { SOURCES += file_win.cpp ; @@ -86,6 +70,9 @@ lib torrent : zlib//zlib src/$(SOURCES) + /boost/thread//boost_thread/shared + /boost/date_time//boost_date_time/static + /boost/filesystem//boost_filesystem/static : ./include multi diff --git a/docs/manual.rst b/docs/manual.rst index 0b3595455..717f5b7e0 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -69,11 +69,11 @@ libtorrent has been successfully compiled and tested on: * Windows 2000 vc7.1 * Linux x86 (debian) GCC 3.0.4, GCC 3.2.3 * Windows 2000, msvc6 sp5 (does not support 64-bit values due to problems with operator<<(ostream&, __int64)) - * Cygwin GCC 3.3.1 Fails on: * GCC 2.95.4 (``std::ios_base`` is missing) + * Cygwin GCC 3.3.1 (builds but crashes) libtorrent is released under the BSD-license_. @@ -116,11 +116,7 @@ version of boost, `boost 1.30.2`__. __ http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=8041&release_id=178835 -There are two versions of the socket code, one that works with unix systems (and bsd-sockets) and -one that uses winsock. If you're building in windows, the file ``socket_win.cpp`` is supposed to -be included in the build while ``socket_bsd.cpp`` is supposed to be excluded. - -The file abstraction has the same kind of separation. There's one ``file_win.cpp`` which +There are two versions of the file abstraction. There's one ``file_win.cpp`` which relies on windows file API that supports files larger than 2 Gigabytes. This does not work in vc6 for some reason, possibly because it may require windows NT and above. The other file, ``file.cpp`` is the default implementation that simply relies on the standard library's fstream, @@ -189,8 +185,12 @@ The ``session`` class has the following synopsis:: class session: public boost::noncopyable { - session(std::pair listen_port_range, const fingerprint& print); + session(std::pair listen_port_range); + session( + std::pair listen_port_range + , const fingerprint& print + , const char* listen_interface = 0); torrent_handle add_torrent( const torrent_info& t @@ -250,7 +250,11 @@ increase the port number by one and try again. If it still fails it will continu increasing the port number until it succeeds or has reached the end of the range. If it fails with all ports, a listen_failed_alert_ will be posted and the session thread will exit. The only thing you can do with your session if this alert is posted is to destruct -it and possibly try again or change the port range. +it and possibly try again or change the port range. The listen interaface string is +the name (ip address) of the interface you want to listen on. If this is left as +0, the os will decide which interface to listen on (works in most cases). All torrents +will use this interface to open outgoing connections on by default. You can change +which interface to use for outgoing connections on a per torrent basis. See torrent_handle_. For information about the ``pop_alert()`` function, see alerts_. @@ -527,6 +531,8 @@ Its declaration looks like this:: void set_tracker_login(std::string const& username, std::string const& password); + void use_interface(const char* net_interface); + boost::filsystem::path save_path() const; void set_max_uploads(int max_uploads); @@ -568,6 +574,9 @@ as a standard client. ``set_tracker_login()`` sets a username and password that will be sent along in the HTTP-request of the tracker announce. Set this if the tracker requires authorization. +``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. + ``info_hash()`` returns the info hash for the torrent. ``set_max_uploads()`` sets the maximum number of peers that's unchoked at the same time on this diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 906aff20b..8be328928 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -240,7 +240,10 @@ int main(int argc, char* argv[]) try { std::vector handles; - session ses(std::make_pair(6881, 6889)); + session ses( + std::make_pair(6881, 6889) + , fingerprint("LT", 0, 1, 0, 0) + , "192.168.0.1"); ses.set_upload_rate_limit(20 * 1024); ses.set_http_settings(settings); diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index e94781078..e30805c04 100755 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -159,7 +159,8 @@ namespace libtorrent session_impl( std::pair listen_port_range - , const fingerprint& cl_fprint); + , const fingerprint& cl_fprint + , const char* listen_interface); void operator()(); @@ -189,8 +190,12 @@ namespace libtorrent // the range of ports we try to listen on std::pair m_listen_port_range; - // the port we are listening on for connections - int m_listen_port; + // the ip-address of the interface + // we are supposed to listen on. + // if the ip is set to zero, it means + // that we should let the os decide which + // interface to listen on + address m_listen_interface; // this is where all active sockets are stored. // the selector can sleep while there's no activity on @@ -238,8 +243,11 @@ namespace libtorrent { public: - session(std::pair listen_port_range, const fingerprint& print); session(std::pair listen_port_range); + session( + std::pair listen_port_range + , const fingerprint& print + , const char* listen_interface = 0); ~session(); diff --git a/include/libtorrent/socket.hpp b/include/libtorrent/socket.hpp index 7463c8d72..d0cffe547 100755 --- a/include/libtorrent/socket.hpp +++ b/include/libtorrent/socket.hpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -51,6 +52,9 @@ POSSIBILITY OF SUCH DAMAGE. #include // TODO: support ToS +// TODO: support binding to selected interface +// Distinguish between binding listen sockets and +// outgoing connections. namespace libtorrent { @@ -60,6 +64,8 @@ namespace libtorrent public: network_error(int error_code): m_error_code(error_code) {} virtual const char* what() const throw(); + int error_code() const + { return m_error_code; } private: int m_error_code; }; @@ -80,25 +86,28 @@ namespace libtorrent address(unsigned int addr, unsigned short port); - address(const std::string& addr, unsigned short port); + address(const char* addr, unsigned short port); address(const address& a); ~address(); std::string as_string() const; unsigned int ip() const { return m_ip; } - unsigned short port() const { return m_port; } bool operator<(const address& a) const - { if (ip() == a.ip()) return port() < a.port(); else return ip() < a.ip(); } + { if (ip() == a.ip()) return port < a.port; else return ip() < a.ip(); } bool operator!=(const address& a) const - { return ip() != a.ip() || port() != a.port(); } + { return ip() != a.ip() || port != a.port; } bool operator==(const address& a) const - { return ip() == a.ip() && port() == a.port(); } + { return ip() == a.ip() && port == a.port; } + + unsigned short port; + + const static unsigned short any_port = 0; + const static unsigned int any_addr = 0; private: unsigned int m_ip; - unsigned short m_port; }; class socket: public boost::noncopyable @@ -116,7 +125,10 @@ namespace libtorrent socket(type t, bool blocking = true, unsigned short receive_port = 0); virtual ~socket(); - void connect(const address& addr); + void connect( + const address& addr + , address const& bind_to + = address(address::any_addr, address::any_port)); void close(); void set_blocking(bool blocking); @@ -125,7 +137,7 @@ namespace libtorrent const address& sender() const { return m_sender; } address name() const; - void listen(unsigned short port, int queue); + void listen(libtorrent::address const& iface, int queue); boost::shared_ptr accept(); template int send(const T& buffer); diff --git a/include/libtorrent/stat.hpp b/include/libtorrent/stat.hpp index 6e22cda3d..6cc9eac66 100755 --- a/include/libtorrent/stat.hpp +++ b/include/libtorrent/stat.hpp @@ -124,6 +124,9 @@ namespace libtorrent size_type total_protocol_upload() const { return m_total_upload_protocol; } size_type total_protocol_download() const { return m_total_download_protocol; } + // this is used to offset the statistics when a + // peer_connection is opened and have some previous + // transfers from earlier connections. void add_stat(size_type downloaded, size_type uploaded) { m_total_download_payload += downloaded; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ff9f2d6c2..9eda49cd9 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -86,7 +86,8 @@ namespace libtorrent torrent( detail::session_impl& ses , const torrent_info& torrent_file - , const boost::filesystem::path& save_path); + , const boost::filesystem::path& save_path + , address const& net_interface); ~torrent(); @@ -122,6 +123,7 @@ namespace libtorrent torrent_status status() const; + void use_interface(const char* net_interface); peer_connection& connect_to_peer(const address& a); const torrent_info& torrent_file() const @@ -357,6 +359,7 @@ namespace libtorrent std::string m_username; std::string m_password; + address m_net_interface; }; } diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 5446ef490..2bd415af9 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -151,6 +151,10 @@ namespace libtorrent const torrent_info& get_torrent_info() const; bool is_valid() const; + // set the interface to bind outgoing connections + // to. + void use_interface(const char* net_interface); + // TODO: there must be a way to get resume data and // shut down the torrent in one atomic operation entry write_resume_data() const; diff --git a/src/allocate_resources.cpp b/src/allocate_resources.cpp index 01123f319..97320af63 100644 --- a/src/allocate_resources.cpp +++ b/src/allocate_resources.cpp @@ -341,4 +341,4 @@ namespace libtorrent } } -} \ No newline at end of file +} diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index 8a424bacf..e48680628 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -108,7 +108,7 @@ namespace libtorrent // TODO: this is a problem. DNS-lookup is blocking! // (may block up to 5 seconds) - address a(*connect_to_host, port); + address a(connect_to_host->c_str(), port); boost::shared_ptr s(new socket(socket::tcp, false)); s->connect(a); diff --git a/src/policy.cpp b/src/policy.cpp index d75409ee4..23fdf2a4a 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -733,7 +733,7 @@ namespace libtorrent void policy::peer_from_tracker(const address& remote, const peer_id& id) { // just ignore the obviously invalid entries from the tracker - if(remote.ip() == 0 || remote.port() == 0) + if(remote.ip() == 0 || remote.port == 0) return; try diff --git a/src/session.cpp b/src/session.cpp index 77ccf3400..5806b8617 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -248,18 +248,20 @@ namespace libtorrent return 0; } - session_impl::session_impl(std::pair listen_port_range, - const fingerprint& cl_fprint) + session_impl::session_impl( + std::pair listen_port_range + , const fingerprint& cl_fprint + , const char* listen_interface = 0) : m_tracker_manager(m_settings) , m_listen_port_range(listen_port_range) - , m_listen_port(listen_port_range.first) + , m_listen_interface(listen_interface, listen_port_range.first) , m_abort(false) , m_upload_rate(-1) , m_incoming_connection(false) { assert(listen_port_range.first > 0); assert(listen_port_range.first < listen_port_range.second); - assert(m_listen_port > 0); + assert(m_listen_interface.port > 0); // ---- generate a peer id ---- @@ -309,12 +311,18 @@ namespace libtorrent { try { - listener->listen(m_listen_port, 5); + listener->listen(m_listen_interface, 10); } - catch (std::exception&) + catch (network_error& e) { - m_listen_port++; - if (m_listen_port > m_listen_port_range.second) + if (e.error_code() == socket::address_not_available) + { + std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'"; + m_alerts.post_alert(listen_failed_alert(msg)); + return; + } + m_listen_interface.port++; + if (m_listen_interface.port > m_listen_port_range.second) { m_alerts.post_alert(listen_failed_alert( "none of the ports in the given range could be opened")); @@ -326,7 +334,7 @@ namespace libtorrent } #ifndef NDEBUG - (*m_logger) << "listening on port: " << m_listen_port << "\n"; + (*m_logger) << "listening on port: " << m_listen_interface.port << "\n"; #endif m_selector.monitor_readability(listener); m_selector.monitor_errors(listener); @@ -376,7 +384,7 @@ namespace libtorrent ++i) { i->second->abort(); - m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_port)); + m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_interface.port)); } m_connections.clear(); m_torrents.clear(); @@ -621,7 +629,7 @@ namespace libtorrent if (i->second->is_aborted()) { m_tracker_manager.queue_request( - i->second->generate_tracker_request(m_listen_port)); + i->second->generate_tracker_request(m_listen_interface.port)); i->second->disconnect_all(); #ifndef NDEBUG sha1_hash i_hash = i->second->torrent_file().info_hash(); @@ -635,7 +643,7 @@ namespace libtorrent else if (i->second->should_request()) { m_tracker_manager.queue_request( - i->second->generate_tracker_request(m_listen_port) + i->second->generate_tracker_request(m_listen_interface.port) , boost::get_pointer(i->second)); } @@ -740,8 +748,11 @@ namespace libtorrent } - session::session(std::pair listen_port_range, const fingerprint& id) - : m_impl(listen_port_range, id) + session::session( + std::pair listen_port_range + , const fingerprint& id + , const char* listen_interface) + : m_impl(listen_port_range, id, listen_interface) , m_checker_impl(m_impl) , m_thread(boost::ref(m_impl)) , m_checker_thread(boost::ref(m_checker_impl)) @@ -802,7 +813,7 @@ namespace libtorrent // the checker thread and store it before starting // the thread boost::shared_ptr torrent_ptr( - new torrent(m_impl, ti, save_path)); + new torrent(m_impl, ti, save_path, m_impl.m_listen_interface)); detail::piece_checker_data d; d.torrent_ptr = torrent_ptr; @@ -943,7 +954,7 @@ namespace libtorrent ++i) { address a( - i->dict()["ip"].string() + i->dict()["ip"].string().c_str() , (unsigned short)i->dict()["port"].integer()); tmp_peers.push_back(a); } diff --git a/src/torrent.cpp b/src/torrent.cpp index e11bd422a..1f5eeb3d4 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -216,7 +216,8 @@ namespace libtorrent torrent::torrent( detail::session_impl& ses , const torrent_info& torrent_file - , const boost::filesystem::path& save_path) + , const boost::filesystem::path& save_path + , address const& net_interface) : m_block_size(calculate_block_size(torrent_file)) , m_abort(false) , m_event(tracker_request::started) @@ -235,6 +236,7 @@ namespace libtorrent , m_num_pieces(0) , m_got_tracker_response(false) , m_ratio(0.f) + , m_net_interface(net_interface) { assert(torrent_file.begin_files() != torrent_file.end_files()); m_have_pieces.resize(torrent_file.num_pieces(), false); @@ -245,6 +247,11 @@ namespace libtorrent if (m_ses.m_abort) m_abort = true; } + void torrent::use_interface(const char* net_interface) + { + m_net_interface = address(net_interface, address::any_port); + } + void torrent::tracker_response( std::vector& peer_list , int interval) @@ -290,7 +297,7 @@ namespace libtorrent if (i->id == m_ses.get_peer_id()) continue; - address a(i->ip, i->port); + address a(i->ip.c_str(), i->port); m_policy->peer_from_tracker(a, i->id); } @@ -530,7 +537,7 @@ namespace libtorrent peer_connection& torrent::connect_to_peer(const address& a) { boost::shared_ptr s(new socket(socket::tcp, false)); - s->connect(a); + s->connect(a, m_net_interface); boost::shared_ptr c(new peer_connection( m_ses , m_ses.m_selector diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index af1d3d754..36648b59a 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -102,6 +102,35 @@ namespace libtorrent throw invalid_handle(); } + void torrent_handle::use_interface(const char* net_interface) + { + if (m_ses == 0) throw invalid_handle(); + + { + boost::mutex::scoped_lock l(m_ses->m_mutex); + torrent* t = m_ses->find_torrent(m_info_hash); + if (t != 0) + { + t->use_interface(net_interface); + return; + } + } + + + if (m_chk) + { + boost::mutex::scoped_lock l(m_chk->m_mutex); + + detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash); + if (d != 0) + { + d->torrent_ptr->use_interface(net_interface); + return; + } + } + throw invalid_handle(); + } + void torrent_handle::set_max_connections(int max_connections) { assert(max_connections > 2 || max_connections == -1); @@ -320,7 +349,7 @@ namespace libtorrent address ip = i->second->get_socket()->sender(); entry::dictionary_type peer; peer["ip"] = ip.as_string(); - peer["port"] = ip.port(); + peer["port"] = ip.port; peer_list.push_back(peer); } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 505391600..16f87af3a 100755 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -73,7 +73,7 @@ namespace libtorrent { // TODO: this is a problem. DNS-lookup is blocking! // (may block up to 5 seconds) - address a(hostname, port); + address a(hostname.c_str(), port); m_socket.reset(new socket(socket::udp, false)); m_socket->connect(a);