fixed assert bug in policy and generalized the tracker_connection observer interface a bit

This commit is contained in:
Arvid Norberg 2005-03-24 12:13:47 +00:00
parent d9e93a3e99
commit d9e10440f3
10 changed files with 88 additions and 66 deletions

View File

@ -77,6 +77,8 @@ namespace libtorrent
virtual bool tick(); virtual bool tick();
virtual bool send_finished() const virtual bool send_finished() const
{ return m_send_buffer.empty(); } { return m_send_buffer.empty(); }
virtual tracker_request const& tracker_req() const
{ return m_req; }
private: private:

View File

@ -192,10 +192,14 @@ namespace libtorrent
// (either http_tracker_connection or udp_tracker_connection) // (either http_tracker_connection or udp_tracker_connection)
// when this torrent got a response from its tracker request // when this torrent got a response from its tracker request
// or when a failure occured // or when a failure occured
virtual void tracker_response(std::vector<peer_entry>& e, int interval virtual void tracker_response(
tracker_request const& r
, std::vector<peer_entry>& e, int interval
, int complete, int incomplete); , int complete, int incomplete);
virtual void tracker_request_timed_out(); virtual void tracker_request_timed_out(
virtual void tracker_request_error(int response_code, const std::string& str); 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 // generates a request string for sending
// to the tracker // to the tracker

View File

@ -70,11 +70,6 @@ namespace libtorrent
// returns -1 if gzip header is invalid or the header size in bytes // returns -1 if gzip header is invalid or the header size in bytes
int gzip_header(const char* buf, int size); int gzip_header(const char* buf, int size);
bool inflate_gzip(
std::vector<char>& buffer
, request_callback* requester
, int maximum_tracker_response_length);
struct tracker_request struct tracker_request
{ {
tracker_request() tracker_request()
@ -116,13 +111,16 @@ namespace libtorrent
request_callback(): m_manager(0) {} request_callback(): m_manager(0) {}
virtual ~request_callback() {} virtual ~request_callback() {}
virtual void tracker_response( virtual void tracker_response(
std::vector<peer_entry>& peers tracker_request const&
, std::vector<peer_entry>& peers
, int interval , int interval
, int complete , int complete
, int incomplete) = 0; , 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( virtual void tracker_request_error(
int response_code tracker_request const&
, int response_code
, const std::string& description) = 0; , const std::string& description) = 0;
address m_tracker_address; address m_tracker_address;
@ -134,6 +132,12 @@ namespace libtorrent
tracker_manager* m_manager; tracker_manager* m_manager;
}; };
bool inflate_gzip(
std::vector<char>& buffer
, tracker_request const& req
, request_callback* requester
, int maximum_tracker_response_length);
struct tracker_connection: boost::noncopyable struct tracker_connection: boost::noncopyable
{ {
tracker_connection(boost::weak_ptr<request_callback> r) tracker_connection(boost::weak_ptr<request_callback> r)
@ -145,6 +149,7 @@ namespace libtorrent
bool has_requester() const { return !m_requester.expired(); } bool has_requester() const { return !m_requester.expired(); }
request_callback& requester(); request_callback& requester();
virtual ~tracker_connection() {} virtual ~tracker_connection() {}
virtual tracker_request const& tracker_req() const = 0;
protected: protected:

View File

@ -73,6 +73,8 @@ namespace libtorrent
virtual bool tick(); virtual bool tick();
virtual bool send_finished() const; virtual bool send_finished() const;
virtual tracker_request const& tracker_req() const
{ return m_request; }
private: private:

View File

@ -102,7 +102,7 @@ namespace libtorrent
"0123456789"; "0123456789";
std::stringstream ret; std::stringstream ret;
ret << std::hex << std::setfill('0'); ret << std::hex << std::setfill('0');
for (int i = 0; i < len; ++i) for (int i = 0; i < len; ++i)
{ {
if (std::count( if (std::count(

View File

@ -131,7 +131,7 @@ namespace libtorrent
if (m_req.kind == tracker_request::scrape_request) if (m_req.kind == tracker_request::scrape_request)
{ {
// TODO: find and replace "announce" with "scrape" // find and replace "announce" with "scrape"
// in request // in request
std::size_t pos = request.find("announce"); std::size_t pos = request.find("announce");
@ -242,7 +242,7 @@ namespace libtorrent
if (d > seconds(m_settings.tracker_timeout) || if (d > seconds(m_settings.tracker_timeout) ||
(!has_requester() && d > seconds(m_settings.stop_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; return true;
} }
@ -278,7 +278,7 @@ namespace libtorrent
if (m_socket->has_error()) if (m_socket->has_error())
{ {
if (has_requester()) requester().tracker_request_error( if (has_requester()) requester().tracker_request_error(
-1, "connection refused"); m_req, -1, "connection refused");
return true; return true;
} }
@ -298,8 +298,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, 200
200
, "too large tracker response"); , "too large tracker response");
} }
return true; return true;
@ -327,8 +326,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, -1
-1
, "invalid tracker response, connection closed"); , "invalid tracker response, connection closed");
} }
return true; return true;
@ -353,7 +351,7 @@ namespace libtorrent
if (m_server_protocol.substr(0, 5) != "HTTP/") if (m_server_protocol.substr(0, 5) != "HTTP/")
{ {
std::string error_msg = "unknown protocol in response: " + m_server_protocol; 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; return true;
} }
line >> m_code; line >> m_code;
@ -366,8 +364,9 @@ namespace libtorrent
if (received <= 0) if (received <= 0)
{ {
if (has_requester()) if (has_requester())
requester().tracker_request_error(-1, "invalid tracker " requester().tracker_request_error(m_req, -1
"response, connection closed while reading header"); , "invalid tracker response, connection closed "
"while reading header");
return true; return true;
} }
@ -395,8 +394,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, -1,
-1,
"invalid content-length in tracker response"); "invalid content-length in tracker response");
} }
return true; return true;
@ -405,8 +403,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, -1
-1
, "content-length is greater than maximum response length"); , "content-length is greater than maximum response length");
} }
return true; return true;
@ -416,8 +413,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, -1
-1
, "content-length is smaller than minimum response length"); , "content-length is smaller than minimum response length");
} }
return true; return true;
@ -435,7 +431,8 @@ namespace libtorrent
error_str += line.substr(18, line.length() - 18 - 2); error_str += line.substr(18, line.length() - 18 - 2);
error_str += "\""; error_str += "\"";
if (has_requester()) 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; return true;
} }
} }
@ -461,7 +458,8 @@ namespace libtorrent
error_str += boost::lexical_cast<std::string>(m_code); error_str += boost::lexical_cast<std::string>(m_code);
error_str += ") without 'Location' header"; error_str += ") without 'Location' header";
if (has_requester()) 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; return true;
} }
@ -499,7 +497,7 @@ namespace libtorrent
{ {
boost::shared_ptr<request_callback> r = m_requester.lock(); boost::shared_ptr<request_callback> r = m_requester.lock();
if (!r) return true; 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)) m_settings.tracker_maximum_response_length))
return true; return true;
} }
@ -515,8 +513,7 @@ namespace libtorrent
{ {
if (has_requester()) if (has_requester())
{ {
requester().tracker_request_error( requester().tracker_request_error(m_req, -1
-1
, "invalid tracker response (body > content_length)"); , "invalid tracker response (body > content_length)");
} }
return true; return true;
@ -532,7 +529,7 @@ namespace libtorrent
throw; throw;
} }
#endif #endif
} }
peer_entry http_tracker_connection::extract_peer_info(const entry& info) peer_entry http_tracker_connection::extract_peer_info(const entry& info)
{ {
@ -577,7 +574,7 @@ namespace libtorrent
entry const& failure = e["failure reason"]; entry const& failure = e["failure reason"];
if (has_requester()) requester().tracker_request_error( if (has_requester()) requester().tracker_request_error(
m_code, failure.string().c_str()); m_req, m_code, failure.string().c_str());
return; return;
} }
catch (type_error const&) {} catch (type_error const&) {}
@ -592,7 +589,7 @@ namespace libtorrent
entry scrape_data = e["files"][ih]; entry scrape_data = e["files"][ih];
int complete = scrape_data["complete"].integer(); int complete = scrape_data["complete"].integer();
int incomplete = scrape_data["incomplete"].integer(); int incomplete = scrape_data["incomplete"].integer();
requester().tracker_response(peer_list, 0, complete requester().tracker_response(m_req, peer_list, 0, complete
, incomplete); , incomplete);
return; return;
} }
@ -639,16 +636,16 @@ namespace libtorrent
try { incomplete = e["incomplete"].integer(); } try { incomplete = e["incomplete"].integer(); }
catch(type_error& e) {} catch(type_error& e) {}
requester().tracker_response(peer_list, interval, complete requester().tracker_response(m_req, peer_list, interval, complete
, incomplete); , incomplete);
} }
catch(type_error& e) 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) catch(std::runtime_error& e)
{ {
requester().tracker_request_error(-1, e.what()); requester().tracker_request_error(m_req, -1, e.what());
} }
} }

