From dbed97349c2b2096bec8f2406c196bc98f47a0d9 Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Thu, 25 Sep 2008 20:45:31 +0000 Subject: [PATCH] lt sync 2726 --- libtorrent/bindings/python/src/peer_info.cpp | 7 +- libtorrent/include/libtorrent/peer_info.hpp | 3 + libtorrent/include/libtorrent/session.hpp | 8 ++ libtorrent/include/libtorrent/torrent.hpp | 2 - .../include/libtorrent/torrent_info.hpp | 2 - libtorrent/include/libtorrent/udp_socket.hpp | 8 ++ libtorrent/src/broadcast_socket.cpp | 2 +- libtorrent/src/file.cpp | 2 +- libtorrent/src/lazy_bdecode.cpp | 33 +++-- libtorrent/src/natpmp.cpp | 14 ++ libtorrent/src/peer_connection.cpp | 27 +++- libtorrent/src/piece_picker.cpp | 3 + libtorrent/src/policy.cpp | 1 + libtorrent/src/session.cpp | 35 ++++- libtorrent/src/session_impl.cpp | 14 +- libtorrent/src/torrent.cpp | 135 +++++++++++++----- libtorrent/src/udp_socket.cpp | 85 +++++++++-- 17 files changed, 303 insertions(+), 78 deletions(-) diff --git a/libtorrent/bindings/python/src/peer_info.cpp b/libtorrent/bindings/python/src/peer_info.cpp index 3d410fb63..e054401c1 100755 --- a/libtorrent/bindings/python/src/peer_info.cpp +++ b/libtorrent/bindings/python/src/peer_info.cpp @@ -44,11 +44,6 @@ list get_pieces(peer_info const& pi) return ret; } -float get_progress(peer_info const& pi) -{ - return (float)pi.pieces.count() / (float)pi.pieces.size(); -} - void bind_peer_info() { scope pi = class_("peer_info") @@ -94,7 +89,7 @@ void bind_peer_info() .def_readonly("send_quota", &peer_info::send_quota) .def_readonly("receive_quota", &peer_info::receive_quota) .def_readonly("rtt", &peer_info::rtt) - .add_property("progress", get_progress) + .def_readonly("progress", &peer_info::progress) ; // flags diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp index c85069bff..e28216ce0 100644 --- a/libtorrent/include/libtorrent/peer_info.hpp +++ b/libtorrent/include/libtorrent/peer_info.hpp @@ -196,6 +196,9 @@ namespace libtorrent // the highest transfer rates seen for this peer int download_rate_peak; int upload_rate_peak; + + // the peers progress + float progress; }; struct TORRENT_EXPORT peer_list_entry diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index a3fa9e5cd..f112253ea 100644 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -155,6 +155,7 @@ namespace libtorrent session(fingerprint const& print = fingerprint("LT" , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0) + , int flags = start_default_features | add_default_plugins #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath = "." #endif @@ -163,6 +164,7 @@ namespace libtorrent fingerprint const& print , std::pair listen_port_range , char const* listen_interface = "0.0.0.0" + , int flags = start_default_features | add_default_plugins #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath = "." #endif @@ -290,6 +292,12 @@ namespace libtorrent delete_files = 1 }; + enum session_flags_t + { + add_default_plugins = 1, + start_default_features = 2 + }; + void remove_torrent(const torrent_handle& h, int options = none); void set_settings(session_settings const& s); diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 7c8a69020..356e2feff 100644 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -130,8 +130,6 @@ namespace libtorrent ~torrent(); - void parse_resume_data(std::vector* resume_data); - #ifndef TORRENT_DISABLE_ENCRYPTION sha1_hash const& obfuscated_hash() const { return m_obfuscated_hash; } diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp index a027e3460..51cca20a5 100644 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -197,8 +197,6 @@ namespace libtorrent nodes_t m_nodes; // the hash that identifies this torrent - // is mutable because it's calculated - // lazily sha1_hash m_info_hash; // if a creation date is found in the torrent file diff --git a/libtorrent/include/libtorrent/udp_socket.hpp b/libtorrent/include/libtorrent/udp_socket.hpp index 79b301b49..d1c87e2aa 100644 --- a/libtorrent/include/libtorrent/udp_socket.hpp +++ b/libtorrent/include/libtorrent/udp_socket.hpp @@ -64,6 +64,10 @@ namespace libtorrent void set_proxy_settings(proxy_settings const& ps); proxy_settings const& get_proxy_settings() { return m_proxy_settings; } +#ifndef NDEBUG + ~udp_socket() { m_magic = 0; } +#endif + private: callback_t m_callback; @@ -94,6 +98,7 @@ namespace libtorrent char m_v4_buf[1600]; char m_v6_buf[1600]; int m_bind_port; + char m_outstanding; tcp::socket m_socks5_sock; int m_connection_ticket; @@ -103,6 +108,9 @@ namespace libtorrent char m_tmp_buf[100]; bool m_tunnel_packets; udp::endpoint m_proxy_addr; +#ifndef NDEBUG + int m_magic; +#endif }; } diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp index d9fd2470f..deefe23be 100644 --- a/libtorrent/src/broadcast_socket.cpp +++ b/libtorrent/src/broadcast_socket.cpp @@ -170,7 +170,7 @@ namespace libtorrent , end(interfaces.end()); i != end; ++i) { // only broadcast to IPv4 addresses that are not local - if (!is_local(i->interface_address)) continue; + if (is_local(i->interface_address)) continue; // only multicast on compatible networks if (i->interface_address.is_v4() != multicast_endpoint.address().is_v4()) continue; // ignore any loopback interface diff --git a/libtorrent/src/file.cpp b/libtorrent/src/file.cpp index 29420711e..bd3a0d368 100755 --- a/libtorrent/src/file.cpp +++ b/libtorrent/src/file.cpp @@ -95,7 +95,7 @@ namespace std::string ret; ret.resize(size); size = wcstombs(&ret[0], ws.c_str(), size + 1); - if (size == wchar_t(-1)) return s; + if (size == std::size_t(-1)) return s; ret.resize(size); return ret; } diff --git a/libtorrent/src/lazy_bdecode.cpp b/libtorrent/src/lazy_bdecode.cpp index e823b07bc..6c469b64a 100644 --- a/libtorrent/src/lazy_bdecode.cpp +++ b/libtorrent/src/lazy_bdecode.cpp @@ -47,7 +47,11 @@ namespace namespace libtorrent { - int fail_bdecode() { return -1; } + int fail_bdecode(lazy_entry& ret) + { + ret = lazy_entry(); + return -1; + } // fills in 'val' with what the string between start and the // first occurance of the delimiter is interpreted as an int. @@ -58,7 +62,7 @@ namespace libtorrent while (start < end && *start != delimiter) { using namespace std; - if (!isdigit(*start)) { fail_bdecode(); return 0; } + if (!isdigit(*start)) { return 0; } val *= 10; val += *start - '0'; ++start; @@ -87,11 +91,11 @@ namespace libtorrent lazy_entry* top = stack.back(); - if (int(stack.size()) > depth_limit) return fail_bdecode(); - if (start >= end) return fail_bdecode(); + if (int(stack.size()) > depth_limit) return fail_bdecode(ret); + if (start >= end) return fail_bdecode(ret); char t = *start; ++start; - if (start >= end && t != 'e') return fail_bdecode(); + if (start >= end && t != 'e') return fail_bdecode(ret); switch (top->type()) { @@ -105,12 +109,12 @@ namespace libtorrent } boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 3 > end || *start != ':') return fail_bdecode(); + if (start == 0 || start + len + 3 > end || *start != ':') return fail_bdecode(ret); ++start; - if (start == end) fail_bdecode(); + if (start == end) fail_bdecode(ret); lazy_entry* ent = top->dict_append(start); start += len; - if (start >= end) fail_bdecode(); + if (start >= end) fail_bdecode(ret); stack.push_back(ent); t = *start; ++start; @@ -145,7 +149,7 @@ namespace libtorrent char const* int_start = start; start = find_char(start, end, 'e'); top->construct_int(int_start, start - int_start); - if (start == end) return fail_bdecode(); + if (start == end) return fail_bdecode(ret); TORRENT_ASSERT(*start == 'e'); ++start; stack.pop_back(); @@ -154,11 +158,11 @@ namespace libtorrent default: { using namespace std; - if (!isdigit(t)) return fail_bdecode(); + if (!isdigit(t)) return fail_bdecode(ret); boost::int64_t len = t - '0'; start = parse_int(start, end, ':', len); - if (start == 0 || start + len + 1 > end || *start != ':') return fail_bdecode(); + if (start == 0 || start + len + 1 > end || *start != ':') return fail_bdecode(ret); ++start; top->construct_string(start, int(len)); stack.pop_back(); @@ -391,11 +395,12 @@ namespace libtorrent { os << "["; bool one_liner = (e.list_size() == 0 - || e.list_at(0)->type() == lazy_entry::int_t + || (e.list_at(0)->type() == lazy_entry::int_t + && e.list_size() < 20) || (e.list_at(0)->type() == lazy_entry::string_t && (e.list_at(0)->string_length() < 10 - || e.list_size() < 2))) - && e.list_size() < 5; + || e.list_size() < 2)) + && e.list_size() < 5); if (!one_liner) os << "\n"; for (int i = 0; i < e.list_size(); ++i) { diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp index 878cc6fbf..b183d1d22 100644 --- a/libtorrent/src/natpmp.cpp +++ b/libtorrent/src/natpmp.cpp @@ -226,6 +226,20 @@ void natpmp::try_next_mapping(int i) void natpmp::update_mapping(int i) { + if (i == m_mappings.size()) + { + if (m_abort) + { + error_code ec; + m_send_timer.cancel(ec); + m_socket.close(ec); + } +#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) + m_log << " done" << (m_abort?" shutting down":"") << std::endl; +#endif + return; + } + natpmp::mapping_t& m = m_mappings[i]; if (m.action == mapping_t::action_none || m.protocol == none) diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 778f81d87..8ed1cd187 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -1693,6 +1693,9 @@ namespace libtorrent send_block_requests(); return; } +#ifndef NDEBUG + pending_block pending_b = *b; +#endif int block_index = b - m_download_queue.begin() - 1; for (int i = 0; i < block_index; ++i) @@ -1721,6 +1724,9 @@ namespace libtorrent --block_index; } } + TORRENT_ASSERT(int(m_download_queue.size()) > block_index + 1); + b = m_download_queue.begin() + (block_index + 1); + TORRENT_ASSERT(b->block == pending_b.block); // if the block we got is already finished, then ignore it if (picker.is_downloaded(block_finished)) @@ -2666,6 +2672,8 @@ namespace libtorrent p.used_receive_buffer = m_recv_pos; p.write_state = m_channel_state[upload_channel]; p.read_state = m_channel_state[download_channel]; + + p.progress = (float)p.pieces.count() / (float)p.pieces.size(); } // allocates a disk buffer of size 'disk_buffer_size' and replaces the @@ -3625,7 +3633,22 @@ namespace libtorrent disconnect(ec.message().c_str()); return; } - m_socket->bind(t->get_interface(), ec); + + tcp::endpoint bind_interface = t->get_interface(); + + std::pair const& out_ports = m_ses.settings().outgoing_ports; + if (out_ports.first > 0 && out_ports.second >= out_ports.first) + { + m_socket->set_option(socket_acceptor::reuse_address(true), ec); + if (ec) + { + disconnect(ec.message().c_str()); + return; + } + bind_interface.port(m_ses.next_port()); + } + + m_socket->bind(bind_interface, ec); if (ec) { disconnect(ec.message().c_str()); @@ -3818,7 +3841,7 @@ namespace libtorrent } if (t->ready_for_connections() && m_initialized) - TORRENT_ASSERT(t->torrent_file().num_pieces() == m_have_piece.size()); + TORRENT_ASSERT(t->torrent_file().num_pieces() == int(m_have_piece.size())); if (m_ses.settings().close_redundant_connections) { diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 35b97b4df..6aeb5fae0 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -1304,6 +1304,9 @@ namespace libtorrent , int prefer_whole_pieces, void* peer, piece_state_t speed , int options, std::vector const& suggested_pieces) const { + // prevent the number of partial pieces to grow indefinitely + if (m_downloads.size() > 20) options |= prioritize_partials; + // only one of rarest_first and sequential can be set. TORRENT_ASSERT(bool(options & rarest_first) + bool(options & sequential) <= 1); diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index b98ce6363..dd2edcc82 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -991,6 +991,7 @@ namespace libtorrent ++p->second.failcount; return false; } + TORRENT_ASSERT(p->second.connection); TORRENT_ASSERT(!is_connect_candidate(p->second, m_torrent->is_finished())); --m_num_connect_candidates; return true; diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 3c65d02b5..b0db1d9ef 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -56,6 +56,9 @@ POSSIBILITY OF SUCH DAMAGE. #pragma warning(pop) #endif +#include "libtorrent/extensions/ut_pex.hpp" +#include "libtorrent/extensions/ut_metadata.hpp" +#include "libtorrent/extensions/smart_ban.hpp" #include "libtorrent/peer_id.hpp" #include "libtorrent/torrent_info.hpp" #include "libtorrent/tracker_manager.hpp" @@ -112,6 +115,7 @@ namespace libtorrent fingerprint const& id , std::pair listen_port_range , char const* listen_interface + , int flags #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath #endif @@ -120,7 +124,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , logpath #endif - )) + )) { #ifdef TORRENT_MEMDEBUG start_malloc_debug(); @@ -135,9 +139,23 @@ namespace libtorrent boost::function0 test = boost::ref(*m_impl); TORRENT_ASSERT(!test.empty()); #endif +#ifndef TORRENT_DISABLE_EXTENSIONS + if (flags & add_default_plugins) + { + add_extension(create_ut_pex_plugin); + add_extension(create_ut_metadata_plugin); + add_extension(create_smart_ban_plugin); + } +#endif + if (flags & start_default_features) + { + start_upnp(); + start_upnp(); + } } session::session(fingerprint const& id + , int flags #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING , fs::path logpath #endif @@ -155,6 +173,19 @@ namespace libtorrent boost::function0 test = boost::ref(*m_impl); TORRENT_ASSERT(!test.empty()); #endif +#ifndef TORRENT_DISABLE_EXTENSIONS + if (flags & add_default_plugins) + { + add_extension(create_ut_pex_plugin); + add_extension(create_ut_metadata_plugin); + add_extension(create_smart_ban_plugin); + } +#endif + if (flags & start_default_features) + { + start_upnp(); + start_natpmp(); + } } session::~session() @@ -170,10 +201,12 @@ namespace libtorrent m_impl->abort(); } +#ifndef TORRENT_DISABLE_EXTENSIONS void session::add_extension(boost::function(torrent*, void*)> ext) { m_impl->add_extension(ext); } +#endif #ifndef TORRENT_DISABLE_GEO_IP bool session::load_asnum_db(char const* file) diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index b90b8ad43..ae2846e2c 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -386,6 +387,17 @@ namespace aux { void session_impl::add_extension( boost::function(torrent*, void*)> ext) { + TORRENT_ASSERT(ext); + + typedef boost::shared_ptr(*function_t)(torrent*, void*); + function_t const* f = ext.target(); + + if (f) + { + for (extension_list_t::iterator i = m_extensions.begin(); i != m_extensions.end(); ++i) + if (function_equal(*i, *f)) return; + } + m_extensions.push_back(ext); } #endif @@ -2469,7 +2481,7 @@ namespace aux { ++total_downloaders; unique.insert(i->second->queue_position()); } - TORRENT_ASSERT(unique.size() == total_downloaders); + TORRENT_ASSERT(int(unique.size()) == total_downloaders); TORRENT_ASSERT(m_max_connections > 0); TORRENT_ASSERT(m_max_uploads > 0); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index cfeeffa86..49710cf4d 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -205,7 +205,7 @@ namespace libtorrent , m_start_sent(false) , m_complete_sent(false) { - parse_resume_data(resume_data); + if (resume_data) m_resume_data.swap(*resume_data); #ifndef TORRENT_DISABLE_ENCRYPTION hasher h; @@ -286,7 +286,7 @@ namespace libtorrent , m_start_sent(false) , m_complete_sent(false) { - parse_resume_data(resume_data); + if (resume_data) m_resume_data.swap(*resume_data); #ifndef TORRENT_DISABLE_ENCRYPTION hasher h; @@ -309,27 +309,25 @@ namespace libtorrent } } - void torrent::parse_resume_data(std::vector* resume_data) - { - if (!resume_data) return; - m_resume_data.swap(*resume_data); - if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0] - + m_resume_data.size(), m_resume_entry) != 0) - { - std::vector().swap(m_resume_data); - if (m_ses.m_alerts.should_post()) - { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed")); -#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: parse failed\n"; -#endif - } - } - } - void torrent::start() { + if (!m_resume_data.empty()) + { + if (lazy_bdecode(&m_resume_data[0], &m_resume_data[0] + + m_resume_data.size(), m_resume_entry) != 0) + { + std::vector().swap(m_resume_data); + if (m_ses.m_alerts.should_post()) + { + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed")); +#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING + (*m_ses.m_logger) << "fastresume data for " + << torrent_file().name() << " rejected: parse failed\n"; +#endif + } + } + } + // we need to start announcing since we don't have any // metadata. To receive peers to ask for it. if (m_torrent_file->is_valid()) init(); @@ -1998,6 +1996,8 @@ namespace libtorrent if (m_currently_trying_tracker >= (int)m_trackers.size()) m_currently_trying_tracker = (int)m_trackers.size()-1; m_last_working_tracker = -1; + if (!m_trackers.empty()) start_announcing(); + else stop_announcing(); } void torrent::choke_peer(peer_connection& c) @@ -2306,11 +2306,6 @@ namespace libtorrent s->get().set_no_connect(true); } - std::pair const& out_ports = m_settings.outgoing_ports; - 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 c(new (std::nothrow) web_peer_connection( m_ses, shared_from_this(), s, a, url, 0)); if (!c) return; @@ -2520,8 +2515,50 @@ namespace libtorrent m_picker->set_piece_priority(i, p[i]); } - if (rd.dict_find_int_value("auto_managed")) auto_managed(true); - if (rd.dict_find_int_value("paused")) pause(); + int auto_managed_ = rd.dict_find_int_value("auto_managed", -1); + if (auto_managed_ != -1) auto_managed(auto_managed_); + + int sequential_ = rd.dict_find_int_value("sequential_download", -1); + if (sequential_ != -1) set_sequential_download(sequential_); + + int paused_ = rd.dict_find_int_value("paused", -1); + if (paused_ == 1) pause(); + else if (paused_ == 0) resume(); + + lazy_entry const* trackers = rd.dict_find_list("trackers"); + if (trackers) + { + int tier = 0; + for (int i = 0; i < trackers->list_size(); ++i) + { + lazy_entry const* tier_list = trackers->list_at(i); + if (tier_list == 0 || tier_list->type() != lazy_entry::list_t) + continue; + for (int j = 0; j < tier_list->list_size(); ++j) + { + announce_entry e(tier_list->list_string_value_at(j)); + if (std::find_if(m_trackers.begin(), m_trackers.end() + , boost::bind(&announce_entry::url, _1) == e.url) != m_trackers.end()) + continue; + e.tier = tier; + m_trackers.push_back(e); + } + ++tier; + } + std::sort(m_trackers.begin(), m_trackers.end(), boost::bind(&announce_entry::tier, _1) + < boost::bind(&announce_entry::tier, _2)); + } + + lazy_entry const* url_list = rd.dict_find_list("url-list"); + if (url_list) + { + for (int i = 0; i < url_list->list_size(); ++i) + { + std::string url = url_list->list_string_value_at(i); + if (url.empty()) continue; + m_web_seeds.insert(url); + } + } } void torrent::write_resume_data(entry& ret) const @@ -2544,6 +2581,8 @@ namespace libtorrent ret["num_seeds"] = seeds; ret["num_downloaders"] = downloaders; + + ret["sequential_download"] = m_sequential_download; const sha1_hash& info_hash = torrent_file().info_hash(); ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); @@ -2595,6 +2634,39 @@ namespace libtorrent } } + // save trackers + if (!m_trackers.empty()) + { + entry::list_type& tr_list = ret["trackers"].list(); + tr_list.push_back(entry::list_type()); + int tier = 0; + for (std::vector::const_iterator i = m_trackers.begin() + , end(m_trackers.end()); i != end; ++i) + { + if (i->tier == tier) + { + tr_list.back().list().push_back(i->url); + } + else + { + tr_list.push_back(entry::list_t); + tr_list.back().list().push_back(i->url); + tier = i->tier; + } + } + } + + // save web seeds + if (!m_web_seeds.empty()) + { + entry::list_type& url_list = ret["url-list"].list(); + for (std::set::const_iterator i = m_web_seeds.begin() + , end(m_web_seeds.end()); i != end; ++i) + { + url_list.push_back(*i); + } + } + // write have bitmask entry::string_type& pieces = ret["pieces"].string(); pieces.resize(m_torrent_file->num_pieces()); @@ -2812,10 +2884,6 @@ namespace libtorrent bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s); (void)ret; TORRENT_ASSERT(ret); - std::pair const& out_ports = m_ses.settings().outgoing_ports; - 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 c(new bt_peer_connection( m_ses, shared_from_this(), s, a, peerinfo)); @@ -2871,7 +2939,8 @@ namespace libtorrent return false; } #endif - return true; + + return peerinfo->connection; } bool torrent::set_metadata(lazy_entry const& metadata, std::string& error) diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp index 3a5c00892..c36a97530 100644 --- a/libtorrent/src/udp_socket.cpp +++ b/libtorrent/src/udp_socket.cpp @@ -18,20 +18,33 @@ udp_socket::udp_socket(asio::io_service& ios, udp_socket::callback_t const& c , m_ipv4_sock(ios) , m_ipv6_sock(ios) , m_bind_port(0) + , m_outstanding(0) , m_socks5_sock(ios) , m_connection_ticket(-1) , m_cc(cc) , m_resolver(ios) , m_tunnel_packets(false) { +#ifndef NDEBUG + m_magic = 0x1337; +#endif } +#ifndef NDEBUG + #define CHECK_MAGIC check_magic_ cm_(m_magic) + struct check_magic_ + { + check_magic_(int& m_): m(m_) { TORRENT_ASSERT(m == 0x1337); } + ~check_magic_() { TORRENT_ASSERT(m == 0x1337); } + int& m; + }; +#else + #define CHECK_MAGIC do {} while (false) +#endif + void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec) { - if (ec == asio::error::operation_aborted) return; - - mutex_t::scoped_lock l(m_mutex); - + CHECK_MAGIC; if (m_tunnel_packets) { // send udp packets through SOCKS5 server @@ -47,10 +60,26 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_cod void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_transferred) { - if (e == asio::error::operation_aborted) return; - + TORRENT_ASSERT(m_magic == 0x1337); mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(m_outstanding > 0); + --m_outstanding; + + if (e == asio::error::operation_aborted) + { + if (m_outstanding == 0) + { + // "this" may be destructed in the callback + // that's why we need to unlock + l.unlock(); + callback_t tmp = m_callback; + m_callback.clear(); + } + return; + } + + CHECK_MAGIC; if (!m_callback) return; if (e) @@ -59,9 +88,9 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ try { #endif if (s == &m_ipv4_sock) - get_io_service().post(boost::bind(m_callback, e, m_v4_ep, (char*)0, 0)); + m_callback(e, m_v4_ep, 0, 0); else - get_io_service().post(boost::bind(m_callback, e, m_v6_ep, (char*)0, 0)); + m_callback(e, m_v6_ep, 0, 0); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} #endif @@ -94,7 +123,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ if (m_tunnel_packets && m_v4_ep == m_proxy_addr) unwrap(e, m_v4_buf, bytes_transferred); else - get_io_service().post(boost::bind(m_callback, e, m_v4_ep, m_v4_buf, bytes_transferred)); + m_callback(e, m_v4_ep, m_v4_buf, bytes_transferred); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} @@ -111,7 +140,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ if (m_tunnel_packets && m_v6_ep == m_proxy_addr) unwrap(e, m_v6_buf, bytes_transferred); else - get_io_service().post(boost::bind(m_callback, e, m_v6_ep, m_v6_buf, bytes_transferred)); + m_callback(e, m_v6_ep, m_v6_buf, bytes_transferred); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} @@ -119,10 +148,12 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ s->async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) , m_v6_ep, boost::bind(&udp_socket::on_read, this, s, _1, _2)); } + ++m_outstanding; } void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec) { + CHECK_MAGIC; using namespace libtorrent::detail; char header[20]; @@ -147,6 +178,7 @@ void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_cod // unwrap the UDP packet from the SOCKS5 header void udp_socket::unwrap(error_code const& e, char const* buf, int size) { + CHECK_MAGIC; using namespace libtorrent::detail; // the minimum socks5 header size @@ -177,27 +209,34 @@ void udp_socket::unwrap(error_code const& e, char const* buf, int size) return; } - get_io_service().post(boost::bind(m_callback, e, sender, p, size - (p - buf))); + m_callback(e, sender, p, size - (p - buf)); } void udp_socket::close() { - mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(m_magic == 0x1337); error_code ec; m_ipv4_sock.close(ec); m_ipv6_sock.close(ec); m_socks5_sock.close(ec); - m_callback.clear(); if (m_connection_ticket >= 0) { m_cc.done(m_connection_ticket); m_connection_ticket = -1; } + + if (m_outstanding == 0) + { + // "this" may be destructed in the callback + callback_t tmp = m_callback; + m_callback.clear(); + } } void udp_socket::bind(udp::endpoint const& ep, error_code& ec) { + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); @@ -221,11 +260,13 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec) m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); } + ++m_outstanding; m_bind_port = ep.port(); } void udp_socket::bind(int port) { + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); error_code ec; @@ -239,6 +280,7 @@ void udp_socket::bind(int port) m_ipv4_sock.bind(udp::endpoint(address_v4::any(), port), ec); m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf)) , m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2)); + ++m_outstanding; } m_ipv6_sock.open(udp::v6(), ec); if (!ec) @@ -247,12 +289,14 @@ void udp_socket::bind(int port) m_ipv6_sock.bind(udp::endpoint(address_v6::any(), port), ec); m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf)) , m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2)); + ++m_outstanding; } m_bind_port = port; } void udp_socket::set_proxy_settings(proxy_settings const& ps) { + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); error_code ec; @@ -275,6 +319,7 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps) void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) { if (e) return; + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); @@ -286,6 +331,7 @@ void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) void udp_socket::on_timeout() { + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); error_code ec; @@ -295,6 +341,7 @@ void udp_socket::on_timeout() void udp_socket::on_connect(int ticket) { + CHECK_MAGIC; mutex_t::scoped_lock l(m_mutex); m_connection_ticket = ticket; @@ -306,12 +353,13 @@ void udp_socket::on_connect(int ticket) void udp_socket::on_connected(error_code const& e) { + CHECK_MAGIC; + + mutex_t::scoped_lock l(m_mutex); m_cc.done(m_connection_ticket); m_connection_ticket = -1; if (e) return; - mutex_t::scoped_lock l(m_mutex); - using namespace libtorrent::detail; // send SOCKS5 authentication methods @@ -335,6 +383,7 @@ void udp_socket::on_connected(error_code const& e) void udp_socket::handshake1(error_code const& e) { + CHECK_MAGIC; if (e) return; mutex_t::scoped_lock l(m_mutex); @@ -345,6 +394,7 @@ void udp_socket::handshake1(error_code const& e) void udp_socket::handshake2(error_code const& e) { + CHECK_MAGIC; if (e) return; using namespace libtorrent::detail; @@ -390,6 +440,7 @@ void udp_socket::handshake2(error_code const& e) void udp_socket::handshake3(error_code const& e) { + CHECK_MAGIC; if (e) return; mutex_t::scoped_lock l(m_mutex); @@ -400,6 +451,7 @@ void udp_socket::handshake3(error_code const& e) void udp_socket::handshake4(error_code const& e) { + CHECK_MAGIC; if (e) return; mutex_t::scoped_lock l(m_mutex); @@ -418,6 +470,7 @@ void udp_socket::handshake4(error_code const& e) void udp_socket::socks_forward_udp() { + CHECK_MAGIC; using namespace libtorrent::detail; mutex_t::scoped_lock l(m_mutex); @@ -437,6 +490,7 @@ void udp_socket::socks_forward_udp() void udp_socket::connect1(error_code const& e) { + CHECK_MAGIC; if (e) return; mutex_t::scoped_lock l(m_mutex); @@ -447,6 +501,7 @@ void udp_socket::connect1(error_code const& e) void udp_socket::connect2(error_code const& e) { + CHECK_MAGIC; if (e) return; mutex_t::scoped_lock l(m_mutex);