From d9e10440f343d41134e19470619b93ca77ce51fc Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 24 Mar 2005 12:13:47 +0000 Subject: [PATCH] fixed assert bug in policy and generalized the tracker_connection observer interface a bit --- .../libtorrent/http_tracker_connection.hpp | 2 + include/libtorrent/torrent.hpp | 10 ++-- include/libtorrent/tracker_manager.hpp | 21 +++++--- include/libtorrent/udp_tracker_connection.hpp | 2 + src/escape_string.cpp | 2 +- src/http_tracker_connection.cpp | 51 +++++++++---------- src/policy.cpp | 18 +++---- src/torrent.cpp | 12 +++-- src/tracker_manager.cpp | 15 +++--- src/udp_tracker_connection.cpp | 21 +++++--- 10 files changed, 88 insertions(+), 66 deletions(-) diff --git a/include/libtorrent/http_tracker_connection.hpp b/include/libtorrent/http_tracker_connection.hpp index 8b4e47c27..68740c6c1 100755 --- a/include/libtorrent/http_tracker_connection.hpp +++ b/include/libtorrent/http_tracker_connection.hpp @@ -77,6 +77,8 @@ namespace libtorrent virtual bool tick(); virtual bool send_finished() const { return m_send_buffer.empty(); } + virtual tracker_request const& tracker_req() const + { return m_req; } private: diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 3d7516f8e..296f0f5bb 100755 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -192,10 +192,14 @@ namespace libtorrent // (either http_tracker_connection or udp_tracker_connection) // when this torrent got a response from its tracker request // or when a failure occured - virtual void tracker_response(std::vector& e, int interval + virtual void tracker_response( + tracker_request const& r + , std::vector& e, int interval , int complete, int incomplete); - virtual void tracker_request_timed_out(); - virtual void tracker_request_error(int response_code, const std::string& str); + virtual void tracker_request_timed_out( + tracker_request const& r); + virtual void tracker_request_error(tracker_request const& r + , int response_code, const std::string& str); // generates a request string for sending // to the tracker diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index c64a1476a..101749b5d 100755 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -70,11 +70,6 @@ namespace libtorrent // returns -1 if gzip header is invalid or the header size in bytes int gzip_header(const char* buf, int size); - bool inflate_gzip( - std::vector& buffer - , request_callback* requester - , int maximum_tracker_response_length); - struct tracker_request { tracker_request() @@ -116,13 +111,16 @@ namespace libtorrent request_callback(): m_manager(0) {} virtual ~request_callback() {} virtual void tracker_response( - std::vector& peers + tracker_request const& + , std::vector& peers , int interval , int complete , int incomplete) = 0; - virtual void tracker_request_timed_out() = 0; + virtual void tracker_request_timed_out( + tracker_request const&) = 0; virtual void tracker_request_error( - int response_code + tracker_request const& + , int response_code , const std::string& description) = 0; address m_tracker_address; @@ -134,6 +132,12 @@ namespace libtorrent tracker_manager* m_manager; }; + bool inflate_gzip( + std::vector& buffer + , tracker_request const& req + , request_callback* requester + , int maximum_tracker_response_length); + struct tracker_connection: boost::noncopyable { tracker_connection(boost::weak_ptr r) @@ -145,6 +149,7 @@ namespace libtorrent bool has_requester() const { return !m_requester.expired(); } request_callback& requester(); virtual ~tracker_connection() {} + virtual tracker_request const& tracker_req() const = 0; protected: diff --git a/include/libtorrent/udp_tracker_connection.hpp b/include/libtorrent/udp_tracker_connection.hpp index da980229b..055fffb5b 100755 --- a/include/libtorrent/udp_tracker_connection.hpp +++ b/include/libtorrent/udp_tracker_connection.hpp @@ -73,6 +73,8 @@ namespace libtorrent virtual bool tick(); virtual bool send_finished() const; + virtual tracker_request const& tracker_req() const + { return m_request; } private: diff --git a/src/escape_string.cpp b/src/escape_string.cpp index ada4b01a9..c531513e6 100755 --- a/src/escape_string.cpp +++ b/src/escape_string.cpp @@ -102,7 +102,7 @@ namespace libtorrent "0123456789"; std::stringstream ret; - ret << std::hex << std::setfill('0'); + ret << std::hex << std::setfill('0'); for (int i = 0; i < len; ++i) { if (std::count( diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index b81cfc8f5..43c7eec59 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -131,7 +131,7 @@ namespace libtorrent if (m_req.kind == tracker_request::scrape_request) { - // TODO: find and replace "announce" with "scrape" + // find and replace "announce" with "scrape" // in request std::size_t pos = request.find("announce"); @@ -242,7 +242,7 @@ namespace libtorrent if (d > seconds(m_settings.tracker_timeout) || (!has_requester() && d > seconds(m_settings.stop_tracker_timeout))) { - if (has_requester()) requester().tracker_request_timed_out(); + if (has_requester()) requester().tracker_request_timed_out(m_req); return true; } @@ -278,7 +278,7 @@ namespace libtorrent if (m_socket->has_error()) { if (has_requester()) requester().tracker_request_error( - -1, "connection refused"); + m_req, -1, "connection refused"); return true; } @@ -298,8 +298,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - 200 + requester().tracker_request_error(m_req, 200 , "too large tracker response"); } return true; @@ -327,8 +326,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - -1 + requester().tracker_request_error(m_req, -1 , "invalid tracker response, connection closed"); } return true; @@ -353,7 +351,7 @@ namespace libtorrent if (m_server_protocol.substr(0, 5) != "HTTP/") { std::string error_msg = "unknown protocol in response: " + m_server_protocol; - if (has_requester()) requester().tracker_request_error(-1, error_msg.c_str()); + if (has_requester()) requester().tracker_request_error(m_req, -1, error_msg.c_str()); return true; } line >> m_code; @@ -366,8 +364,9 @@ namespace libtorrent if (received <= 0) { if (has_requester()) - requester().tracker_request_error(-1, "invalid tracker " - "response, connection closed while reading header"); + requester().tracker_request_error(m_req, -1 + , "invalid tracker response, connection closed " + "while reading header"); return true; } @@ -395,8 +394,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - -1, + requester().tracker_request_error(m_req, -1, "invalid content-length in tracker response"); } return true; @@ -405,8 +403,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - -1 + requester().tracker_request_error(m_req, -1 , "content-length is greater than maximum response length"); } return true; @@ -416,8 +413,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - -1 + requester().tracker_request_error(m_req, -1 , "content-length is smaller than minimum response length"); } return true; @@ -435,7 +431,8 @@ namespace libtorrent error_str += line.substr(18, line.length() - 18 - 2); error_str += "\""; if (has_requester()) - requester().tracker_request_error(-1, error_str.c_str()); + requester().tracker_request_error(m_req, -1 + , error_str.c_str()); return true; } } @@ -461,7 +458,8 @@ namespace libtorrent error_str += boost::lexical_cast(m_code); error_str += ") without 'Location' header"; if (has_requester()) - requester().tracker_request_error(m_code, error_str.c_str()); + requester().tracker_request_error(m_req + , m_code, error_str.c_str()); return true; } @@ -499,7 +497,7 @@ namespace libtorrent { boost::shared_ptr r = m_requester.lock(); if (!r) return true; - if (inflate_gzip(m_buffer, r.get(), + if (inflate_gzip(m_buffer, m_req, r.get(), m_settings.tracker_maximum_response_length)) return true; } @@ -515,8 +513,7 @@ namespace libtorrent { if (has_requester()) { - requester().tracker_request_error( - -1 + requester().tracker_request_error(m_req, -1 , "invalid tracker response (body > content_length)"); } return true; @@ -532,7 +529,7 @@ namespace libtorrent throw; } #endif -} + } peer_entry http_tracker_connection::extract_peer_info(const entry& info) { @@ -577,7 +574,7 @@ namespace libtorrent entry const& failure = e["failure reason"]; if (has_requester()) requester().tracker_request_error( - m_code, failure.string().c_str()); + m_req, m_code, failure.string().c_str()); return; } catch (type_error const&) {} @@ -592,7 +589,7 @@ namespace libtorrent entry scrape_data = e["files"][ih]; int complete = scrape_data["complete"].integer(); int incomplete = scrape_data["incomplete"].integer(); - requester().tracker_response(peer_list, 0, complete + requester().tracker_response(m_req, peer_list, 0, complete , incomplete); return; } @@ -639,16 +636,16 @@ namespace libtorrent try { incomplete = e["incomplete"].integer(); } catch(type_error& e) {} - requester().tracker_response(peer_list, interval, complete + requester().tracker_response(m_req, peer_list, interval, complete , incomplete); } catch(type_error& e) { - requester().tracker_request_error(-1, e.what()); + requester().tracker_request_error(m_req, -1, e.what()); } catch(std::runtime_error& e) { - requester().tracker_request_error(-1, e.what()); + requester().tracker_request_error(m_req, -1, e.what()); } } diff --git a/src/policy.cpp b/src/policy.cpp index 4c27c6ba9..cee9b0806 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -345,8 +345,7 @@ namespace libtorrent // TODO: make this selection better for (std::vector::iterator i = m_peers.begin(); - i != m_peers.end(); - ++i) + i != m_peers.end(); ++i) { peer_connection* c = i->connection; @@ -389,16 +388,15 @@ namespace libtorrent // TODO: make this selection better for (std::vector::iterator i = m_peers.begin(); - i != m_peers.end(); - ++i) + i != m_peers.end(); ++i) { peer_connection* c = i->connection; if (c == 0) continue; if (c->is_disconnecting()) continue; if (!c->is_choked()) continue; if (!c->is_peer_interested()) continue; - if (c->share_diff() - < -free_upload_amount) continue; + if (c->share_diff() < -free_upload_amount + && m_torrent->ratio() != 0) continue; if (c->statistics().download_rate() < max_down_speed) continue; // if (i->last_optimistically_unchoked > min_time) continue; @@ -613,7 +611,7 @@ namespace libtorrent // every minute, disconnect the worst peer in hope of finding a better peer boost::posix_time::ptime local_time = second_clock::universal_time(); - if(m_last_optimistic_disconnect + boost::posix_time::seconds(120) <= local_time) + if (m_last_optimistic_disconnect + boost::posix_time::seconds(120) <= local_time) { m_last_optimistic_disconnect = local_time; --max_connections; // this will have the effect of disconnecting the worst peer @@ -627,7 +625,8 @@ namespace libtorrent while (num_connected_peers > max_connections) { - assert(disconnect_one_peer()); + bool ret = disconnect_one_peer(); + assert(ret); --num_connected_peers; } } @@ -714,8 +713,7 @@ namespace libtorrent { // choke peers that have leeched too much without giving anything back for (std::vector::iterator i = m_peers.begin(); - i != m_peers.end(); - ++i) + i != m_peers.end(); ++i) { peer_connection* c = i->connection; if (c == 0) continue; diff --git a/src/torrent.cpp b/src/torrent.cpp index 18db4c480..47304260d 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -280,7 +280,8 @@ namespace libtorrent } void torrent::tracker_response( - std::vector& peer_list + tracker_request const& r + , std::vector& peer_list , int interval , int complete , int incomplete) @@ -1259,11 +1260,13 @@ namespace libtorrent for (int i = req.first; i < req.first + req.second; ++i) { assert(m_requested_metadata[i] > 0); - --m_requested_metadata[i]; + if (m_requested_metadata[i] > 0) + --m_requested_metadata[i]; } } - void torrent::tracker_request_timed_out() + void torrent::tracker_request_timed_out( + tracker_request const&) { #ifdef TORRENT_VERBOSE_LOGGING debug_log("*** tracker timed out"); @@ -1283,7 +1286,8 @@ namespace libtorrent // TODO: with some response codes, we should just consider // the tracker as a failure and not retry // it anymore - void torrent::tracker_request_error(int response_code, const std::string& str) + void torrent::tracker_request_error(tracker_request const& r + , int response_code, const std::string& str) { #ifdef TORRENT_VERBOSE_LOGGING debug_log(std::string("*** tracker error: ") + str); diff --git a/src/tracker_manager.cpp b/src/tracker_manager.cpp index 19d360a48..24850a7f5 100755 --- a/src/tracker_manager.cpp +++ b/src/tracker_manager.cpp @@ -197,6 +197,7 @@ namespace libtorrent bool inflate_gzip( std::vector& buffer + , tracker_request const& req , request_callback* requester , int maximum_tracker_response_length) { @@ -205,7 +206,7 @@ namespace libtorrent int header_len = gzip_header(&buffer[0], (int)buffer.size()); if (header_len < 0) { - requester->tracker_request_error(200, "invalid gzip header in tracker response"); + requester->tracker_request_error(req, 200, "invalid gzip header in tracker response"); return true; } @@ -229,7 +230,7 @@ namespace libtorrent // and just deflate the buffer if (inflateInit2(&str, -15) != Z_OK) { - requester->tracker_request_error(200, "gzip out of memory"); + requester->tracker_request_error(req, 200, "gzip out of memory"); return true; } @@ -242,7 +243,8 @@ namespace libtorrent if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length) { inflateEnd(&str); - requester->tracker_request_error(200, "tracker response too large"); + requester->tracker_request_error(req, 200 + , "tracker response too large"); return true; } int new_size = (int)inflate_buffer.size() * 2; @@ -262,7 +264,7 @@ namespace libtorrent if (ret != Z_STREAM_END) { - requester->tracker_request_error(200, "gzip error"); + requester->tracker_request_error(req, 200, "gzip error"); return true; } @@ -351,7 +353,8 @@ namespace libtorrent catch (const std::exception& e) { if (c->has_requester()) - c->requester().tracker_request_error(-1, e.what()); + c->requester().tracker_request_error(c->tracker_req() + , -1, e.what()); } if (c->has_requester()) c->requester().m_manager = 0; i = m_connections.erase(i); @@ -469,7 +472,7 @@ namespace libtorrent if (!c.expired()) { boost::shared_ptr r = c.lock(); - r->tracker_request_error(-1, e.what()); + r->tracker_request_error(req, -1, e.what()); } } } diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index bfcf975c2..3d4c14b0b 100755 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -106,7 +106,8 @@ namespace libtorrent { if (m_attempts >= udp_connection_retries) { - if (has_requester()) requester().tracker_request_timed_out(); + if (has_requester()) + requester().tracker_request_timed_out(m_request); return true; } send_udp_connect(); @@ -118,7 +119,8 @@ namespace libtorrent { if (m_attempts >= udp_announce_retries) { - if (has_requester()) requester().tracker_request_timed_out(); + if (has_requester()) + requester().tracker_request_timed_out(m_request); return true; } @@ -140,7 +142,8 @@ namespace libtorrent if (ret == udp_buffer_size) { if (has_requester()) - requester().tracker_request_error(-1, "tracker reply too big"); + requester().tracker_request_error( + m_request, -1, "tracker reply too big"); return true; } @@ -239,7 +242,8 @@ namespace libtorrent if (action == error) { if (has_requester()) - requester().tracker_request_error(-1, std::string(buf, buf + len - 8)); + requester().tracker_request_error( + m_request, -1, std::string(buf, buf + len - 8)); return true; } if (action != announce) return false; @@ -260,7 +264,8 @@ namespace libtorrent if ((len - 24) % 6 != 0) { if (has_requester()) - requester().tracker_request_error(-1, "invalid tracker response"); + requester().tracker_request_error( + m_request, -1, "invalid tracker response"); return true; } @@ -281,7 +286,8 @@ namespace libtorrent peer_list.push_back(e); } - requester().tracker_response(peer_list, interval, complete, incomplete); + requester().tracker_response(m_request, peer_list, interval + , complete, incomplete); return true; } @@ -306,7 +312,8 @@ namespace libtorrent if (action == error) { if (has_requester()) - requester().tracker_request_error(-1, std::string(ptr, buf + len)); + requester().tracker_request_error( + m_request, -1, std::string(ptr, buf + len)); return true; } if (action != connect) return false;