View File

@ -345,8 +345,7 @@ namespace libtorrent
// TODO: make this selection better // TODO: make this selection better
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); i != m_peers.end(); ++i)
++i)
{ {
peer_connection* c = i->connection; peer_connection* c = i->connection;
@ -389,16 +388,15 @@ namespace libtorrent
// TODO: make this selection better // TODO: make this selection better
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); i != m_peers.end(); ++i)
++i)
{ {
peer_connection* c = i->connection; peer_connection* c = i->connection;
if (c == 0) continue; if (c == 0) continue;
if (c->is_disconnecting()) continue; if (c->is_disconnecting()) continue;
if (!c->is_choked()) continue; if (!c->is_choked()) continue;
if (!c->is_peer_interested()) continue; if (!c->is_peer_interested()) continue;
if (c->share_diff() if (c->share_diff() < -free_upload_amount
< -free_upload_amount) continue; && m_torrent->ratio() != 0) continue;
if (c->statistics().download_rate() < max_down_speed) continue; if (c->statistics().download_rate() < max_down_speed) continue;
// if (i->last_optimistically_unchoked > min_time) 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 // every minute, disconnect the worst peer in hope of finding a better peer
boost::posix_time::ptime local_time = second_clock::universal_time(); 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; m_last_optimistic_disconnect = local_time;
--max_connections; // this will have the effect of disconnecting the worst peer --max_connections; // this will have the effect of disconnecting the worst peer
@ -627,7 +625,8 @@ namespace libtorrent
while (num_connected_peers > max_connections) while (num_connected_peers > max_connections)
{ {
assert(disconnect_one_peer()); bool ret = disconnect_one_peer();
assert(ret);
--num_connected_peers; --num_connected_peers;
} }
} }
@ -714,8 +713,7 @@ namespace libtorrent
{ {
// choke peers that have leeched too much without giving anything back // choke peers that have leeched too much without giving anything back
for (std::vector<peer>::iterator i = m_peers.begin(); for (std::vector<peer>::iterator i = m_peers.begin();
i != m_peers.end(); i != m_peers.end(); ++i)
++i)
{ {
peer_connection* c = i->connection; peer_connection* c = i->connection;
if (c == 0) continue; if (c == 0) continue;

View File

@ -280,7 +280,8 @@ namespace libtorrent
} }
void torrent::tracker_response( void torrent::tracker_response(
std::vector<peer_entry>& peer_list tracker_request const& r
, std::vector<peer_entry>& peer_list
, int interval , int interval
, int complete , int complete
, int incomplete) , int incomplete)
@ -1259,11 +1260,13 @@ namespace libtorrent
for (int i = req.first; i < req.first + req.second; ++i) for (int i = req.first; i < req.first + req.second; ++i)
{ {
assert(m_requested_metadata[i] > 0); 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 #ifdef TORRENT_VERBOSE_LOGGING
debug_log("*** tracker timed out"); debug_log("*** tracker timed out");
@ -1283,7 +1286,8 @@ namespace libtorrent
// TODO: with some response codes, we should just consider // TODO: with some response codes, we should just consider
// the tracker as a failure and not retry // the tracker as a failure and not retry
// it anymore // 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 #ifdef TORRENT_VERBOSE_LOGGING
debug_log(std::string("*** tracker error: ") + str); debug_log(std::string("*** tracker error: ") + str);

View File

@ -197,6 +197,7 @@ namespace libtorrent
bool inflate_gzip( bool inflate_gzip(
std::vector<char>& buffer std::vector<char>& buffer
, tracker_request const& req
, request_callback* requester , request_callback* requester
, int maximum_tracker_response_length) , int maximum_tracker_response_length)
{ {
@ -205,7 +206,7 @@ namespace libtorrent
int header_len = gzip_header(&buffer[0], (int)buffer.size()); int header_len = gzip_header(&buffer[0], (int)buffer.size());
if (header_len < 0) 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; return true;
} }
@ -229,7 +230,7 @@ namespace libtorrent
// and just deflate the buffer // and just deflate the buffer
if (inflateInit2(&str, -15) != Z_OK) 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; return true;
} }
@ -242,7 +243,8 @@ namespace libtorrent
if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length) if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length)
{ {
inflateEnd(&str); inflateEnd(&str);
requester->tracker_request_error(200, "tracker response too large"); requester->tracker_request_error(req, 200
, "tracker response too large");
return true; return true;
} }
int new_size = (int)inflate_buffer.size() * 2; int new_size = (int)inflate_buffer.size() * 2;
@ -262,7 +264,7 @@ namespace libtorrent
if (ret != Z_STREAM_END) if (ret != Z_STREAM_END)
{ {
requester->tracker_request_error(200, "gzip error"); requester->tracker_request_error(req, 200, "gzip error");
return true; return true;
} }
@ -351,7 +353,8 @@ namespace libtorrent
catch (const std::exception& e) catch (const std::exception& e)
{ {
if (c->has_requester()) 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; if (c->has_requester()) c->requester().m_manager = 0;
i = m_connections.erase(i); i = m_connections.erase(i);
@ -469,7 +472,7 @@ namespace libtorrent
if (!c.expired()) if (!c.expired())
{ {
boost::shared_ptr<request_callback> r = c.lock(); boost::shared_ptr<request_callback> r = c.lock();
r->tracker_request_error(-1, e.what()); r->tracker_request_error(req, -1, e.what());
} }
} }
} }

