diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 74220ba47..c878eb95c 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -320,6 +320,12 @@ namespace libtorrent // when they are destructed. file_pool m_files; + // this is a list of half-open tcp connections + // (only outgoing connections) + // this has to be one of the last + // members to be destructed + connection_queue m_half_open; + // the bandwidth manager is responsible for // handing out bandwidth to connections that // asks for it, it can also throttle the @@ -335,10 +341,6 @@ namespace libtorrent // peers. connection_map m_connections; - // this is a list of half-open tcp connections - // (only outgoing connections) - connection_queue m_half_open; - // filters incoming connections ip_filter m_ip_filter; diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 34dee5b70..ccb17cb71 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -78,6 +78,7 @@ namespace libtorrent torrent_info const& t , boost::filesystem::path p , std::vector > const& sizes + , bool compact_mode , std::string* error = 0); struct TORRENT_EXPORT file_allocation_failed: std::exception @@ -104,8 +105,12 @@ namespace libtorrent virtual bool move_storage(boost::filesystem::path save_path) = 0; + // verify storage dependent fast resume entries virtual bool verify_resume_data(entry& rd, std::string& error) = 0; + // write storage dependent fast resume entries + virtual void write_resume_data(entry& rd) const = 0; + // moves (or copies) the content in src_slot to dst_slot virtual void move_slot(int src_slot, int dst_slot) = 0; @@ -153,6 +158,7 @@ namespace libtorrent void release_files(); + void write_resume_data(entry& rd) const; bool verify_resume_data(entry& rd, std::string& error); bool is_allocating() const; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index c3778ecb4..d29e0a92c 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -478,10 +478,10 @@ namespace libtorrent { namespace detail , char const* listen_interface) : m_strand(m_io_service) , m_files(40) + , m_half_open(m_io_service) , m_dl_bandwidth_manager(m_io_service, peer_connection::download_channel) , m_ul_bandwidth_manager(m_io_service, peer_connection::upload_channel) , m_tracker_manager(m_settings, m_tracker_proxy) - , m_half_open(m_io_service) , m_listen_port_range(listen_port_range) , m_listen_interface(address::from_string(listen_interface), listen_port_range.first) , m_external_listen_port(0) @@ -2026,7 +2026,6 @@ namespace libtorrent { namespace detail } } - // verify file sizes if (!torrent_ptr->verify_resume_data(rd, error)) return; diff --git a/src/storage.cpp b/src/storage.cpp index 3a019494b..99cb0cc29 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -270,10 +270,17 @@ namespace libtorrent return sizes; } + // matches the sizes and timestamps of the files passed in + // in non-compact mode, actual file sizes and timestamps + // are allowed to be bigger and more recent than the fast + // resume data. This is because full allocation will not move + // pieces, so any older version of the resume data will + // still be a correct subset of the actual data on disk. bool match_filesizes( torrent_info const& t , path p , std::vector > const& sizes + , bool compact_mode , std::string* error) { if ((int)sizes.size() != t.num_files()) @@ -293,6 +300,7 @@ namespace libtorrent try { path f = p / i->path; +std::cerr << f.string() << " "; #if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 size = file_size_win(f); time = last_write_time_win(f); @@ -302,19 +310,23 @@ namespace libtorrent #endif } catch (std::exception&) {} - if (size != s->first) + if (size != s->first + || (!compact_mode && size < s->first)) { if (error) *error = "filesize mismatch for file '" + i->path.native_file_string() - + "', expected to be " + boost::lexical_cast(s->first) + + "', size: " + boost::lexical_cast(size) + + ", expected to be " + boost::lexical_cast(s->first) + " bytes"; return false; } - if (time != s->second) + if (time != s->second + || (!compact_mode && time < s->second)) { if (error) *error = "timestamp mismatch for file '" + i->path.native_file_string() - + "', expected to have modification date " + + "', modification date: " + boost::lexical_cast(time) + + ", expected to have modification date " + boost::lexical_cast(s->second); return false; } @@ -379,6 +391,7 @@ namespace libtorrent void swap_slots(int slot1, int slot2); void swap_slots3(int slot1, int slot2, int slot3); bool verify_resume_data(entry& rd, std::string& error); + void write_resume_data(entry& rd) const; size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero); @@ -442,6 +455,23 @@ namespace libtorrent std::vector().swap(m_scratch_buffer); } + void storage::write_resume_data(entry& rd) const + { + std::vector > file_sizes + = get_filesizes(m_info, m_save_path); + + rd["file sizes"] = entry::list_type(); + entry::list_type& fl = rd["file sizes"].list(); + for (std::vector >::iterator i + = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) + { + entry::list_type p; + p.push_back(entry(i->first)); + p.push_back(entry(i->second)); + fl.push_back(entry(p)); + } + } + bool storage::verify_resume_data(entry& rd, std::string& error) { std::vector > file_sizes; @@ -455,6 +485,12 @@ namespace libtorrent , i->list().back().integer())); } + if (file_sizes.empty()) + { + error = "the number of files in resume data is 0"; + return false; + } + entry::list_type& slots = rd["slots"].list(); bool seed = int(slots.size()) == m_info.num_pieces() && std::find_if(slots.begin(), slots.end() @@ -497,9 +533,8 @@ namespace libtorrent return true; } - if (full_allocation_mode) return true; - - return match_filesizes(m_info, m_save_path, file_sizes, &error); + return match_filesizes(m_info, m_save_path, file_sizes + , !full_allocation_mode, &error); } // returns true on success @@ -1149,6 +1184,11 @@ namespace libtorrent { } + void piece_manager::write_resume_data(entry& rd) const + { + m_pimpl->m_storage->write_resume_data(rd); + } + bool piece_manager::verify_resume_data(entry& rd, std::string& error) { return m_pimpl->m_storage->verify_resume_data(rd, error); diff --git a/src/torrent.cpp b/src/torrent.cpp index 4f181c11e..92de33435 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1702,9 +1702,11 @@ namespace libtorrent assert(peerinfo); assert(peerinfo->connection == 0); #ifndef NDEBUG + // this asserts that we don't have duplicates in the policy's peer list peer_iterator i_ = m_connections.find(peerinfo->ip); assert(i_ == m_connections.end() - || (i_->second->is_disconnecting())); + || i_->second->is_disconnecting() + || dynamic_cast(i_->second) == 0); #endif assert(want_more_peers()); diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 7b9567eb0..da571ab63 100755 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -602,19 +602,7 @@ namespace libtorrent peer_list.push_back(peer); } - std::vector > file_sizes - = get_filesizes(t->torrent_file(), t->save_path()); - - ret["file sizes"] = entry::list_type(); - entry::list_type& fl = ret["file sizes"].list(); - for (std::vector >::iterator i - = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) - { - entry::list_type p; - p.push_back(entry(i->first)); - p.push_back(entry(i->second)); - fl.push_back(entry(p)); - } + t->filesystem().write_resume_data(ret); return ret; }