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
, boost::weak_ptr<request_callback> r);
request_callback& requester();
boost::shared_ptr<request_callback> requester();
virtual ~tracker_connection() {}
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_timeout();

View File

@ -459,14 +459,16 @@ namespace libtorrent
m_send_buffer += "\r\n\r\n";
#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;
info_hash_str << req.info_hash;
requester().debug_log("info_hash: "
cb->debug_log("info_hash: "
+ boost::lexical_cast<std::string>(req.info_hash));
requester().debug_log("name lookup: " + hostname);
cb->debug_log("name lookup: " + hostname);
}
#endif
@ -491,8 +493,9 @@ namespace libtorrent
void http_tracker_connection::name_lookup(asio::error_code const& error
, tcp::resolver::iterator i) try
{
boost::shared_ptr<request_callback> cb = requester();
#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
if (error == asio::error::operation_aborted) return;
if (m_timed_out) return;
@ -504,7 +507,7 @@ namespace libtorrent
}
#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
restart_read_timeout();
@ -519,11 +522,11 @@ namespace libtorrent
if (target == end)
{
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 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 "
+ bind_address_type + " socket. This may prevent you from receiving incoming connections.");
}
@ -533,7 +536,7 @@ namespace libtorrent
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);
if (m_proxy.type == proxy_settings::http
@ -574,7 +577,8 @@ namespace libtorrent
}
#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
restart_read_timeout();
@ -598,7 +602,8 @@ namespace libtorrent
}
#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
restart_read_timeout();
assert(m_buffer.size() - m_recv_pos > 0);
@ -634,7 +639,8 @@ namespace libtorrent
restart_read_timeout();
assert(bytes_transferred > 0);
#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));
#endif
@ -700,6 +706,8 @@ namespace libtorrent
}
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)
{
@ -720,9 +728,9 @@ namespace libtorrent
}
#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
if (has_requester()) requester().tracker_warning("Redirecting to \"" + location + "\"");
if (cb) cb->tracker_warning("Redirecting to \"" + location + "\"");
tracker_request req = tracker_req();
req.url = location;
@ -745,20 +753,18 @@ namespace libtorrent
std::string content_encoding = m_parser.header<std::string>("content-encoding");
#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
if (content_encoding == "gzip" || content_encoding == "x-gzip")
{
boost::shared_ptr<request_callback> r = m_requester.lock();
if (!r)
if (!cb)
{
close();
return;
}
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))
{
close();
@ -835,7 +841,8 @@ namespace libtorrent
void http_tracker_connection::parse(entry const& e)
{
if (!has_requester()) return;
boost::shared_ptr<request_callback> cb = requester();
if (!cb) return;
try
{
@ -852,8 +859,7 @@ namespace libtorrent
try
{
entry const& warning = e["warning message"];
if (has_requester())
requester().tracker_warning(warning.string());
cb->tracker_warning(warning.string());
}
catch(type_error const&) {}
@ -867,7 +873,7 @@ namespace libtorrent
entry scrape_data = e["files"][ih];
int complete = scrape_data["complete"].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);
return;
}
@ -914,16 +920,16 @@ namespace libtorrent
try { incomplete = e["incomplete"].integer(); }
catch(type_error&) {}
requester().tracker_response(tracker_request(), peer_list, interval, complete
cb->tracker_response(tracker_request(), peer_list, interval, complete
, incomplete);
}
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)
{
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)
{}
request_callback& tracker_connection::requester()
boost::shared_ptr<request_callback> tracker_connection::requester()
{
boost::shared_ptr<request_callback> r = m_requester.lock();
assert(r);
return *r;
return m_requester.lock();
}
void tracker_connection::fail(int code, char const* msg)
{
if (has_requester()) requester().tracker_request_error(
m_req, code, msg);
boost::shared_ptr<request_callback> cb = requester();
if (cb) cb->tracker_request_error(m_req, code, msg);
close();
}
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();
}
@ -548,7 +547,8 @@ namespace libtorrent
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)
{

View File

@ -110,8 +110,9 @@ namespace libtorrent
return;
}
boost::shared_ptr<request_callback> cb = requester();
#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
restart_read_timeout();
@ -126,11 +127,11 @@ namespace libtorrent
if (target == end)
{
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 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 "
+ bind_address_type + " socket. This may prevent you from receiving incoming connections.");
}
@ -140,7 +141,7 @@ namespace libtorrent
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_socket.reset(new datagram_socket(m_name_lookup.io_service()));
m_socket->open(target_address.protocol());
@ -163,9 +164,10 @@ namespace libtorrent
void udp_tracker_connection::send_udp_connect()
{
#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) + "]");
}
#endif
@ -259,9 +261,10 @@ namespace libtorrent
m_connection_id = detail::read_int64(ptr);
#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) + "]");
}
#endif
@ -321,9 +324,10 @@ namespace libtorrent
detail::write_uint16(0, out);
#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) + "]");
}
#endif
@ -431,14 +435,15 @@ namespace libtorrent
return;
}
boost::shared_ptr<request_callback> cb = requester();
#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
if (!has_requester())
if (!cb)
{
m_man.remove_request(this);
return;
@ -459,7 +464,7 @@ namespace libtorrent
peer_list.push_back(e);
}
requester().tracker_response(tracker_req(), peer_list, interval
cb->tracker_response(tracker_req(), peer_list, interval
, complete, incomplete);
m_man.remove_request(this);
@ -534,14 +539,15 @@ namespace libtorrent
/*int downloaded = */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);
return;
}
std::vector<peer_entry> peer_list;
requester().tracker_response(tracker_req(), peer_list, 0
cb->tracker_response(tracker_req(), peer_list, 0
, complete, incomplete);
m_man.remove_request(this);