From 30329cc225372743751f4bd7ca45d27004c2492a Mon Sep 17 00:00:00 2001 From: Magnus Jonsson Date: Sat, 24 Jan 2004 19:19:17 +0000 Subject: [PATCH] *** empty log message *** --- include/libtorrent/policy.hpp | 5 ++ include/libtorrent/torrent_handle.hpp | 1 - include/libtorrent/torrent_info.hpp | 13 +-- src/policy.cpp | 1 - src/storage.cpp | 125 +++++++++++++++++++++----- src/torrent.cpp | 40 ++++++--- 6 files changed, 143 insertions(+), 42 deletions(-) diff --git a/include/libtorrent/policy.hpp b/include/libtorrent/policy.hpp index 9a41169c6..d5786e7fe 100755 --- a/include/libtorrent/policy.hpp +++ b/include/libtorrent/policy.hpp @@ -96,6 +96,11 @@ namespace libtorrent void set_max_uploads(int num_unchoked); + /* + A limit on the number of sockets opened, for use on systems where a + user has a limited number of open file descriptors. And for windows + which has a buggy tcp-stack. + */ void set_max_connections(int num_connected); #ifndef NDEBUG diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index c254cbd0d..b30388980 100755 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -61,7 +61,6 @@ namespace libtorrent { return "invalid torrent handle used"; } }; - // TODO: put torrent_info in its own header struct torrent_status { torrent_status() diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index 443f3a8da..a1e7019e8 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -125,20 +125,23 @@ namespace libtorrent void convert_file_names(); - size_type piece_size(unsigned int index) const + size_type piece_size(int index) const { + assert(index >= 0 && index < num_pieces()); if (index == num_pieces()-1) { - size_type s = total_size() % m_piece_length; - return (s == 0)?m_piece_length:s; + size_type s = total_size() - (size_type)(num_pieces() - 1)*piece_length(); + assert(s > 0); + assert(s <= piece_length()); + return s; } else return piece_length(); } - const sha1_hash& hash_for_piece(unsigned int index) const + const sha1_hash& hash_for_piece(int index) const { - assert(index < m_piece_hash.size()); + assert(index >= 0 && index < (int)m_piece_hash.size()); return m_piece_hash[index]; } diff --git a/src/policy.cpp b/src/policy.cpp index d42f1bae7..c4ff608e9 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -280,7 +280,6 @@ namespace namespace libtorrent { - policy::policy(torrent* t) : m_num_peers(0) , m_torrent(t) diff --git a/src/storage.cpp b/src/storage.cpp index 006ae7477..2bf8bb282 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -426,7 +426,6 @@ namespace libtorrent void allocate_slots(int num_slots); void mark_failed(int index); - unsigned long piece_crc( int slot_index , int block_size @@ -445,6 +444,7 @@ namespace libtorrent private: // returns the slot currently associated with the given // piece or assigns the given piece_index to a free slot + int allocate_slot_for_piece(int piece_index); #ifndef NDEBUG void check_invariant() const; @@ -554,7 +554,7 @@ namespace libtorrent #ifndef NDEBUG check_invariant(); #endif - assert(piece_index >= 0 && piece_index < m_piece_to_slot.size()); + assert(piece_index >= 0 && (unsigned)piece_index < m_piece_to_slot.size()); assert(m_piece_to_slot[piece_index] >= 0); int slot_index = m_piece_to_slot[piece_index]; @@ -634,8 +634,13 @@ namespace libtorrent , size_type offset , size_type size) { + assert(buf); + assert(offset >= 0); + assert(size > 0); + assert(piece_index >= 0 && (unsigned)piece_index < m_piece_to_slot.size()); assert(m_piece_to_slot[piece_index] >= 0); int slot = m_piece_to_slot[piece_index]; + assert(slot >= 0 && slot < (int)m_slot_to_piece.size()); return m_storage.read(buf, slot, offset, size); } @@ -654,7 +659,13 @@ namespace libtorrent , size_type offset , size_type size) { + assert(buf); + assert(offset >= 0); + assert(size > 0); + assert(piece_index >= 0 && (unsigned)piece_index < m_piece_to_slot.size()); + assert(m_piece_to_slot[piece_index] >= 0); int slot = allocate_slot_for_piece(piece_index); + assert(slot >= 0 && (unsigned)slot < m_slot_to_piece.size()); m_storage.write(buf, slot, offset, size); } @@ -678,9 +689,15 @@ namespace libtorrent boost::recursive_mutex::scoped_lock lock(m_mutex); // ---------------------------------------------------------------------- +#ifndef NDEBUG + check_invariant(); +#endif + m_allocating = false; m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot); m_slot_to_piece.resize(m_info.num_pieces(), unallocated); + m_free_slots.resize(0); + m_unallocated_slots.resize(0); const std::size_t piece_size = m_info.piece_length(); const std::size_t last_piece_size = m_info.piece_size( @@ -693,7 +710,7 @@ namespace libtorrent if (!data.piece_map.empty() && data.piece_map.size() <= m_slot_to_piece.size()) { - for (int i = 0; i < data.piece_map.size(); ++i) + for (int i = 0; (unsigned)i < data.piece_map.size(); ++i) { m_slot_to_piece[i] = data.piece_map[i]; if (data.piece_map[i] >= 0) @@ -723,10 +740,13 @@ namespace libtorrent } } - for (int i = data.piece_map.size(); i < pieces.size(); ++i) + for (int i = data.piece_map.size(); (unsigned)i < pieces.size(); ++i) { m_unallocated_slots.push_back(i); } +#ifndef NDEBUG + check_invariant(); +#endif return; } @@ -742,7 +762,7 @@ namespace libtorrent std::size_t piece_offset = 0; int current_slot = 0; - std::size_t bytes_to_read = piece_size; + std::size_t bytes_to_read = m_info.piece_size(0); size_type bytes_current_read = 0; size_type seek_into_next = 0; size_type filesize = 0; @@ -758,6 +778,9 @@ namespace libtorrent end_iter = m_info.end_files(); file_iter != end_iter;) { + assert(current_slot>=0 && current_slotpath); // if the path doesn't exist, create the @@ -805,6 +826,7 @@ namespace libtorrent if (filesize > 0) { bytes_read = in.read(&piece_data[piece_offset], bytes_to_read); + assert(bytes_read>0); } bytes_current_read += bytes_read; @@ -843,7 +865,14 @@ namespace libtorrent ++file_iter; continue; } - + + assert(current_slot < m_info.num_pieces()); + assert(m_slot_to_piece[current_slot]==unallocated); + assert(m_piece_to_slot[current_slot]==has_no_slot || + (m_piece_to_slot[current_slot]>=0 && + m_piece_to_slot[current_slot]get(); + (i == m_info.num_pieces() - 1) ? 1 : 0]->get(); if (hash == m_info.hash_for_piece(i)) { @@ -880,32 +910,35 @@ namespace libtorrent // bytes_left if (pieces[found_piece]) { - assert(m_piece_to_slot[found_piece] >= 0); - assert(m_piece_to_slot[found_piece] < m_slot_to_piece.size()); + assert(m_piece_to_slot[found_piece] == current_slot); m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned; m_free_slots.push_back(m_piece_to_slot[found_piece]); + m_piece_to_slot[found_piece]=has_no_slot; } + assert(m_piece_to_slot[found_piece]==has_no_slot); m_piece_to_slot[found_piece] = current_slot; m_slot_to_piece[current_slot] = found_piece; pieces[found_piece] = true; } else { + assert(found_piece==-1); m_slot_to_piece[current_slot] = unassigned; - size_type last_pos = - m_info.total_size() - - m_info.piece_size( - m_info.num_pieces() - 1); - m_free_slots.push_back(current_slot); } + assert(m_slot_to_piece[current_slot]!=unallocated); + // done with piece, move on to next piece_offset = 0; ++current_slot; - + if(current_slot==m_info.num_pieces()) + { + assert(file_iter == end_iter-1); + break; + } bytes_to_read = m_info.piece_size(current_slot); } @@ -951,15 +984,14 @@ namespace libtorrent check_invariant(); #endif - assert(piece_index >= 0 && piece_index < m_piece_to_slot.size()); + assert(piece_index >= 0 && (unsigned)piece_index < m_piece_to_slot.size()); assert(m_piece_to_slot.size() == m_slot_to_piece.size()); int slot_index = m_piece_to_slot[piece_index]; if (slot_index != has_no_slot) { - assert(slot_index >= 0); - assert(slot_index < m_slot_to_piece.size()); + assert(slot_index >= 0 && (unsigned)slot_index < m_slot_to_piece.size()); #ifndef NDEBUG check_invariant(); @@ -1053,6 +1085,8 @@ namespace libtorrent #endif } + assert(slot_index>=0 && (unsigned)slot_index < m_slot_to_piece.size()); + #ifndef NDEBUG check_invariant(); #endif @@ -1061,6 +1095,8 @@ namespace libtorrent void piece_manager::impl::allocate_slots(int num_slots) { + assert(num_slots>0); + { boost::mutex::scoped_lock lock(m_allocating_monitor); @@ -1117,6 +1153,8 @@ namespace libtorrent m_unallocated_slots.erase(m_unallocated_slots.begin(), iter); m_allocating = false; + + assert(m_free_slots.size()>0); #ifndef NDEBUG check_invariant(); @@ -1139,15 +1177,56 @@ namespace libtorrent // synchronization ------------------------------------------------------ boost::recursive_mutex::scoped_lock lock(m_mutex); // ---------------------------------------------------------------------- + if (m_piece_to_slot.empty()) return; + + assert(m_piece_to_slot.size() == m_info.num_pieces()); + assert(m_slot_to_piece.size() == m_info.num_pieces()); + + for(int i=0;(unsigned)i= 0) - assert(m_slot_to_piece[i] == unallocated); + // Check that piece_to_slot's elements are within bounds + assert(m_piece_to_slot[i]==has_no_slot + ||(m_piece_to_slot[i]>=0 && (unsigned)m_piece_to_slot[i]=0 && (unsigned)m_slot_to_piece[i]=0) + { + assert(m_slot_to_piece[m_piece_to_slot[i]]==i); + if (m_piece_to_slot[i] != i) + { + assert(m_slot_to_piece[i] == unallocated); + } + } + else + { + assert(m_piece_to_slot[i]==has_no_slot); + } + + // do more detailed checks on slot_to_piece if (m_slot_to_piece[i]>=0) { - assert(m_slot_to_piece[i]= '0' && *i <= '9') high=*i - '0'; + else if(*i >= 'A' && *i <= 'F') high=*i + 10 - 'A'; + else if(*i >= 'a' && *i <= 'f') high=*i + 10 - 'a'; + else throw std::runtime_error("invalid escaped string"); + + ++i; if (i == s.end()) throw std::runtime_error("invalid escaped string"); - ++i; - int low = *i - '0'; - if (high >= 16 || low >= 16 || high < 0 || low < 0) - throw std::runtime_error("invalid escaped string"); + int low; + if(*i >= '0' && *i <= '9') low=*i - '0'; + else if(*i >= 'A' && *i <= 'F') low=*i + 10 - 'A'; + else if(*i >= 'a' && *i <= 'f') low=*i + 10 - 'a'; + else throw std::runtime_error("invalid escaped string"); ret += char(high * 16 + low); } @@ -178,7 +192,9 @@ namespace libtorrent std::string escape_string(const char* str, int len) { - static const char special_chars[] = "$-_.+!*'(),"; + // http://www.ietf.org/rfc/rfc2396.txt + // section 2.3 + static const char unreserved_chars[] = "-_.!~*'()"; std::stringstream ret; ret << std::hex << std::setfill('0'); @@ -186,15 +202,15 @@ namespace libtorrent { if (std::isalnum(static_cast(*str)) || std::count( - special_chars - , special_chars+sizeof(special_chars)-1 + unreserved_chars + , unreserved_chars+sizeof(unreserved_chars)-1 , *str)) { ret << *str; } else { - ret << "%" + ret << '%' << std::setw(2) << (int)static_cast(*str); } @@ -582,7 +598,7 @@ namespace libtorrent { m_currently_trying_tracker++; - if (m_currently_trying_tracker >= m_torrent_file.trackers().size()) + if ((unsigned)m_currently_trying_tracker >= m_torrent_file.trackers().size()) { // if we've looped the tracker list, wait a bit before retrying m_currently_trying_tracker = 0;