View File

@ -106,7 +106,8 @@ namespace libtorrent
{ {
if (m_attempts >= udp_connection_retries) 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; return true;
} }
send_udp_connect(); send_udp_connect();
@ -118,7 +119,8 @@ namespace libtorrent
{ {
if (m_attempts >= udp_announce_retries) 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; return true;
} }
@ -140,7 +142,8 @@ namespace libtorrent
if (ret == udp_buffer_size) if (ret == udp_buffer_size)
{ {
if (has_requester()) 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; return true;
} }
@ -239,7 +242,8 @@ namespace libtorrent
if (action == error) if (action == error)
{ {
if (has_requester()) 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; return true;
} }
if (action != announce) return false; if (action != announce) return false;
@ -260,7 +264,8 @@ namespace libtorrent
if ((len - 24) % 6 != 0) if ((len - 24) % 6 != 0)
{ {
if (has_requester()) if (has_requester())
requester().tracker_request_error(-1, "invalid tracker response"); requester().tracker_request_error(
m_request, -1, "invalid tracker response");
return true; return true;
} }
@ -281,7 +286,8 @@ namespace libtorrent
peer_list.push_back(e); 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; return true;
} }
@ -306,7 +312,8 @@ namespace libtorrent
if (action == error) if (action == error)
{ {
if (has_requester()) 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; return true;
} }
if (action != connect) return false; if (action != connect) return false;