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 send_finished() const
{ return m_send_buffer.empty(); }
virtual tracker_request const& tracker_req() const
{ return m_req; }
private:

View File

@ -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<peer_entry>& e, int interval
virtual void tracker_response(
tracker_request const& r
, std::vector<peer_entry>& 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

View File

@ -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<char>& 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<peer_entry>& peers
tracker_request const&
, std::vector<peer_entry>& 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<char>& buffer
, tracker_request const& req
, request_callback* requester
, int maximum_tracker_response_length);
struct tracker_connection: boost::noncopyable
{
tracker_connection(boost::weak_ptr<request_callback> 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:

View File

@ -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:

View File

@ -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(

View File

@ -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<std::string>(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<request_callback> 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());
}
}

View File

@ -345,8 +345,7 @@ namespace libtorrent
// TODO: make this selection better
for (std::vector<peer>::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<peer>::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<peer>::iterator i = m_peers.begin();
i != m_peers.end();
++i)
i != m_peers.end(); ++i)
{
peer_connection* c = i->connection;
if (c == 0) continue;

View File

@ -280,7 +280,8 @@ namespace libtorrent
}
void torrent::tracker_response(
std::vector<peer_entry>& peer_list
tracker_request const& r
, std::vector<peer_entry>& 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);

View File

@ -197,6 +197,7 @@ namespace libtorrent
bool inflate_gzip(
std::vector<char>& 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<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 (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;