// check if the fastresume data is up to date // if it is, use it and return true. If it // isn't return false and the full check // will be run int piece_manager::check_fastresume( lazy_entry const& rd, error_code& error) { mutex::scoped_lock lock(m_mutex); INVARIANT_CHECK; TORRENT_ASSERT(m_files.piece_length() > 0); m_current_slot = 0; // if we don't have any resume data, return if (rd.type() == lazy_entry::none_t) return check_no_fastresume(error); if (rd.type() != lazy_entry::dict_t) { error = errors::not_a_dictionary; return check_no_fastresume(error); } int block_size = (std::min)(16 * 1024, m_files.piece_length()); int blocks_per_piece = int(rd.dict_find_int_value("blocks per piece", -1)); if (blocks_per_piece != -1 && blocks_per_piece != m_files.piece_length() / block_size) { error = errors::invalid_blocks_per_piece; return check_no_fastresume(error); } if (!m_storage->verify_resume_data(rd, error)) return check_no_fastresume(error); return check_init_storage(error); }
void http_tracker_connection::parse(int status_code, lazy_entry const& e) { boost::shared_ptr<request_callback> cb = requester(); if (!cb) return; int interval = int(e.dict_find_int_value("interval", 1800)); int min_interval = int(e.dict_find_int_value("min interval", 60)); std::string trackerid; lazy_entry const* tracker_id = e.dict_find_string("tracker id"); if (tracker_id) trackerid = tracker_id->string_value(); // parse the response lazy_entry const* failure = e.dict_find_string("failure reason"); if (failure) { fail(error_code(errors::tracker_failure), status_code , failure->string_value().c_str(), interval, min_interval); return; } lazy_entry const* warning = e.dict_find_string("warning message"); if (warning) cb->tracker_warning(tracker_req(), warning->string_value()); std::vector<peer_entry> peer_list; if (tracker_req().kind == tracker_request::scrape_request) { std::string ih = tracker_req().info_hash.to_string(); lazy_entry const* files = e.dict_find_dict("files"); if (files == 0) { fail(error_code(errors::invalid_files_entry), -1, "" , interval, min_interval); return; } lazy_entry const* scrape_data = files->dict_find_dict(ih.c_str()); if (scrape_data == 0) { fail(error_code(errors::invalid_hash_entry), -1, "" , interval, min_interval); return; } int complete = int(scrape_data->dict_find_int_value("complete", -1)); int incomplete = int(scrape_data->dict_find_int_value("incomplete", -1)); int downloaded = int(scrape_data->dict_find_int_value("downloaded", -1)); int downloaders = int(scrape_data->dict_find_int_value("downloaders", -1)); cb->tracker_scrape_response(tracker_req(), complete , incomplete, downloaded, downloaders); return; } lazy_entry const* peers_ent = e.dict_find("peers"); if (peers_ent && peers_ent->type() == lazy_entry::string_t) { char const* peers = peers_ent->string_ptr(); int len = peers_ent->string_length(); for (int i = 0; i < len; i += 6) { if (len - i < 6) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v4_address(peers).to_string(ec); p.port = detail::read_uint16(peers); if (ec) continue; peer_list.push_back(p); } } else if (peers_ent && peers_ent->type() == lazy_entry::list_t) { int len = peers_ent->list_size(); for (int i = 0; i < len; ++i) { peer_entry p; if (!extract_peer_info(*peers_ent->list_at(i), p)) return; peer_list.push_back(p); } } else { peers_ent = 0; } #if TORRENT_USE_IPV6 lazy_entry const* ipv6_peers = e.dict_find_string("peers6"); if (ipv6_peers) { char const* peers = ipv6_peers->string_ptr(); int len = ipv6_peers->string_length(); for (int i = 0; i < len; i += 18) { if (len - i < 18) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v6_address(peers).to_string(ec); p.port = detail::read_uint16(peers); if (ec) continue; peer_list.push_back(p); } } else { ipv6_peers = 0; } #else lazy_entry const* ipv6_peers = 0; #endif // if we didn't receive any peers. We don't care if we're stopping anyway if (peers_ent == 0 && ipv6_peers == 0 && tracker_req().event != tracker_request::stopped) { fail(error_code(errors::invalid_peers_entry), -1, "" , interval, min_interval); return; } // look for optional scrape info address external_ip; lazy_entry const* ip_ent = e.dict_find_string("external ip"); if (ip_ent) { char const* p = ip_ent->string_ptr(); if (ip_ent->string_length() == address_v4::bytes_type().size()) external_ip = detail::read_v4_address(p); #if TORRENT_USE_IPV6 else if (ip_ent->string_length() == address_v6::bytes_type().size()) external_ip = detail::read_v6_address(p); #endif } int complete = int(e.dict_find_int_value("complete", -1)); int incomplete = int(e.dict_find_int_value("incomplete", -1)); std::list<address> ip_list; if (m_tracker_connection) { error_code ec; ip_list.push_back(m_tracker_connection->socket().remote_endpoint(ec).address()); std::list<tcp::endpoint> const& epts = m_tracker_connection->endpoints(); for (std::list<tcp::endpoint>::const_iterator i = epts.begin() , end(epts.end()); i != end; ++i) { ip_list.push_back(i->address()); } } cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, peer_list , interval, min_interval, complete, incomplete, external_ip, trackerid); }