diff --git a/ChangeLog b/ChangeLog index 6449e064b..a2a636fb1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ - * Added more clients to the identifiable list - * Fixed fingerprint parser to cope with latest Mainline versions + * session::listen_on() won't reopen the socket in case the port and + interface is the same as is already open. + * Added http proxy support for web seeds. + * Fixed problem where upload and download stats could become incorrect + in case of high cpu load. + * Added more clients to the identifiable list. + * Fixed fingerprint parser to cope with latest Mainline versions. release 0.10 diff --git a/Makefile.am b/Makefile.am index f276b3dbf..6a5699b74 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,15 @@ SUBDIRS = include @ZLIBDIR@ src examples test EXTRA_DIST = docs/manual.html docs/manual.rst docs/extension_protocol.rst \ docs/extension_protocol.html docs/udp_tracker_protocol.rst \ docs/projects.rst docs/projects.html \ +docs/arctic_thumb.png \ +docs/bitbuddy_thumb.jpg \ +docs/bitslug_thumb.png \ +docs/btg_thumb.jpg \ +docs/moopolice_thumb.gif \ +docs/qbittorrent_thumb.jpg \ +docs/ziptorrent_thumb.gif \ +docs/vs2005_build_notes.html \ +docs/vs2005_build_notes.rst \ docs/udp_tracker_protocol.html docs/client_test.rst docs/client_test.html \ docs/unicode_support.png docs/client_test.png docs/style.css Jamfile project-root.jam \ m4/ac_cxx_namespaces.m4 m4/acx_pthread.m4 m4/ax_boost_date-time.m4 \ diff --git a/configure.in b/configure.in index 5c2895b17..93fb670d5 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ AC_PREREQ(2.59) AC_INIT(src/torrent.cpp) -AM_INIT_AUTOMAKE(libtorrent, 0.10) +AM_INIT_AUTOMAKE(libtorrent, 0.11) AM_CONFIG_HEADER(config.h) diff --git a/docs/manual.html b/docs/manual.html index 9490349b2..219b51a0b 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -18,7 +18,7 @@ Author: Arvid Norberg, arvid@rasterbar.com Version: -0.10 +0.11
@@ -189,7 +189,7 @@ following features:

  • serves multiple torrents on a single port and in a single thread
  • gzipped tracker-responses
  • HTTP seeding, as specified by Michael Burford of GetRight.
  • -
  • piece picking on block-level like in Azureus (as opposed to piece-level). +
  • piece picking on block-level (as opposed to piece-level). This means it can download parts of the same piece from different peers. It will also prefer to download whole pieces from single peers if the download speed is high enough from that particular peer.
  • diff --git a/docs/manual.rst b/docs/manual.rst index d57dabc0a..fd303715d 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3,7 +3,7 @@ libtorrent manual ================= :Author: Arvid Norberg, arvid@rasterbar.com -:Version: 0.10 +:Version: 0.11 .. contents:: Table of contents :depth: 2 @@ -31,7 +31,7 @@ following features: * serves multiple torrents on a single port and in a single thread * gzipped tracker-responses * `HTTP seeding`_, as `specified by Michael Burford of GetRight`__. -* piece picking on block-level like in Azureus_ (as opposed to piece-level). +* piece picking on block-level (as opposed to piece-level). This means it can download parts of the same piece from different peers. It will also prefer to download whole pieces from single peers if the download speed is high enough from that particular peer. @@ -67,7 +67,6 @@ following features: __ http://home.elp.rr.com/tur/multitracker-spec.txt __ http://www.getright.com/seedtorrent.html -.. _Azureus: http://azureus.sourceforge.net __ extension_protocol.html __ udp_tracker_protocol.html diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 57aac294a..abce44b10 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -425,6 +425,8 @@ int main(int ac, char* av[]) std::string allocation_mode; std::string in_monitor_dir; std::string bind_to_interface; + std::string proxy; + std::string proxy_login; int poll_interval; namespace po = boost::program_options; @@ -469,6 +471,13 @@ int main(int ac, char* av[]) ("bind,b", po::value(&bind_to_interface)->default_value("") , "Sets the local interface to bind outbound and the listen " "socket to") + ("proxy-server,x", po::value(&proxy)->default_value("") + , "Sets the http proxy to be used for tracker and web seeds " + "connections. The string is expected to be on the form: " + ":. If no port is specified, 8080 is assumed") + ("proxy-login,o", po::value(&proxy_login)->default_value("") + , "Sets the username and password used to authenticate with the http " + "proxy. The string should be given in the form: :") ; po::positional_options_description p; @@ -511,6 +520,38 @@ int main(int ac, char* av[]) input = vm["input-file"].as< std::vector >(); session_settings settings; + + if (!proxy.empty()) + { + try + { + std::size_t i = proxy.find(':'); + settings.proxy_ip = proxy.substr(0, i); + if (i == std::string::npos) settings.proxy_port = 8080; + else settings.proxy_port = boost::lexical_cast( + proxy.substr(i + 1)); + } + catch (std::exception&) + { + std::cerr << "Proxy hostname did not match the required format: " + << proxy << std::endl; + return 1; + } + + if (!proxy_login.empty()) + { + std::size_t i = proxy_login.find(':'); + if (i == std::string::npos) + { + std::cerr << "Proxy login did not match the required format: " + << proxy_login << std::endl; + return 1; + } + settings.proxy_login = proxy_login.substr(0, i); + settings.proxy_password = proxy_login.substr(i + 1); + } + } + settings.user_agent = "client_test " LIBTORRENT_VERSION; settings.sequenced_download_threshold = 15; diff --git a/include/libtorrent/version.hpp b/include/libtorrent/version.hpp index abac9267d..25c7a9f05 100755 --- a/include/libtorrent/version.hpp +++ b/include/libtorrent/version.hpp @@ -34,8 +34,8 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_VERSION_HPP_INCLUDED #define LIBTORRENT_VERSION_MAJOR 0 -#define LIBTORRENT_VERSION_MINOR 10 +#define LIBTORRENT_VERSION_MINOR 11 -#define LIBTORRENT_VERSION "0.10.0.0" +#define LIBTORRENT_VERSION "0.11.0.0" #endif diff --git a/include/libtorrent/web_peer_connection.hpp b/include/libtorrent/web_peer_connection.hpp index 7001fe623..5026765b5 100755 --- a/include/libtorrent/web_peer_connection.hpp +++ b/include/libtorrent/web_peer_connection.hpp @@ -128,7 +128,6 @@ namespace libtorrent #ifndef NDEBUG void check_invariant() const; - boost::posix_time::ptime m_last_choke; #endif private: diff --git a/src/session.cpp b/src/session.cpp index 62395252b..fdcb75bd1 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -1054,7 +1054,6 @@ namespace libtorrent { namespace detail i != m_half_open.end(); ++i) { assert(i->second->is_connecting()); -// assert(m_selector.is_writability_monitored(i->second->get_socket())); } for (connection_map::iterator i = m_connections.begin(); @@ -1062,14 +1061,10 @@ namespace libtorrent { namespace detail { assert(i->second); assert(!i->second->is_connecting()); - if (i->second->is_connecting() -/* || i->second->can_write() != m_selector.is_writability_monitored(i->first) - || i->second->can_read() != m_selector.is_readability_monitored(i->first)*/) + if (i->second->is_connecting()) { std::ofstream error_log("error.log", std::ios_base::app); boost::intrusive_ptr p = i->second; -// error_log << "selector::is_writability_monitored() " << m_selector.is_writability_monitored(i->first) << "\n"; -// error_log << "selector::is_readability_monitored() " << m_selector.is_readability_monitored(i->first) << "\n"; error_log << "peer_connection::is_connecting() " << p->is_connecting() << "\n"; error_log << "peer_connection::can_write() " << p->can_write() << "\n"; error_log << "peer_connection::can_read() " << p->can_read() << "\n"; @@ -1396,16 +1391,24 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_impl.m_mutex); + tcp::endpoint new_interface; + if (net_interface && std::strlen(net_interface) > 0) + new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first); + else + new_interface = tcp::endpoint(address(), port_range.first); + + m_impl.m_listen_port_range = port_range; + + // if the interface is the same and the socket is open + // don't do anything + if (new_interface == m_impl.m_listen_interface + && m_impl.m_listen_socket) return true; + if (m_impl.m_listen_socket) m_impl.m_listen_socket.reset(); m_impl.m_incoming_connection = false; - - m_impl.m_listen_port_range = port_range; - if (net_interface && std::strlen(net_interface) > 0) - m_impl.m_listen_interface = tcp::endpoint(address::from_string(net_interface), port_range.first); - else - m_impl.m_listen_interface = tcp::endpoint(address(), port_range.first); + m_impl.m_listen_interface = new_interface; m_impl.open_listen_port(); return m_impl.m_listen_socket; diff --git a/src/torrent.cpp b/src/torrent.cpp index f7efde16e..765e09e6e 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -960,10 +960,20 @@ namespace libtorrent = parse_url_components(url); m_resolving_web_seeds.insert(url); - tcp::resolver::query q(hostname, "0"); - - m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup - , shared_from_this(), _1, _2, port, url)); + if (m_ses.m_settings.proxy_ip.empty()) + { + tcp::resolver::query q(hostname, "0"); + m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup + , shared_from_this(), _1, _2, port, url)); + } + else + { + // use proxy + tcp::resolver::query q(m_ses.m_settings.proxy_ip, "0"); + m_host_resolver.async_resolve(q, bind(&torrent::on_name_lookup + , shared_from_this(), _1, _2, m_ses.m_settings.proxy_port, url)); + } + } void torrent::on_name_lookup(asio::error const& e, tcp::resolver::iterator host diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 43a9f70bf..9ca5a5846 100755 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -138,10 +138,15 @@ namespace libtorrent m_requests.push_back(r); + bool using_proxy = false; + if (!m_ses.m_settings.proxy_ip.empty()) + using_proxy = true; + if (single_file_request) { request += "GET "; - request += escape_path(m_path.c_str(), m_path.length()); + if (using_proxy) request += m_url; + else request += escape_path(m_path.c_str(), m_path.length()); request += " HTTP/1.1\r\n"; request += "Host: "; request += m_host; @@ -151,13 +156,23 @@ namespace libtorrent request += escape_string(m_ses.m_settings.user_agent.c_str() , m_ses.m_settings.user_agent.size()); } + if (using_proxy && !m_ses.m_settings.proxy_login.empty()) + { + request += "\r\nProxy-Authorization: Basic "; + request += base64encode(m_ses.m_settings.proxy_login + ":" + + m_ses.m_settings.proxy_password); + } + if (using_proxy) + { + request += "\r\nProxy-Connection: keep-alive"; + } request += "\r\nRange: bytes="; request += boost::lexical_cast(r.piece * info.piece_length() + r.start); request += "-"; request += boost::lexical_cast(r.piece * info.piece_length() + r.start + r.length - 1); - if (m_first_request) + if (m_first_request || using_proxy) request += "\r\nConnection: keep-alive"; request += "\r\n\r\n"; m_first_request = false; @@ -173,10 +188,19 @@ namespace libtorrent { file_slice const& f = *i; - std::string path = m_path; - path += info.file_at(f.file_index).path.string(); request += "GET "; - request += escape_path(path.c_str(), path.length()); + if (using_proxy) + { + request += m_url; + std::string path = info.file_at(f.file_index).path.string(); + request += escape_path(path.c_str(), path.length()); + } + else + { + std::string path = m_path; + path += info.file_at(f.file_index).path.string(); + request += escape_path(path.c_str(), path.length()); + } request += " HTTP/1.1\r\n"; request += "Host: "; request += m_host; @@ -186,11 +210,21 @@ namespace libtorrent request += escape_string(m_ses.m_settings.user_agent.c_str() , m_ses.m_settings.user_agent.size()); } + if (using_proxy && !m_ses.m_settings.proxy_login.empty()) + { + request += "\r\nProxy-Authorization: Basic "; + request += base64encode(m_ses.m_settings.proxy_login + ":" + + m_ses.m_settings.proxy_password); + } + if (using_proxy) + { + request += "\r\nProxy-Connection: keep-alive"; + } request += "\r\nRange: bytes="; request += boost::lexical_cast(f.offset); request += "-"; request += boost::lexical_cast(f.offset + f.size - 1); - if (m_first_request) + if (m_first_request || using_proxy) request += "\r\nConnection: keep-alive"; request += "\r\n\r\n"; m_first_request = false;