diff --git a/docs/manual.rst b/docs/manual.rst
index b36db463b..42e5e0a5e 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -6404,6 +6404,31 @@ I2P errors:
160 no_i2p_router The URL specified an i2p address, but no i2p router is configured
====== ========================================= =================================================================
+tracker errors:
+
+====== ========================================= =================================================================
+170 scrape_not_available The tracker URL doesn't support transforming it into a scrape
+ URL. i.e. it doesn't contain "announce.
+------ ----------------------------------------- -----------------------------------------------------------------
+171 invalid_tracker_response invalid tracker response
+------ ----------------------------------------- -----------------------------------------------------------------
+172 invalid_peer_dict invalid peer dictionary entry. Not a dictionary
+------ ----------------------------------------- -----------------------------------------------------------------
+173 tracker_failure tracker sent a failure message
+------ ----------------------------------------- -----------------------------------------------------------------
+174 invalid_files_entry missing or invalid 'files' entry
+------ ----------------------------------------- -----------------------------------------------------------------
+175 invalid_hash_entry missing or invalid 'hash' entry
+------ ----------------------------------------- -----------------------------------------------------------------
+176 invalid_peers_entry missing or invalid 'peers' and 'peers6' entry
+------ ----------------------------------------- -----------------------------------------------------------------
+177 invalid_tracker_response_length udp tracker response packet has invalid size
+------ ----------------------------------------- -----------------------------------------------------------------
+178 invalid_tracker_transaction_id invalid transaction id in udp tracker response
+------ ----------------------------------------- -----------------------------------------------------------------
+179 invalid_tracker_action invalid action field in udp tracker response
+====== ========================================= =================================================================
+
The names of these error codes are declared in then ``libtorrent::errors`` namespace.
There is also another error category, ``libtorrent::upnp_category``, defining errors
diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp
index 0ff66ddb1..0a23e8fc9 100644
--- a/include/libtorrent/alert_types.hpp
+++ b/include/libtorrent/alert_types.hpp
@@ -241,24 +241,13 @@ namespace libtorrent
, int times
, int status
, std::string const& url_
- , error_code const& e)
+ , error_code const& e
+ , std::string const& m)
: tracker_alert(h, url_)
, times_in_row(times)
, status_code(status)
- , msg(e.message())
- {
- TORRENT_ASSERT(!url.empty());
- }
-
- tracker_error_alert(torrent_handle const& h
- , int times
- , int status
- , std::string const& url_
- , std::string const& msg_)
- : tracker_alert(h, url_)
- , times_in_row(times)
- , status_code(status)
- , msg(msg_)
+ , error(e)
+ , msg(msg)
{
TORRENT_ASSERT(!url.empty());
}
@@ -270,6 +259,7 @@ namespace libtorrent
int times_in_row;
int status_code;
+ error_code error;
std::string msg;
};
diff --git a/include/libtorrent/error_code.hpp b/include/libtorrent/error_code.hpp
index 3ca781803..08c45544a 100644
--- a/include/libtorrent/error_code.hpp
+++ b/include/libtorrent/error_code.hpp
@@ -224,6 +224,27 @@ namespace libtorrent
reserved159,
// i2p errors
no_i2p_router, // 160
+ reserved161,
+ reserved162,
+ reserved163,
+ reserved164,
+ reserved165,
+ reserved166,
+ reserved167,
+ reserved168,
+ reserved169,
+
+// tracker errors
+ scrape_not_available, // 170
+ invalid_tracker_response,
+ invalid_peer_dict,
+ tracker_failure,
+ invalid_files_entry,
+ invalid_hash_entry,
+ invalid_peers_entry,
+ invalid_tracker_response_length,
+ invalid_tracker_transaction_id,
+ invalid_tracker_action,
error_code_max
};
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index d5f36aadd..1f28fd0b9 100644
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -423,10 +423,9 @@ namespace libtorrent
, std::list
const& ip_list
, std::vector& e, int interval, int min_interval
, int complete, int incomplete, address const& external_ip);
- 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, int retry_interval);
+ , int response_code, error_code const& ec, const std::string& msg
+ , int retry_interval);
virtual void tracker_warning(tracker_request const& req
, std::string const& msg);
virtual void tracker_scrape_response(tracker_request const& req
diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp
index aff77bda6..15f23aede 100644
--- a/include/libtorrent/tracker_manager.hpp
+++ b/include/libtorrent/tracker_manager.hpp
@@ -135,12 +135,11 @@ namespace libtorrent
, int complete
, int incomplete
, address const& external_ip) = 0;
- virtual void tracker_request_timed_out(
- tracker_request const& req) = 0;
virtual void tracker_request_error(
tracker_request const& req
, int response_code
- , const std::string& description
+ , error_code const& ec
+ , const std::string& msg
, int retry_interval) = 0;
union_endpoint m_tracker_address;
@@ -201,9 +200,9 @@ namespace libtorrent
tracker_request const& tracker_req() const { return m_req; }
- void fail_disp(int code, std::string const& msg) { fail(code, msg.c_str()); }
- void fail(int code, char const* msg, int interval = 0, int min_interval = 0);
- void fail_timeout();
+ void fail_disp(error_code ec) { fail(ec); }
+ void fail(error_code const& ec, int code = -1, char const* msg = ""
+ , int interval = 0, int min_interval = 0);
virtual void start() = 0;
virtual void close();
address const& bind_interface() const { return m_req.bind_ip; }
diff --git a/src/error_code.cpp b/src/error_code.cpp
index 00584ffe4..8f67a095c 100644
--- a/src/error_code.cpp
+++ b/src/error_code.cpp
@@ -213,6 +213,26 @@ namespace libtorrent
"",
// i2p errors
"no i2p router is set up",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+// tracker errors
+ "scrape not available on tracker",
+ "invalid tracker response",
+ "invalid peer dictionary entry",
+ "tracker sent a failure message",
+ "missing or invalid 'files' entry",
+ "missing or invalid 'hash' entry",
+ "missing or invalid 'peers' and 'peers6' entry",
+ "udp tracker response packet has invalid size",
+ "invalid transaction id in udp tracker response",
+ "invalid action field in udp tracker response",
};
if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0]))
return "Unknown error";
diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp
index c05459c87..a2bec5bed 100644
--- a/src/http_tracker_connection.cpp
+++ b/src/http_tracker_connection.cpp
@@ -108,7 +108,7 @@ namespace libtorrent
if (pos == std::string::npos)
{
m_ios.post(boost::bind(&http_tracker_connection::fail_disp, self()
- , -1, "scrape is not available on url: '" + tracker_req().url +"'"));
+ , error_code(errors::scrape_not_available)));
return;
}
url.replace(pos, 8, "scrape");
@@ -247,7 +247,7 @@ namespace libtorrent
}
if (endpoints.empty())
- fail(-1, "blocked by IP filter");
+ fail(error_code(errors::banned_by_ip_filter));
}
void http_tracker_connection::on_connect(http_connection& c)
@@ -267,25 +267,25 @@ namespace libtorrent
if (ec && ec != asio::error::eof)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
if (!parser.header_finished())
{
- fail(-1, "premature end of file");
+ fail(asio::error::eof);
return;
}
if (parser.status_code() != 200)
{
- fail(parser.status_code(), parser.message().c_str());
+ fail(error_code(errors::http_error), parser.status_code(), parser.message().c_str());
return;
}
if (ec && ec != asio::error::eof)
{
- fail(parser.status_code(), ec.message().c_str());
+ fail(ec, parser.status_code());
return;
}
@@ -301,19 +301,7 @@ namespace libtorrent
}
else
{
- std::string error_str("invalid encoding of tracker response: \"");
- for (char const* i = data, *end(data + size); i != end; ++i)
- {
- if (*i >= ' ' && *i <= '~') error_str += *i;
- else
- {
- char val[30];
- snprintf(val, sizeof(val), "0x%02x ", *i);
- error_str += val;
- }
- }
- error_str += "\"";
- fail(parser.status_code(), error_str.c_str());
+ fail(error_code(errors::invalid_bencoding), parser.status_code());
}
close();
}
@@ -323,7 +311,7 @@ namespace libtorrent
// extract peer id (if any)
if (info.type() != lazy_entry::dict_t)
{
- fail(-1, "invalid response from tracker (invalid peer entry)");
+ fail(error_code(errors::invalid_peer_dict));
return false;
}
lazy_entry const* i = info.dict_find_string("peer id");
@@ -341,7 +329,7 @@ namespace libtorrent
i = info.dict_find_string("ip");
if (i == 0)
{
- fail(-1, "invalid response from tracker");
+ fail(error_code(errors::invalid_tracker_response));
return false;
}
ret.ip = i->string_value();
@@ -350,7 +338,7 @@ namespace libtorrent
i = info.dict_find_int("port");
if (i == 0)
{
- fail(-1, "invalid response from tracker");
+ fail(error_code(errors::invalid_tracker_response));
return false;
}
ret.port = (unsigned short)i->int_value();
@@ -370,7 +358,8 @@ namespace libtorrent
lazy_entry const* failure = e.dict_find_string("failure reason");
if (failure)
{
- fail(status_code, failure->string_value().c_str(), interval, min_interval);
+ fail(error_code(errors::tracker_failure), status_code
+ , failure->string_value().c_str(), interval, min_interval);
return;
}
@@ -387,7 +376,7 @@ namespace libtorrent
lazy_entry const* files = e.dict_find_dict("files");
if (files == 0)
{
- fail(-1, "invalid or missing 'files' entry in scrape response"
+ fail(error_code(errors::invalid_files_entry), -1, ""
, interval, min_interval);
return;
}
@@ -395,7 +384,7 @@ namespace libtorrent
lazy_entry const* scrape_data = files->dict_find_dict(ih.c_str());
if (scrape_data == 0)
{
- fail(-1, "missing or invalid info-hash entry in scrape response"
+ fail(error_code(errors::invalid_hash_entry), -1, ""
, interval, min_interval);
return;
}
@@ -469,7 +458,7 @@ namespace libtorrent
if (peers_ent == 0 && ipv6_peers == 0)
{
- fail(-1, "missing 'peers' and 'peers6' entry in tracker response"
+ fail(error_code(errors::invalid_peers_entry), -1, ""
, interval, min_interval);
return;
}
diff --git a/src/torrent.cpp b/src/torrent.cpp
index b5d420637..493d37740 100644
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -6257,49 +6257,11 @@ namespace libtorrent
return ret;
}
- void torrent::tracker_request_timed_out(
- tracker_request const& r)
- {
- mutex::scoped_lock l(m_ses.m_mutex);
-
- INVARIANT_CHECK;
-
-#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
- debug_log("*** tracker timed out");
-#endif
-
- if (r.kind == tracker_request::announce_request)
- {
- announce_entry* ae = find_tracker(r);
- if (ae)
- {
- ae->failed();
- int tracker_index = ae - &m_trackers[0];
- deprioritize_tracker(tracker_index);
- }
- if (m_ses.m_alerts.should_post())
- {
- m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
- , ae?ae->fails:0, 0, r.url
- , errors::timed_out));
- }
- }
- else if (r.kind == tracker_request::scrape_request)
- {
- if (m_ses.m_alerts.should_post())
- {
- m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle()
- , r.url, errors::timed_out));
- }
- }
- update_tracker_timer();
- }
-
// TODO: with some response codes, we should just consider
// the tracker as a failure and not retry
// it anymore
void torrent::tracker_request_error(tracker_request const& r
- , int response_code, const std::string& str
+ , int response_code, error_code const& ec, const std::string& msg
, int retry_interval)
{
mutex::scoped_lock l(m_ses.m_mutex);
@@ -6307,7 +6269,7 @@ namespace libtorrent
INVARIANT_CHECK;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
- debug_log(std::string("*** tracker error: ") + str);
+ debug_log("*** tracker error: " + ec.message() + " " + msg);
#endif
if (r.kind == tracker_request::announce_request)
{
@@ -6321,14 +6283,14 @@ namespace libtorrent
if (m_ses.m_alerts.should_post())
{
m_ses.m_alerts.post_alert(tracker_error_alert(get_handle()
- , ae?ae->fails:0, response_code, r.url, str));
+ , ae?ae->fails:0, response_code, r.url, ec, msg));
}
}
else if (r.kind == tracker_request::scrape_request)
{
if (m_ses.m_alerts.should_post())
{
- m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, str));
+ m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle(), r.url, ec));
}
}
update_tracker_timer();
diff --git a/src/tracker_manager.cpp b/src/tracker_manager.cpp
index 031f2c6de..480b6672c 100644
--- a/src/tracker_manager.cpp
+++ b/src/tracker_manager.cpp
@@ -140,10 +140,11 @@ namespace libtorrent
return m_requester.lock();
}
- void tracker_connection::fail(int code, char const* msg, int interval, int min_interval)
+ void tracker_connection::fail(error_code const& ec, int code
+ , char const* msg, int interval, int min_interval)
{
boost::shared_ptr cb = requester();
- if (cb) cb->tracker_request_error(m_req, code, msg
+ if (cb) cb->tracker_request_error(m_req, code, ec, msg
, interval == 0 ? min_interval : interval);
close();
}
@@ -158,13 +159,6 @@ namespace libtorrent
m_man.received_bytes(bytes);
}
- void tracker_connection::fail_timeout()
- {
- boost::shared_ptr cb = requester();
- if (cb) cb->tracker_request_timed_out(m_req);
- close();
- }
-
void tracker_connection::close()
{
cancel();
@@ -246,8 +240,9 @@ namespace libtorrent
{
// we need to post the error to avoid deadlock
if (boost::shared_ptr r = c.lock())
- ios.post(boost::bind(&request_callback::tracker_request_error, r, req, -1
- , "unknown protocol in tracker url: " + req.url, 0));
+ ios.post(boost::bind(&request_callback::tracker_request_error, r, req
+ , -1, error_code(errors::unsupported_url_protocol)
+ , "", 0));
return;
}
diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp
index c0d999436..4e35bf16c 100644
--- a/src/udp_tracker_connection.cpp
+++ b/src/udp_tracker_connection.cpp
@@ -97,7 +97,7 @@ namespace libtorrent
if (ec)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
@@ -123,7 +123,7 @@ namespace libtorrent
if (error == asio::error::operation_aborted) return;
if (error || i == udp::resolver::iterator())
{
- fail(-1, error.message().c_str());
+ fail(error);
return;
}
@@ -152,7 +152,7 @@ namespace libtorrent
if (m_endpoints.empty())
{
- fail(-1, "blocked by IP filter");
+ fail(error_code(errors::banned_by_ip_filter));
return;
}
@@ -194,7 +194,7 @@ namespace libtorrent
m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
if (ec)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
@@ -231,7 +231,7 @@ namespace libtorrent
#endif
m_socket.close();
m_name_lookup.cancel();
- fail_timeout();
+ fail(error_code(errors::timed_out));
}
void udp_tracker_connection::close()
@@ -254,7 +254,7 @@ namespace libtorrent
if (m_target != ep) return;
received_bytes(size + 28); // assuming UDP/IP header
- if (e) fail(-1, e.message().c_str());
+ if (e) fail(e);
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
boost::shared_ptr cb = requester();
@@ -289,7 +289,7 @@ namespace libtorrent
if (action == action_error)
{
- fail(-1, std::string(ptr, size - 8).c_str());
+ fail(error_code(errors::tracker_failure), -1, std::string(ptr, size - 8).c_str());
return;
}
@@ -379,7 +379,7 @@ namespace libtorrent
++m_attempts;
if (ec)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
}
@@ -415,7 +415,7 @@ namespace libtorrent
++m_attempts;
if (ec)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
}
@@ -433,7 +433,7 @@ namespace libtorrent
int num_peers = (size - 20) / 6;
if ((size - 20) % 6 != 0)
{
- fail(-1, "invalid udp tracker response length");
+ fail(error_code(errors::invalid_tracker_response_length));
return;
}
@@ -495,25 +495,25 @@ namespace libtorrent
if (transaction != m_transaction_id)
{
- fail(-1, "incorrect transaction id");
+ fail(error_code(errors::invalid_tracker_transaction_id));
return;
}
if (action == action_error)
{
- fail(-1, std::string(buf, size - 8).c_str());
+ fail(error_code(errors::tracker_failure), -1, std::string(buf, size - 8).c_str());
return;
}
if (action != action_scrape)
{
- fail(-1, "invalid action in announce response");
+ fail(error_code(errors::invalid_tracker_action));
return;
}
if (size < 20)
{
- fail(-1, "got a message with size < 20");
+ fail(error_code(errors::invalid_tracker_response_length));
return;
}
@@ -602,7 +602,7 @@ namespace libtorrent
++m_attempts;
if (ec)
{
- fail(-1, ec.message().c_str());
+ fail(ec);
return;
}
}