web seed fix

This commit is contained in:
Arvid Norberg 2009-04-11 20:45:14 +00:00
parent 1c01c9ce98
commit 90ce06bb47
8 changed files with 78 additions and 42 deletions

View File

@ -46,6 +46,9 @@ namespace libtorrent
boost::array<char, 3 + std::numeric_limits<size_type>::digits10> TORRENT_EXPORT to_string(size_type n);
bool TORRENT_EXPORT is_digit(char c);
bool TORRENT_EXPORT isprint(char c);
char TORRENT_EXPORT to_lower(char c);
bool TORRENT_EXPORT string_begins_no_case(char const* s1, char const* s2);
std::string TORRENT_EXPORT unescape_string(std::string const& s, error_code& ec);
std::string TORRENT_EXPORT escape_string(const char* str, int len);
@ -75,3 +78,4 @@ namespace libtorrent
}
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED

View File

@ -161,10 +161,8 @@ namespace libtorrent
bool m_first_request;
// this is used for intermediate storage of pieces
// that is received in more than on HTTP responses
// that are received in more than one HTTP response
std::vector<char> m_piece;
// the mapping of the data in the m_piece buffer
peer_request m_intermediate_piece;
// the number of bytes into the receive buffer where
// current read cursor is.
@ -176,6 +174,9 @@ namespace libtorrent
// position in the current range response
int m_range_pos;
// the position in the current block
int m_block_pos;
};
}

View File

