*** empty log message ***

This commit is contained in:
Magnus Jonsson 2004-01-24 19:19:17 +00:00
parent 19a4dad706
commit 30329cc225
6 changed files with 143 additions and 42 deletions

View File

@ -96,6 +96,11 @@ namespace libtorrent
void set_max_uploads(int num_unchoked); 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); void set_max_connections(int num_connected);
#ifndef NDEBUG #ifndef NDEBUG

View File

@ -61,7 +61,6 @@ namespace libtorrent
{ return "invalid torrent handle used"; } { return "invalid torrent handle used"; }
}; };
// TODO: put torrent_info in its own header
struct torrent_status struct torrent_status
{ {
torrent_status() torrent_status()

View File

@ -125,20 +125,23 @@ namespace libtorrent
void convert_file_names(); 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) if (index == num_pieces()-1)
{ {
size_type s = total_size() % m_piece_length; size_type s = total_size() - (size_type)(num_pieces() - 1)*piece_length();
return (s == 0)?m_piece_length:s; assert(s > 0);
assert(s <= piece_length());
return s;
} }
else else
return piece_length(); 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]; return m_piece_hash[index];
} }

View File

@ -280,7 +280,6 @@ namespace
namespace libtorrent namespace libtorrent
{ {
policy::policy(torrent* t) policy::policy(torrent* t)
: m_num_peers(0) : m_num_peers(0)
, m_torrent(t) , m_torrent(t)

View File

@ -426,7 +426,6 @@ namespace libtorrent
void allocate_slots(int num_slots); void allocate_slots(int num_slots);
void mark_failed(int index); void mark_failed(int index);
unsigned long piece_crc( unsigned long piece_crc(
int slot_index int slot_index
, int block_size , int block_size
@ -445,6 +444,7 @@ namespace libtorrent
private: private:
// returns the slot currently associated with the given // returns the slot currently associated with the given
// piece or assigns the given piece_index to a free slot // piece or assigns the given piece_index to a free slot
int allocate_slot_for_piece(int piece_index); int allocate_slot_for_piece(int piece_index);
#ifndef NDEBUG #ifndef NDEBUG
void check_invariant() const; void check_invariant() const;
@ -554,7 +554,7 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
check_invariant(); check_invariant();
#endif #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); assert(m_piece_to_slot[piece_index] >= 0);
int slot_index = m_piece_to_slot[piece_index]; int slot_index = m_piece_to_slot[piece_index];
@ -634,8 +634,13 @@ namespace libtorrent
, size_type offset , size_type offset
, size_type size) , 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); assert(m_piece_to_slot[piece_index] >= 0);
int slot = m_piece_to_slot[piece_index]; 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); return m_storage.read(buf, slot, offset, size);
} }
@ -654,7 +659,13 @@ namespace libtorrent
, size_type offset , size_type offset
, size_type size) , 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); 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); m_storage.write(buf, slot, offset, size);
} }
@ -678,9 +689,15 @@ namespace libtorrent
boost::recursive_mutex::scoped_lock lock(m_mutex); boost::recursive_mutex::scoped_lock lock(m_mutex);
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
#ifndef NDEBUG
check_invariant();
#endif
m_allocating = false; m_allocating = false;
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot); m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
m_slot_to_piece.resize(m_info.num_pieces(), unallocated); 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 piece_size = m_info.piece_length();
const std::size_t last_piece_size = m_info.piece_size( const std::size_t last_piece_size = m_info.piece_size(
@ -693,7 +710,7 @@ namespace libtorrent
if (!data.piece_map.empty() if (!data.piece_map.empty()
&& data.piece_map.size() <= m_slot_to_piece.size()) && 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]; m_slot_to_piece[i] = data.piece_map[i];
if (data.piece_map[i] >= 0) 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); m_unallocated_slots.push_back(i);
} }
#ifndef NDEBUG
check_invariant();
#endif
return; return;
} }
@ -742,7 +762,7 @@ namespace libtorrent
std::size_t piece_offset = 0; std::size_t piece_offset = 0;
int current_slot = 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 bytes_current_read = 0;
size_type seek_into_next = 0; size_type seek_into_next = 0;
size_type filesize = 0; size_type filesize = 0;
@ -758,6 +778,9 @@ namespace libtorrent
end_iter = m_info.end_files(); end_iter = m_info.end_files();
file_iter != end_iter;) file_iter != end_iter;)
{ {
assert(current_slot>=0 && current_slot<m_info.num_pieces());
// Update progress meter and check if we've been requested to abort
{ {
boost::mutex::scoped_lock lock(mutex); boost::mutex::scoped_lock lock(mutex);
@ -766,8 +789,6 @@ namespace libtorrent
return; return;
} }
assert(current_slot <= m_info.num_pieces());
fs::path path(m_save_path / file_iter->path); fs::path path(m_save_path / file_iter->path);
// if the path doesn't exist, create the // if the path doesn't exist, create the
@ -805,6 +826,7 @@ namespace libtorrent
if (filesize > 0) if (filesize > 0)
{ {
bytes_read = in.read(&piece_data[piece_offset], bytes_to_read); bytes_read = in.read(&piece_data[piece_offset], bytes_to_read);
assert(bytes_read>0);
} }
bytes_current_read += bytes_read; bytes_current_read += bytes_read;
@ -844,6 +866,13 @@ namespace libtorrent
continue; 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]<current_slot &&
m_slot_to_piece[m_piece_to_slot[current_slot]]==current_slot));
// we need to take special actions if this is // we need to take special actions if this is
// the last piece, since that piece might actually // the last piece, since that piece might actually
// be smaller than piece_size. // be smaller than piece_size.
@ -859,12 +888,13 @@ namespace libtorrent
// TODO: there's still potential problems if some // TODO: there's still potential problems if some
// pieces have the same hash // pieces have the same hash
// for the file not to be corrupt, piece_index <= slot_index
for (int i = current_slot; i < m_info.num_pieces(); ++i) for (int i = current_slot; i < m_info.num_pieces(); ++i)
{ {
if (pieces[i] && i != current_slot) continue; if (pieces[i] && i != current_slot) continue;
const sha1_hash& hash = digest[ const sha1_hash& hash = digest[
i == m_info.num_pieces() - 1]->get(); (i == m_info.num_pieces() - 1) ? 1 : 0]->get();
if (hash == m_info.hash_for_piece(i)) if (hash == m_info.hash_for_piece(i))
{ {
@ -880,32 +910,35 @@ namespace libtorrent
// bytes_left // bytes_left
if (pieces[found_piece]) if (pieces[found_piece])
{ {
assert(m_piece_to_slot[found_piece] >= 0); assert(m_piece_to_slot[found_piece] == current_slot);
assert(m_piece_to_slot[found_piece] < m_slot_to_piece.size());
m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned; m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned;
m_free_slots.push_back(m_piece_to_slot[found_piece]); 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_piece_to_slot[found_piece] = current_slot;
m_slot_to_piece[current_slot] = found_piece; m_slot_to_piece[current_slot] = found_piece;
pieces[found_piece] = true; pieces[found_piece] = true;
} }
else else
{ {
assert(found_piece==-1);
m_slot_to_piece[current_slot] = unassigned; 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); m_free_slots.push_back(current_slot);
} }
assert(m_slot_to_piece[current_slot]!=unallocated);
// done with piece, move on to next // done with piece, move on to next
piece_offset = 0; piece_offset = 0;
++current_slot; ++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); bytes_to_read = m_info.piece_size(current_slot);
} }
@ -951,15 +984,14 @@ namespace libtorrent
check_invariant(); check_invariant();
#endif #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()); assert(m_piece_to_slot.size() == m_slot_to_piece.size());
int slot_index = m_piece_to_slot[piece_index]; int slot_index = m_piece_to_slot[piece_index];
if (slot_index != has_no_slot) if (slot_index != has_no_slot)
{ {
assert(slot_index >= 0); assert(slot_index >= 0 && (unsigned)slot_index < m_slot_to_piece.size());
assert(slot_index < m_slot_to_piece.size());
#ifndef NDEBUG #ifndef NDEBUG
check_invariant(); check_invariant();
@ -1053,6 +1085,8 @@ namespace libtorrent
#endif #endif
} }
assert(slot_index>=0 && (unsigned)slot_index < m_slot_to_piece.size());
#ifndef NDEBUG #ifndef NDEBUG
check_invariant(); check_invariant();
#endif #endif
@ -1061,6 +1095,8 @@ namespace libtorrent
void piece_manager::impl::allocate_slots(int num_slots) void piece_manager::impl::allocate_slots(int num_slots)
{ {
assert(num_slots>0);
{ {
boost::mutex::scoped_lock lock(m_allocating_monitor); boost::mutex::scoped_lock lock(m_allocating_monitor);
@ -1118,6 +1154,8 @@ namespace libtorrent
m_allocating = false; m_allocating = false;
assert(m_free_slots.size()>0);
#ifndef NDEBUG #ifndef NDEBUG
check_invariant(); check_invariant();
#endif #endif
@ -1139,15 +1177,56 @@ namespace libtorrent
// synchronization ------------------------------------------------------ // synchronization ------------------------------------------------------
boost::recursive_mutex::scoped_lock lock(m_mutex); 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<m_free_slots.size();++i)
{
unsigned slot=m_free_slots[i];
assert(slot<m_slot_to_piece.size());
assert(m_slot_to_piece[slot] == unassigned);
}
for(int i=0;(unsigned)i<m_unallocated_slots.size();++i)
{
unsigned slot=m_unallocated_slots[i];
assert(slot<m_slot_to_piece.size());
assert(m_slot_to_piece[slot] == unallocated);
}
for (int i = 0; i < m_info.num_pieces(); ++i) for (int i = 0; i < m_info.num_pieces(); ++i)
{ {
if (m_piece_to_slot[i] != i && m_piece_to_slot[i] >= 0) // 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]<m_slot_to_piece.size()));
// Check that piece_to_slot's elements are within bounds
assert(m_slot_to_piece[i]==unallocated
|| m_slot_to_piece[i]==unassigned
||(m_slot_to_piece[i]>=0 && (unsigned)m_slot_to_piece[i]<m_piece_to_slot.size()));
// do more detailed checks on piece_to_slot
if (m_piece_to_slot[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); 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) if (m_slot_to_piece[i]>=0)
{ {
assert(m_slot_to_piece[i]<m_piece_to_slot.size()); assert((unsigned)m_slot_to_piece[i]<m_piece_to_slot.size());
assert(m_piece_to_slot[m_slot_to_piece[i]]==i); assert(m_piece_to_slot[m_slot_to_piece[i]]==i);
#ifdef TORRENT_STORAGE_DEBUG #ifdef TORRENT_STORAGE_DEBUG
assert( assert(

View File

@ -153,21 +153,35 @@ namespace libtorrent
std::string ret; std::string ret;
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
{ {
if (*i != '%') ret += *i; if(*i == '+')
{
ret+=' ';
}
else if (*i != '%')
{
ret += *i;
}
else else
{ {
++i;
if (i == s.end()) if (i == s.end())
throw std::runtime_error("invalid escaped string"); throw std::runtime_error("invalid escaped string");
++i;
int high = *i - '0'; int high;
if(*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()) if (i == s.end())
throw std::runtime_error("invalid escaped string"); throw std::runtime_error("invalid escaped string");
++i;
int low = *i - '0'; int low;
if (high >= 16 || low >= 16 || high < 0 || low < 0) if(*i >= '0' && *i <= '9') low=*i - '0';
throw std::runtime_error("invalid escaped string"); 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); ret += char(high * 16 + low);
} }
@ -178,7 +192,9 @@ namespace libtorrent
std::string escape_string(const char* str, int len) 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; std::stringstream ret;
ret << std::hex << std::setfill('0'); ret << std::hex << std::setfill('0');
@ -186,15 +202,15 @@ namespace libtorrent
{ {
if (std::isalnum(static_cast<unsigned char>(*str)) if (std::isalnum(static_cast<unsigned char>(*str))
|| std::count( || std::count(
special_chars unreserved_chars
, special_chars+sizeof(special_chars)-1 , unreserved_chars+sizeof(unreserved_chars)-1
, *str)) , *str))
{ {
ret << *str; ret << *str;
} }
else else
{ {
ret << "%" ret << '%'
<< std::setw(2) << std::setw(2)
<< (int)static_cast<unsigned char>(*str); << (int)static_cast<unsigned char>(*str);
} }
@ -582,7 +598,7 @@ namespace libtorrent
{ {
m_currently_trying_tracker++; 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 // if we've looped the tracker list, wait a bit before retrying
m_currently_trying_tracker = 0; m_currently_trying_tracker = 0;