diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp index a1dcf4364..02b11e071 100755 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ b/libtorrent/include/libtorrent/alert_types.hpp @@ -58,10 +58,12 @@ namespace libtorrent tracker_alert(torrent_handle const& h , int times , int status + , std::string const& url_ , std::string const& msg) : torrent_alert(h, alert::warning, msg) , times_in_row(times) , status_code(status) + , url(url_) {} virtual std::auto_ptr clone() const @@ -69,6 +71,7 @@ namespace libtorrent int times_in_row; int status_code; + std::string url; }; struct TORRENT_EXPORT tracker_warning_alert: torrent_alert diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index 0953cc320..9cf035e4b 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -132,7 +132,6 @@ struct bandwidth_manager bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const { - TORRENT_ASSERT(l.locked()); for (typename history_t::const_iterator i = m_history.begin(), end(m_history.end()); i != end; ++i) { @@ -265,7 +264,6 @@ private: void hand_out_bandwidth(boost::mutex::scoped_lock& l) { - TORRENT_ASSERT(l.locked()); // if we're already handing out bandwidth, just return back // to the loop further down on the callstack if (m_in_hand_out_bandwidth) return; diff --git a/libtorrent/include/libtorrent/bt_peer_connection.hpp b/libtorrent/include/libtorrent/bt_peer_connection.hpp index dc5237a7d..d07dcb2dd 100755 --- a/libtorrent/include/libtorrent/bt_peer_connection.hpp +++ b/libtorrent/include/libtorrent/bt_peer_connection.hpp @@ -100,6 +100,7 @@ namespace libtorrent bt_peer_connection( aux::session_impl& ses , boost::shared_ptr s + , tcp::endpoint const& remote , policy::peer* peerinfo); ~bt_peer_connection(); diff --git a/libtorrent/include/libtorrent/entry.hpp b/libtorrent/include/libtorrent/entry.hpp index 7238af37e..eb4aafe34 100755 --- a/libtorrent/include/libtorrent/entry.hpp +++ b/libtorrent/include/libtorrent/entry.hpp @@ -167,6 +167,8 @@ namespace libtorrent #endif entry* find_key(char const* key); entry const* find_key(char const* key) const; + entry* find_key(std::string const& key); + entry const* find_key(std::string const& key) const; void print(std::ostream& os, int indent = 0) const; diff --git a/libtorrent/include/libtorrent/http_connection.hpp b/libtorrent/include/libtorrent/http_connection.hpp index b65b303ae..3ec5b3494 100644 --- a/libtorrent/include/libtorrent/http_connection.hpp +++ b/libtorrent/include/libtorrent/http_connection.hpp @@ -52,7 +52,7 @@ namespace libtorrent struct http_connection; typedef boost::function http_handler; + , http_parser const&, char const* data, int size, http_connection&)> http_handler; typedef boost::function http_connect_handler; @@ -136,6 +136,7 @@ private: bool m_called; std::string m_hostname; std::string m_port; + std::string m_url; // the current download limit, in bytes per second // 0 is unlimited. diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp index 97d76a3d1..69545fd76 100755 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -120,6 +120,7 @@ namespace libtorrent peer_connection( aux::session_impl& ses , boost::shared_ptr s + , tcp::endpoint const& remote , policy::peer* peerinfo); virtual ~peer_connection(); diff --git a/libtorrent/include/libtorrent/peer_id.hpp b/libtorrent/include/libtorrent/peer_id.hpp index a546c6e08..e35775544 100755 --- a/libtorrent/include/libtorrent/peer_id.hpp +++ b/libtorrent/include/libtorrent/peer_id.hpp @@ -141,6 +141,9 @@ namespace libtorrent iterator begin() { return m_number; } iterator end() { return m_number+number_size; } + std::string to_string() const + { return std::string((char const*)&m_number[0], number_size); } + private: unsigned char m_number[number_size]; diff --git a/libtorrent/include/libtorrent/socket.hpp b/libtorrent/include/libtorrent/socket.hpp index 499842dd7..90d15e73d 100755 --- a/libtorrent/include/libtorrent/socket.hpp +++ b/libtorrent/include/libtorrent/socket.hpp @@ -95,6 +95,7 @@ namespace libtorrent typedef asio::io_service io_service; using asio::async_write; + using asio::error_code; typedef asio::basic_deadline_timer deadline_timer; diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp index 983e9fa4d..f4d364e66 100644 --- a/libtorrent/include/libtorrent/time.hpp +++ b/libtorrent/include/libtorrent/time.hpp @@ -255,7 +255,7 @@ namespace libtorrent #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#include +#include #include "libtorrent/assert.hpp" namespace libtorrent diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index 1d0f8d425..36d3ced4c 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -94,13 +94,14 @@ private: struct rootdevice; void on_upnp_xml(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d); + , libtorrent::http_parser const& p, rootdevice& d + , http_connection& c); void on_upnp_map_response(asio::error_code const& e , libtorrent::http_parser const& p, rootdevice& d - , int mapping); + , int mapping, http_connection& c); void on_upnp_unmap_response(asio::error_code const& e , libtorrent::http_parser const& p, rootdevice& d - , int mapping); + , int mapping, http_connection& c); void on_expire(asio::error_code const& e); void map_port(rootdevice& d, int i); diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index d70e7af31..ecce02ba2 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -125,8 +125,9 @@ namespace libtorrent bt_peer_connection::bt_peer_connection( session_impl& ses , boost::shared_ptr s + , tcp::endpoint const& remote , policy::peer* peerinfo) - : peer_connection(ses, s, peerinfo) + : peer_connection(ses, s, remote, peerinfo) , m_state(read_protocol_identifier) #ifndef TORRENT_DISABLE_EXTENSIONS , m_supports_extensions(false) diff --git a/libtorrent/src/entry.cpp b/libtorrent/src/entry.cpp index c3e91044a..2688c491d 100755 --- a/libtorrent/src/entry.cpp +++ b/libtorrent/src/entry.cpp @@ -54,19 +54,6 @@ namespace TORRENT_ASSERT(o); o->~T(); } - - struct compare_string - { - compare_string(char const* s): m_str(s) {} - - bool operator()( - std::pair const& e) const - { - return m_str && e.first == m_str; - } - char const* m_str; - }; } namespace libtorrent @@ -94,6 +81,16 @@ namespace libtorrent } entry& entry::operator[](char const* key) + { + dictionary_type::iterator i = dict().find(key); + if (i != dict().end()) return i->second; + dictionary_type::iterator ret = dict().insert( + dict().begin() + , std::make_pair(key, entry())); + return ret->second; + } + + entry& entry::operator[](std::string const& key) { dictionary_type::iterator i = dict().find(key); if (i != dict().end()) return i->second; @@ -103,21 +100,11 @@ namespace libtorrent return ret->second; } - - entry& entry::operator[](std::string const& key) - { - return (*this)[key.c_str()]; - } - entry* entry::find_key(char const* key) { - dictionary_type::iterator i = std::find_if( - dict().begin() - , dict().end() - , compare_string(key)); + dictionary_type::iterator i = dict().find(key); if (i == dict().end()) return 0; return &i->second; - } entry const* entry::find_key(char const* key) const @@ -127,6 +114,20 @@ namespace libtorrent return &i->second; } + entry* entry::find_key(std::string const& key) + { + dictionary_type::iterator i = dict().find(key); + if (i == dict().end()) return 0; + return &i->second; + } + + entry const* entry::find_key(std::string const& key) const + { + dictionary_type::const_iterator i = dict().find(key); + if (i == dict().end()) return 0; + return &i->second; + } + #ifndef BOOST_NO_EXCEPTIONS const entry& entry::operator[](char const* key) const { diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index 92db5c485..45ae7b7f3 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -61,6 +61,7 @@ void http_connection::get(std::string const& url, time_duration timeout headers << "Authorization: Basic " << base64encode(auth) << "\r\n"; headers << "\r\n"; sendbuffer = headers.str(); + m_url = url; start(hostname, boost::lexical_cast(port), timeout, handle_redirects); } @@ -190,7 +191,7 @@ void http_connection::callback(asio::error_code const& e, char const* data, int if (!m_bottled || !m_called) { m_called = true; - if (m_handler) m_handler(e, m_parser, data, size); + if (m_handler) m_handler(e, m_parser, data, size, *this); } } @@ -269,8 +270,8 @@ void http_connection::on_read(asio::error_code const& e catch (std::exception&) { m_timer.cancel(); - m_handler(asio::error::fault, m_parser, 0, 0); - m_handler.clear(); + callback(asio::error::fault, 0, 0); + close(); return; } @@ -282,17 +283,50 @@ void http_connection::on_read(asio::error_code const& e if (code >= 300 && code < 400) { // attempt a redirect - std::string const& url = m_parser.header("location"); - if (url.empty()) + std::string const& location = m_parser.header("location"); + if (location.empty()) { // missing location header - callback(e); + callback(asio::error::fault); + close(); return; } - asio::error_code ec; - m_sock.close(ec); - get(url, m_timeout, m_redirects - 1); + try + { + asio::error_code ec; + m_sock.close(ec); + get(location, m_timeout, m_redirects - 1); + return; + } + catch (std::exception& e) + { + // some broken web servers send out relative paths + // in the location header. + std::string url = m_url; + // remove the leaf filename + std::size_t i = url.find_last_of('/'); + if (i == std::string::npos) + { + url += '/'; + } + else + { + url.resize(i + 1); + } + url += location; + + try + { + get(url, m_timeout, m_redirects - 1); + } + catch (std::exception& e) + { + // location header is invalid + callback(asio::error::fault); + close(); + } + } return; } diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp index d99c6f94a..9fa870ed7 100755 --- a/libtorrent/src/http_tracker_connection.cpp +++ b/libtorrent/src/http_tracker_connection.cpp @@ -904,9 +904,7 @@ namespace libtorrent if (tracker_req().kind == tracker_request::scrape_request) { - std::string ih; - std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end() - , std::back_inserter(ih)); + std::string ih = tracker_req().info_hash.to_string(); entry scrape_data = e["files"][ih]; int complete = -1; diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 60dfa2d20..60811909f 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -403,7 +403,7 @@ void node_impl::on_announce(msg const& m, msg& reply) torrent_entry& v = m_map[m.info_hash]; peer_entry e; - e.addr = tcp::endpoint(m.addr.address(), m.addr.port()); + e.addr = tcp::endpoint(m.addr.address(), m.port); e.added = time_now(); std::set::iterator i = v.peers.find(e); if (i != v.peers.end()) v.peers.erase(i++); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 9ae19b6ac..e2df0cc37 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -65,7 +65,7 @@ namespace libtorrent session_impl& ses , boost::weak_ptr tor , shared_ptr s - , tcp::endpoint const& remote + , tcp::endpoint const& endp , policy::peer* peerinfo) : #ifndef NDEBUG @@ -85,7 +85,7 @@ namespace libtorrent , m_last_receive(time_now()) , m_last_sent(time_now()) , m_socket(s) - , m_remote(remote) + , m_remote(endp) , m_torrent(tor) , m_active(true) , m_peer_interested(false) @@ -145,6 +145,7 @@ namespace libtorrent peer_connection::peer_connection( session_impl& ses , boost::shared_ptr s + , tcp::endpoint const& endp , policy::peer* peerinfo) : #ifndef NDEBUG @@ -164,6 +165,7 @@ namespace libtorrent , m_last_receive(time_now()) , m_last_sent(time_now()) , m_socket(s) + , m_remote(endp) , m_active(false) , m_peer_interested(false) , m_peer_choked(true) @@ -209,8 +211,9 @@ namespace libtorrent m_remote = m_socket->remote_endpoint(); #ifdef TORRENT_VERBOSE_LOGGING - TORRENT_ASSERT(m_socket->remote_endpoint() == remote()); - m_logger = m_ses.create_log(remote().address().to_string() + "_" + error_code ec; + TORRENT_ASSERT(m_socket->remote_endpoint(ec) == remote()); + m_logger = m_ses.create_log(remote().address().to_string(ec) + "_" + boost::lexical_cast(remote().port()), m_ses.listen_port()); (*m_logger) << "*** INCOMING CONNECTION\n"; #endif @@ -1434,10 +1437,8 @@ namespace libtorrent if (t->alerts().should_post(alert::fatal)) { - if (j.str != "write failed: No space left on device"){ - std::string err = "torrent paused: disk write error, " + j.str; - t->alerts().post_alert(file_error_alert(t->get_handle(), err)); - } + std::string err = "torrent paused: disk write error, " + j.str; + t->alerts().post_alert(file_error_alert(t->get_handle(), err)); } t->pause(); return; diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 025437977..800422d63 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1093,7 +1093,13 @@ namespace detail // check if we have any active torrents // if we don't reject the connection - if (m_torrents.empty()) return; + if (m_torrents.empty()) + { +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << " There are no torrents, disconnect\n"; +#endif + return; + } bool has_active_torrent = false; for (torrent_map::iterator i = m_torrents.begin() @@ -1105,10 +1111,16 @@ namespace detail break; } } - if (!has_active_torrent) return; + if (!has_active_torrent) + { +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << " There are no _active_ torrents, disconnect\n"; +#endif + return; + } boost::intrusive_ptr c( - new bt_peer_connection(*this, s, 0)); + new bt_peer_connection(*this, s, endp, 0)); #ifndef NDEBUG c->m_in_constructor = false; #endif diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 062902a63..8abaea813 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -499,8 +499,15 @@ namespace libtorrent std::pair ret = directories.insert((m_save_path / bp).string()); bp = bp.branch_path(); } +#if defined(_WIN32) && defined(UNICODE) + try + { fs::remove(safe_convert(p)); } + catch (std::exception& e) + { error = e.what(); } +#else if (std::remove(p.c_str()) != 0 && errno != ENOENT) error = std::strerror(errno); +#endif } // remove the directories. Reverse order to delete @@ -509,8 +516,15 @@ namespace libtorrent for (std::set::reverse_iterator i = directories.rbegin() , end(directories.rend()); i != end; ++i) { +#if defined(_WIN32) && defined(UNICODE) + try + { fs::remove(safe_convert(*i)); } + catch (std::exception& e) + { error = e.what(); } +#else if (std::remove(i->c_str()) != 0 && errno != ENOENT) error = std::strerror(errno); +#endif } if (!error.empty()) throw std::runtime_error(error); @@ -1688,6 +1702,12 @@ namespace libtorrent try { + if (m_info->num_pieces() == 0) + { + m_state = state_create_files; + return std::make_pair(false, 1.f); + } + // initialization for the full check if (m_hash_to_piece.empty()) { @@ -1915,7 +1935,7 @@ namespace libtorrent { // find the file that failed, and skip all the blocks in that file size_type file_offset = 0; - size_type current_offset = m_current_slot * m_info->piece_length(); + size_type current_offset = size_type(m_current_slot) * m_info->piece_length(); for (torrent_info::file_iterator i = m_info->begin_files(true); i != m_info->end_files(true); ++i) { @@ -2182,7 +2202,8 @@ namespace libtorrent if (m_unallocated_slots.empty() && m_state == state_finished) { - TORRENT_ASSERT(m_storage_mode != storage_mode_compact); + TORRENT_ASSERT(m_storage_mode != storage_mode_compact + || m_info->num_pieces() == 0); } if (m_storage_mode != storage_mode_compact) diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 8cbfa420e..983778c94 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -1635,8 +1635,22 @@ namespace libtorrent std::string hostname; int port; std::string path; - boost::tie(protocol, auth, hostname, port, path) - = parse_url_components(url); + + try + { + boost::tie(protocol, auth, hostname, port, path) + = parse_url_components(url); + } + catch (std::exception& e) + { + if (m_ses.m_alerts.should_post(alert::warning)) + { + m_ses.m_alerts.post_alert( + url_seed_alert(get_handle(), url, e.what())); + } + remove_url_seed(url); + return; + } #ifdef TORRENT_USE_OPENSSL if (protocol != "http" && protocol != "https") @@ -1691,6 +1705,18 @@ namespace libtorrent } else { + if (m_ses.m_port_filter.access(port) & port_filter::blocked) + { + if (m_ses.m_alerts.should_post(alert::warning)) + { + m_ses.m_alerts.post_alert( + url_seed_alert(get_handle(), url, "port blocked by port-filter")); + } + // never try it again + remove_url_seed(url); + return; + } + tcp::resolver::query q(hostname, boost::lexical_cast(port)); m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url @@ -1733,8 +1759,21 @@ namespace libtorrent using boost::tuples::ignore; std::string hostname; int port; - boost::tie(ignore, ignore, hostname, port, ignore) - = parse_url_components(url); + try + { + boost::tie(ignore, ignore, hostname, port, ignore) + = parse_url_components(url); + } + catch (std::exception& e) + { + if (m_ses.m_alerts.should_post(alert::warning)) + { + m_ses.m_alerts.post_alert( + url_seed_alert(get_handle(), url, e.what())); + } + remove_url_seed(url); + return; + } if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) { @@ -1743,6 +1782,7 @@ namespace libtorrent m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() , "proxy (" + hostname + ") blocked by IP filter")); } + remove_url_seed(url); return; } @@ -3226,7 +3266,7 @@ namespace libtorrent --filtered_pieces; } - st.total_wanted -= filtered_pieces * m_torrent_file->piece_length(); + st.total_wanted -= size_type(filtered_pieces) * m_torrent_file->piece_length(); } TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done); @@ -3290,7 +3330,7 @@ namespace libtorrent if (r.kind == tracker_request::announce_request) { m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, 0, s.str())); + , m_failed_trackers + 1, 0, r.url, s.str())); } else if (r.kind == tracker_request::scrape_request) { @@ -3322,7 +3362,7 @@ namespace libtorrent if (r.kind == tracker_request::announce_request) { m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, response_code, s.str())); + , m_failed_trackers + 1, response_code, r.url, s.str())); } else if (r.kind == tracker_request::scrape_request) { diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index cc199c069..c3040f80e 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -443,14 +443,17 @@ namespace libtorrent void torrent_info::read_torrent_info(const entry& torrent_file) { // extract the url of the tracker - if (entry const* i = torrent_file.find_key("announce-list")) + entry const* i = torrent_file.find_key("announce-list"); + if (i && i->type() == entry::list_t) { const entry::list_type& l = i->list(); for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j) { + if (j->type() != entry::list_t) continue; const entry::list_type& ll = j->list(); for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k) { + if (k->type() != entry::string_t) continue; announce_entry e(k->string()); e.tier = (int)std::distance(l.begin(), j); m_urls.push_back(e); @@ -823,7 +826,7 @@ namespace libtorrent if (index == num_pieces()-1) { size_type size = total_size() - - (num_pieces() - 1) * piece_length(); + - size_type(num_pieces() - 1) * piece_length(); TORRENT_ASSERT(size > 0); TORRENT_ASSERT(size <= piece_length()); return int(size); diff --git a/libtorrent/src/tracker_manager.cpp b/libtorrent/src/tracker_manager.cpp index eb1f4cfd3..b389c12ac 100755 --- a/libtorrent/src/tracker_manager.cpp +++ b/libtorrent/src/tracker_manager.cpp @@ -424,13 +424,13 @@ namespace libtorrent = std::find(url.begin(), url.end(), ':'); protocol.assign(start, end); - if (end == url.end()) throw std::runtime_error("invalid url"); + if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); ++end; - if (end == url.end()) throw std::runtime_error("invalid url"); - if (*end != '/') throw std::runtime_error("invalid url"); + if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); + if (*end != '/') throw std::runtime_error("invalid url '" + url + "'"); ++end; - if (end == url.end()) throw std::runtime_error("invalid url"); - if (*end != '/') throw std::runtime_error("invalid url"); + if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'"); + if (*end != '/') throw std::runtime_error("invalid url '" + url + "'"); ++end; start = end; @@ -454,7 +454,7 @@ namespace libtorrent if (start != url.end() && *start == '[') { port_pos = std::find(start, url.end(), ']'); - if (port_pos == url.end()) throw std::runtime_error("invalid hostname syntax"); + if (port_pos == url.end()) throw std::runtime_error("invalid hostname syntax '" + url + "'"); port_pos = std::find(port_pos, url.end(), ':'); } else diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index 24cb7769b..7a37635ed 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -71,7 +71,7 @@ upnp::upnp(io_service& ios, connection_queue& cc , m_io_service(ios) , m_strand(ios) , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900) - , m_strand.wrap(bind(&upnp::on_reply, self(), _1, _2, _3)), false) + , bind(&upnp::on_reply, self(), _1, _2, _3), false) , m_broadcast_timer(ios) , m_refresh_timer(ios) , m_disabled(false) @@ -119,8 +119,8 @@ void upnp::discover_device() try ++m_retry_count; m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); - m_broadcast_timer.async_wait(m_strand.wrap(bind(&upnp::resend_request - , self(), _1))); + m_broadcast_timer.async_wait(bind(&upnp::resend_request + , self(), _1)); #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() @@ -209,9 +209,10 @@ try m_log << time_now_string() << " ==> connecting to " << d.url << std::endl; #endif + if (d.upnp_connection) d.upnp_connection->close(); d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2 - , boost::ref(d))))); + , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 + , boost::ref(d), _5))); d.upnp_connection->get(d.url); } catch (std::exception& e) @@ -358,8 +359,20 @@ try std::string protocol; std::string auth; // we don't have this device in our list. Add it - boost::tie(protocol, auth, d.hostname, d.port, d.path) - = parse_url_components(d.url); + try + { + boost::tie(protocol, auth, d.hostname, d.port, d.path) + = parse_url_components(d.url); + } + catch (std::exception& e) + { +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() + << " <== (" << from << ") invalid url: '" << d.url + << "'. Ignoring device" << std::endl; +#endif + return; + } // ignore the auth here. It will be re-parsed // by the http connection later @@ -444,9 +457,10 @@ try m_log << time_now_string() << " ==> connecting to " << d.url << std::endl; #endif + if (d.upnp_connection) d.upnp_connection->close(); d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2 - , boost::ref(d))))); + , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2 + , boost::ref(d), _5))); d.upnp_connection->get(d.url); } catch (std::exception& e) @@ -552,9 +566,10 @@ void upnp::map_port(rootdevice& d, int i) m_log << time_now_string() << " ==> connecting to " << d.hostname << std::endl; #endif + if (d.upnp_connection) d.upnp_connection->close(); d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2 - , boost::ref(d), i)), true + , m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2 + , boost::ref(d), i, _5), true , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) @@ -609,9 +624,11 @@ void upnp::unmap_port(rootdevice& d, int i) m_log << time_now_string() << " ==> connecting to " << d.hostname << std::endl; #endif + + if (d.upnp_connection) d.upnp_connection->close(); d.upnp_connection.reset(new http_connection(m_io_service - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2 - , boost::ref(d), i)), true + , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2 + , boost::ref(d), i, _5), true , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) , seconds(10)); @@ -675,10 +692,11 @@ namespace } void upnp::on_upnp_xml(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d) try + , libtorrent::http_parser const& p, rootdevice& d + , http_connection& c) try { TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection) + if (d.upnp_connection && d.upnp_connection.get() == &c) { d.upnp_connection->close(); d.upnp_connection.reset(); @@ -823,10 +841,11 @@ namespace } void upnp::on_upnp_map_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping) try + , libtorrent::http_parser const& p, rootdevice& d, int mapping + , http_connection& c) try { TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection) + if (d.upnp_connection && d.upnp_connection.get() == &c) { d.upnp_connection->close(); d.upnp_connection.reset(); @@ -945,7 +964,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e || next_expire > d.mapping[mapping].expires) { m_refresh_timer.expires_at(d.mapping[mapping].expires); - m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1))); + m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); } } else @@ -969,10 +988,11 @@ catch (std::exception&) }; void upnp::on_upnp_unmap_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping) try + , libtorrent::http_parser const& p, rootdevice& d, int mapping + , http_connection& c) try { TORRENT_ASSERT(d.magic == 1337); - if (d.upnp_connection) + if (d.upnp_connection && d.upnp_connection.get() == &c) { d.upnp_connection->close(); d.upnp_connection.reset(); @@ -1054,7 +1074,7 @@ void upnp::on_expire(asio::error_code const& e) try if (next_expire != max_time()) { m_refresh_timer.expires_at(next_expire); - m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1))); + m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1)); } } catch (std::exception&) diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp index 3e390ac4f..e79f6b9bf 100755 --- a/libtorrent/src/web_peer_connection.cpp +++ b/libtorrent/src/web_peer_connection.cpp @@ -224,7 +224,7 @@ namespace libtorrent request += "\r\nProxy-Connection: keep-alive"; } request += "\r\nRange: bytes="; - request += boost::lexical_cast(r.piece + request += boost::lexical_cast(size_type(r.piece) * info.piece_length() + r.start); request += "-"; request += boost::lexical_cast(r.piece