fixed race condition in tracker manager

This commit is contained in:
Arvid Norberg 2007-09-14 02:54:15 +00:00
parent 7bbfb3bd4b
commit 15a193d363
4 changed files with 63 additions and 52 deletions

View File

@ -194,11 +194,10 @@ namespace libtorrent
, address bind_interface , address bind_interface
, boost::weak_ptr<request_callback> r); , boost::weak_ptr<request_callback> r);
request_callback& requester(); boost::shared_ptr<request_callback> requester();
virtual ~tracker_connection() {} virtual ~tracker_connection() {}
tracker_request const& tracker_req() const { return m_req; } tracker_request const& tracker_req() const { return m_req; }
bool has_requester() const { return !m_requester.expired(); }
void fail(int code, char const* msg); void fail(int code, char const* msg);
void fail_timeout(); void fail_timeout();

View File

@ -459,14 +459,16 @@ namespace libtorrent
m_send_buffer += "\r\n\r\n"; m_send_buffer += "\r\n\r\n";
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester())
boost::shared_ptr<request_callback> cb = requester();
if (cb)
{ {
requester().debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]"); cb->debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]");
std::stringstream info_hash_str; std::stringstream info_hash_str;
info_hash_str << req.info_hash; info_hash_str << req.info_hash;
requester().debug_log("info_hash: " cb->debug_log("info_hash: "
+ boost::lexical_cast<std::string>(req.info_hash)); + boost::lexical_cast<std::string>(req.info_hash));
requester().debug_log("name lookup: " + hostname); cb->debug_log("name lookup: " + hostname);
} }
#endif #endif
@ -491,8 +493,9 @@ namespace libtorrent
void http_tracker_connection::name_lookup(asio::error_code const& error void http_tracker_connection::name_lookup(asio::error_code const& error
, tcp::resolver::iterator i) try , tcp::resolver::iterator i) try
{ {
boost::shared_ptr<request_callback> cb = requester();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("tracker name lookup handler called"); if (cb) cb->debug_log("tracker name lookup handler called");
#endif #endif
if (error == asio::error::operation_aborted) return; if (error == asio::error::operation_aborted) return;
if (m_timed_out) return; if (m_timed_out) return;
@ -504,7 +507,7 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("tracker name lookup successful"); if (cb) cb->debug_log("tracker name lookup successful");
#endif #endif
restart_read_timeout(); restart_read_timeout();
@ -519,11 +522,11 @@ namespace libtorrent
if (target == end) if (target == end)
{ {
assert(target_address.address().is_v4() != bind_interface().is_v4()); assert(target_address.address().is_v4() != bind_interface().is_v4());
if (has_requester()) if (cb)
{ {
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
requester().tracker_warning("the tracker only resolves to an " cb->tracker_warning("the tracker only resolves to an "
+ tracker_address_type + " address, and you're listening on an " + tracker_address_type + " address, and you're listening on an "
+ bind_address_type + " socket. This may prevent you from receiving incoming connections."); + bind_address_type + " socket. This may prevent you from receiving incoming connections.");
} }
@ -533,7 +536,7 @@ namespace libtorrent
target_address = *target; target_address = *target;
} }
if (has_requester()) requester().m_tracker_address = target_address; if (cb) cb->m_tracker_address = target_address;
m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy); m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy);
if (m_proxy.type == proxy_settings::http if (m_proxy.type == proxy_settings::http
@ -574,7 +577,8 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("tracker connection successful"); boost::shared_ptr<request_callback> cb = requester();
if (cb) cb->debug_log("tracker connection successful");
#endif #endif
restart_read_timeout(); restart_read_timeout();
@ -598,7 +602,8 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("tracker send data completed"); boost::shared_ptr<request_callback> cb = requester();
if (cb) cb->debug_log("tracker send data completed");
#endif #endif
restart_read_timeout(); restart_read_timeout();
assert(m_buffer.size() - m_recv_pos > 0); assert(m_buffer.size() - m_recv_pos > 0);
@ -634,7 +639,8 @@ namespace libtorrent
restart_read_timeout(); restart_read_timeout();
assert(bytes_transferred > 0); assert(bytes_transferred > 0);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("tracker connection reading " boost::shared_ptr<request_callback> cb = requester();
if (cb) cb->debug_log("tracker connection reading "
+ boost::lexical_cast<std::string>(bytes_transferred)); + boost::lexical_cast<std::string>(bytes_transferred));
#endif #endif
@ -701,6 +707,8 @@ namespace libtorrent
std::string location = m_parser.header<std::string>("location"); std::string location = m_parser.header<std::string>("location");
boost::shared_ptr<request_callback> cb = requester();
if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) if (m_parser.status_code() >= 300 && m_parser.status_code() < 400)
{ {
if (location.empty()) if (location.empty())
@ -720,9 +728,9 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("Redirecting to \"" + location + "\""); if (cb) cb->debug_log("Redirecting to \"" + location + "\"");
#endif #endif
if (has_requester()) requester().tracker_warning("Redirecting to \"" + location + "\""); if (cb) cb->tracker_warning("Redirecting to \"" + location + "\"");
tracker_request req = tracker_req(); tracker_request req = tracker_req();
req.url = location; req.url = location;
@ -745,20 +753,18 @@ namespace libtorrent
std::string content_encoding = m_parser.header<std::string>("content-encoding"); std::string content_encoding = m_parser.header<std::string>("content-encoding");
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("content-encoding: \"" + content_encoding + "\""); if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\"");
#endif #endif
if (content_encoding == "gzip" || content_encoding == "x-gzip") if (content_encoding == "gzip" || content_encoding == "x-gzip")
{ {
boost::shared_ptr<request_callback> r = m_requester.lock(); if (!cb)
if (!r)
{ {
close(); close();
return; return;
} }
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start()); m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start());
if (inflate_gzip(m_buffer, tracker_request(), r.get(), if (inflate_gzip(m_buffer, tracker_request(), cb.get(),
m_settings.tracker_maximum_response_length)) m_settings.tracker_maximum_response_length))
{ {
close(); close();
@ -835,7 +841,8 @@ namespace libtorrent
void http_tracker_connection::parse(entry const& e) void http_tracker_connection::parse(entry const& e)
{ {
if (!has_requester()) return; boost::shared_ptr<request_callback> cb = requester();
if (!cb) return;
try try
{ {
@ -852,8 +859,7 @@ namespace libtorrent
try try
{ {
entry const& warning = e["warning message"]; entry const& warning = e["warning message"];
if (has_requester()) cb->tracker_warning(warning.string());
requester().tracker_warning(warning.string());
} }
catch(type_error const&) {} catch(type_error const&) {}
@ -867,7 +873,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(tracker_request(), peer_list, 0, complete cb->tracker_response(tracker_request(), peer_list, 0, complete
, incomplete); , incomplete);
return; return;
} }
@ -914,16 +920,16 @@ namespace libtorrent
try { incomplete = e["incomplete"].integer(); } try { incomplete = e["incomplete"].integer(); }
catch(type_error&) {} catch(type_error&) {}
requester().tracker_response(tracker_request(), peer_list, interval, complete cb->tracker_response(tracker_request(), peer_list, interval, complete
, incomplete); , incomplete);
} }
catch(type_error& e) catch(type_error& e)
{ {
requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
} }
} }

View File

@ -365,23 +365,22 @@ namespace libtorrent
, m_req(req) , m_req(req)
{} {}
request_callback& tracker_connection::requester() boost::shared_ptr<request_callback> tracker_connection::requester()
{ {
boost::shared_ptr<request_callback> r = m_requester.lock(); return m_requester.lock();
assert(r);
return *r;
} }
void tracker_connection::fail(int code, char const* msg) void tracker_connection::fail(int code, char const* msg)
{ {
if (has_requester()) requester().tracker_request_error( boost::shared_ptr<request_callback> cb = requester();
m_req, code, msg); if (cb) cb->tracker_request_error(m_req, code, msg);
close(); close();
} }
void tracker_connection::fail_timeout() void tracker_connection::fail_timeout()
{ {
if (has_requester()) requester().tracker_request_timed_out(m_req); boost::shared_ptr<request_callback> cb = requester();
if (cb) cb->tracker_request_timed_out(m_req);
close(); close();
} }
@ -548,7 +547,8 @@ namespace libtorrent
m_connections.push_back(con); m_connections.push_back(con);
if (con->has_requester()) con->requester().m_manager = this; boost::shared_ptr<request_callback> cb = con->requester();
if (cb) cb->m_manager = this;
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@ -110,8 +110,9 @@ namespace libtorrent
return; return;
} }
boost::shared_ptr<request_callback> cb = requester();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) requester().debug_log("udp tracker name lookup successful"); if (cb) cb->debug_log("udp tracker name lookup successful");
#endif #endif
restart_read_timeout(); restart_read_timeout();
@ -126,11 +127,11 @@ namespace libtorrent
if (target == end) if (target == end)
{ {
assert(target_address.address().is_v4() != bind_interface().is_v4()); assert(target_address.address().is_v4() != bind_interface().is_v4());
if (has_requester()) if (cb)
{ {
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
requester().tracker_warning("the tracker only resolves to an " cb->tracker_warning("the tracker only resolves to an "
+ tracker_address_type + " address, and you're listening on an " + tracker_address_type + " address, and you're listening on an "
+ bind_address_type + " socket. This may prevent you from receiving incoming connections."); + bind_address_type + " socket. This may prevent you from receiving incoming connections.");
} }
@ -140,7 +141,7 @@ namespace libtorrent
target_address = *target; target_address = *target;
} }
if (has_requester()) requester().m_tracker_address = tcp::endpoint(target_address.address(), target_address.port()); if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
m_target = target_address; m_target = target_address;
m_socket.reset(new datagram_socket(m_name_lookup.io_service())); m_socket.reset(new datagram_socket(m_name_lookup.io_service()));
m_socket->open(target_address.protocol()); m_socket->open(target_address.protocol());
@ -163,9 +164,10 @@ namespace libtorrent
void udp_tracker_connection::send_udp_connect() void udp_tracker_connection::send_udp_connect()
{ {
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) boost::shared_ptr<request_callback> cb = requester();
if (cb)
{ {
requester().debug_log("==> UDP_TRACKER_CONNECT [" cb->debug_log("==> UDP_TRACKER_CONNECT ["
+ lexical_cast<std::string>(tracker_req().info_hash) + "]"); + lexical_cast<std::string>(tracker_req().info_hash) + "]");
} }
#endif #endif
@ -259,9 +261,10 @@ namespace libtorrent
m_connection_id = detail::read_int64(ptr); m_connection_id = detail::read_int64(ptr);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) boost::shared_ptr<request_callback> cb = requester();
if (cb)
{ {
requester().debug_log("<== UDP_TRACKER_CONNECT_RESPONSE [" cb->debug_log("<== UDP_TRACKER_CONNECT_RESPONSE ["
+ lexical_cast<std::string>(m_connection_id) + "]"); + lexical_cast<std::string>(m_connection_id) + "]");
} }
#endif #endif
@ -321,9 +324,10 @@ namespace libtorrent
detail::write_uint16(0, out); detail::write_uint16(0, out);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) boost::shared_ptr<request_callback> cb = requester();
if (cb)
{ {
requester().debug_log("==> UDP_TRACKER_ANNOUNCE [" cb->debug_log("==> UDP_TRACKER_ANNOUNCE ["
+ lexical_cast<std::string>(req.info_hash) + "]"); + lexical_cast<std::string>(req.info_hash) + "]");
} }
#endif #endif
@ -431,14 +435,15 @@ namespace libtorrent
return; return;
} }
boost::shared_ptr<request_callback> cb = requester();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester()) if (cb)
{ {
requester().debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE"); cb->debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE");
} }
#endif #endif
if (!has_requester()) if (!cb)
{ {
m_man.remove_request(this); m_man.remove_request(this);
return; return;
@ -459,7 +464,7 @@ namespace libtorrent
peer_list.push_back(e); peer_list.push_back(e);
} }
requester().tracker_response(tracker_req(), peer_list, interval cb->tracker_response(tracker_req(), peer_list, interval
, complete, incomplete); , complete, incomplete);
m_man.remove_request(this); m_man.remove_request(this);
@ -534,14 +539,15 @@ namespace libtorrent
/*int downloaded = */detail::read_int32(buf); /*int downloaded = */detail::read_int32(buf);
int incomplete = detail::read_int32(buf); int incomplete = detail::read_int32(buf);
if (!has_requester()) boost::shared_ptr<request_callback> cb = requester();
if (!cb)
{ {
m_man.remove_request(this); m_man.remove_request(this);
return; return;
} }
std::vector<peer_entry> peer_list; std::vector<peer_entry> peer_list;
requester().tracker_response(tracker_req(), peer_list, 0 cb->tracker_response(tracker_req(), peer_list, 0
, complete, incomplete); , complete, incomplete);
m_man.remove_request(this); m_man.remove_request(this);