@ -90,6 +90,22 @@ namespace libtorrent
return c >= 32 && c < 127;
}
char to_lower(char c)
{
return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c;
}
bool string_begins_no_case(char const* s1, char const* s2)
{
while (*s1 != 0)
{
if (to_lower(*s1) != to_lower(*s2)) return false;
++s1;
++s2;
}
return true;
}
std::string unescape_string(std::string const& s, error_code& ec)
{
std::string ret;

View File

@ -39,14 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp"
#include "libtorrent/http_parser.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/escape_string.hpp"
using namespace libtorrent;
namespace
{
char to_lower(char c) { return std::tolower(c); }
}
namespace libtorrent
{
http_parser::http_parser()

View File

@ -1680,6 +1680,8 @@ namespace libtorrent
m_last_piece = time_now();
m_outstanding_bytes -= bytes;
#ifdef TORRENT_DEBUG
boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(m_received_in_piece + bytes <= t->block_size());
m_received_in_piece += bytes;
#endif
#if !defined TORRENT_DISABLE_INVARIANT_CHECKS && defined TORRENT_DEBUG
@ -1820,6 +1822,7 @@ namespace libtorrent
if ((*i)->on_piece(p, data))
{
#ifdef TORRENT_DEBUG
TORRENT_ASSERT(m_received_in_piece == p.length);
m_received_in_piece = 0;
#endif
return;
@ -1861,6 +1864,7 @@ namespace libtorrent
if (t->is_seed())
{
#ifdef TORRENT_DEBUG
TORRENT_ASSERT(m_received_in_piece == p.length);
m_received_in_piece = 0;
#endif
if (!m_download_queue.empty()) m_download_queue.erase(m_download_queue.begin());
@ -1897,6 +1901,7 @@ namespace libtorrent
"request queue ***\n";
#endif
#ifdef TORRENT_DEBUG
TORRENT_ASSERT(m_received_in_piece == p.length);
m_received_in_piece = 0;
#endif
t->add_redundant_bytes(p.length);

View File

@ -66,6 +66,7 @@ namespace libtorrent
, m_url(url)
, m_first_request(true)
, m_range_pos(0)
, m_block_pos(0)
{
INVARIANT_CHECK;
@ -124,23 +125,12 @@ namespace libtorrent
piece_block_progress ret;
ret.piece_index = m_requests.front().piece;
if (!m_piece.empty())
{
ret.bytes_downloaded = int(m_piece.size());
}
ret.bytes_downloaded = m_block_pos;
if (m_block_pos)
ret.block_index = (m_requests.front().start + m_block_pos - 1) / t->block_size();
else
{
if (!m_parser.header_finished())
{
ret.bytes_downloaded = 0;
}
else
{
int receive_buffer_size = receive_buffer().left() - m_parser.body_start();
ret.bytes_downloaded = receive_buffer_size % t->block_size();
}
}
ret.block_index = (m_requests.front().start + ret.bytes_downloaded) / t->block_size();
ret.block_index = (m_requests.front().start + m_block_pos) / t->block_size();
ret.full_block_bytes = t->block_size();
const int last_piece = t->torrent_file().num_pieces() - 1;
if (ret.piece_index == last_piece && ret.block_index
@ -494,6 +484,8 @@ namespace libtorrent
bool success = true;
char const* ptr = range_str.c_str();
if (string_begins_no_case("bytes ", ptr)) ptr += 6;
else success = false;
char* end;
range_start = strtoll(ptr, &end, 10);
if (end == ptr) success = false;
@ -533,19 +525,6 @@ namespace libtorrent
}
}
int left_in_response = range_end - range_start - m_range_pos;
int payload_transferred = (std::min)(left_in_response, int(bytes_transferred));
m_statistics.received_bytes(payload_transferred, 0);
incoming_piece_fragment(payload_transferred);
bytes_transferred -= payload_transferred;
m_range_pos += payload_transferred;;
if (m_range_pos > range_end - range_start) m_range_pos = range_end - range_start;
// std::cerr << "REQUESTS: m_requests: " << m_requests.size()
// << " file_requests: " << m_file_requests.size() << std::endl;
torrent_info const& info = t->torrent_file();
if (m_requests.empty() || m_file_requests.empty())
{
m_statistics.received_bytes(0, bytes_transferred);
@ -553,12 +532,31 @@ namespace libtorrent
return;
}
int left_in_response = range_end - range_start - m_range_pos;
int payload_transferred = (std::min)(left_in_response, int(bytes_transferred));
torrent_info const& info = t->torrent_file();
peer_request front_request = m_requests.front();
TORRENT_ASSERT(m_block_pos >= 0);
if (m_block_pos + payload_transferred > front_request.length)
payload_transferred = front_request.length - m_block_pos;
m_statistics.received_bytes(payload_transferred, 0);
incoming_piece_fragment(payload_transferred);
bytes_transferred -= payload_transferred;
m_range_pos += payload_transferred;
m_block_pos += payload_transferred;
if (m_range_pos > range_end - range_start) m_range_pos = range_end - range_start;
// std::cerr << "REQUESTS: m_requests: " << m_requests.size()
// << " file_requests: " << m_file_requests.size() << std::endl;
int file_index = m_file_requests.front();
peer_request in_range = info.orig_files().map_file(file_index, range_start
, int(range_end - range_start));
peer_request front_request = m_requests.front();
size_type rs = size_type(in_range.piece) * info.piece_length() + in_range.start;
size_type re = rs + in_range.length;
size_type fs = size_type(front_request.piece) * info.piece_length() + front_request.start;
@ -618,9 +616,11 @@ namespace libtorrent
// will be disconnected, including this web seed. We need to
// check for the disconnect condition after the call.
m_requests.pop_front();
incoming_piece(front_request, &m_piece[0]);
m_requests.pop_front();
if (associated_torrent().expired()) return;
TORRENT_ASSERT(m_block_pos == front_request.length);
m_block_pos = 0;
cut_receive_buffer(m_body_start, t->block_size() + 1024);
m_body_start = 0;
recv_buffer = receive_buffer();
@ -636,11 +636,13 @@ namespace libtorrent
&& recv_buffer.left() >= m_requests.front().length)
{
peer_request r = m_requests.front();
m_requests.pop_front();
TORRENT_ASSERT(recv_buffer.left() >= r.length);
incoming_piece(r, recv_buffer.begin);
m_requests.pop_front();
if (associated_torrent().expired()) return;
TORRENT_ASSERT(m_block_pos == front_request.length);
m_block_pos = 0;
m_received_body += r.length;
TORRENT_ASSERT(receive_buffer().begin + m_body_start == recv_buffer.begin);
TORRENT_ASSERT(m_received_body <= range_end - range_start);

View File

@ -363,6 +363,18 @@ int test_main()
to_hex(bin, 20, hex);
TEST_CHECK(strcmp(hex, str) == 0);
// test to_lower
TEST_CHECK(to_lower('C') == 'c');
TEST_CHECK(to_lower('c') == 'c');
TEST_CHECK(to_lower('-') == '-');
TEST_CHECK(to_lower('&') == '&');
// test string_begins_no_case
TEST_CHECK(string_begins_no_case("foobar", "FoobAR --"));
TEST_CHECK(!string_begins_no_case("foobar", "F00"));
// test itoa
TEST_CHECK(to_string(345).elems == std::string("345"));

View File

@ -58,7 +58,7 @@ void test_transfer(boost::intrusive_ptr<torrent_info> torrent_file, int proxy)
ses.set_settings(settings);
ses.set_alert_mask(~alert::progress_notification);
ses.listen_on(std::make_pair(51000, 52000));
ses.set_download_rate_limit(torrent_file->total_size() / 10);
ses.set_download_rate_limit(torrent_file->total_size() / 5);
remove_all("./tmp1");
char const* test_name[] = {"no", "SOCKS4", "SOCKS5", "SOCKS5 password", "HTTP", "HTTP password"};