diff --git a/include/libtorrent/escape_string.hpp b/include/libtorrent/escape_string.hpp index 99c08b21c..a07a3fe5a 100644 --- a/include/libtorrent/escape_string.hpp +++ b/include/libtorrent/escape_string.hpp @@ -46,6 +46,9 @@ namespace libtorrent boost::array::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 + diff --git a/include/libtorrent/web_peer_connection.hpp b/include/libtorrent/web_peer_connection.hpp index 51e8de7b4..8d8b1fb99 100644 --- a/include/libtorrent/web_peer_connection.hpp +++ b/include/libtorrent/web_peer_connection.hpp @@ -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 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; }; } diff --git a/src/escape_string.cpp b/src/escape_string.cpp index de7f723f6..0818ec780 100644 --- a/src/escape_string.cpp +++ b/src/escape_string.cpp @@ -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; diff --git a/src/http_parser.cpp b/src/http_parser.cpp index c8f5519af..80b0c0c53 100644 --- a/src/http_parser.cpp +++ b/src/http_parser.cpp @@ -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() diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 98bc79c6e..515405395 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1680,6 +1680,8 @@ namespace libtorrent m_last_piece = time_now(); m_outstanding_bytes -= bytes; #ifdef TORRENT_DEBUG + boost::shared_ptr 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); diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index ccf74ab99..0a8d53e88 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -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); diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index 19f27c1d0..b9894e89f 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -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")); diff --git a/test/test_web_seed.cpp b/test/test_web_seed.cpp index faa1dcce0..631d23d08 100644 --- a/test/test_web_seed.cpp +++ b/test/test_web_seed.cpp @@ -58,7 +58,7 @@ void test_transfer(boost::intrusive_ptr 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"};