void dht_tracker::start(entry const& bootstrap) { std::vector<udp::endpoint> initial_nodes; if (bootstrap.type() == entry::dictionary_t) { try { if (entry const* nodes = bootstrap.find_key("nodes")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes); } catch (std::exception&) {} } error_code ec; m_timer.expires_from_now(seconds(1), ec); m_timer.async_wait(bind(&dht_tracker::tick, self(), _1)); m_connection_timer.expires_from_now(seconds(10), ec); m_connection_timer.async_wait( bind(&dht_tracker::connection_timeout, self(), _1)); m_refresh_timer.expires_from_now(seconds(5), ec); m_refresh_timer.async_wait(bind(&dht_tracker::refresh_timeout, self(), _1)); m_dht.bootstrap(initial_nodes, boost::bind(&dht_tracker::on_bootstrap, self())); }
void extract_single_file(const entry& dict, file_entry& target , std::string const& root_dir) { target.size = dict["length"].integer(); target.path = root_dir; // prefer the name.utf-8 // because if it exists, it is more // likely to be correctly encoded const entry::list_type* list = 0; if (entry const* p = dict.find_key("path.utf-8")) { list = &p->list(); } else { list = &dict["path"].list(); } for (entry::list_type::const_iterator i = list->begin(); i != list->end(); ++i) { if (i->string() != "..") target.path /= i->string(); } verify_encoding(target); if (target.path.is_complete()) throw std::runtime_error("torrent contains " "a file with an absolute path: '" + target.path.native_file_string() + "'"); }
bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret) { // extract peer id (if any) if (info.type() != entry::dictionary_t) { fail(-1, "invalid response from tracker (invalid peer entry)"); return false; } entry const* i = info.find_key("peer id"); if (i != 0) { if (i->type() != entry::string_t || i->string().length() != 20) { fail(-1, "invalid response from tracker (invalid peer id)"); return false; } std::copy(i->string().begin(), i->string().end(), ret.pid.begin()); } else { // if there's no peer_id, just initialize it to a bunch of zeroes std::fill_n(ret.pid.begin(), 20, 0); } // extract ip i = info.find_key("ip"); if (i == 0 || i->type() != entry::string_t) { fail(-1, "invalid response from tracker"); return false; } ret.ip = i->string(); // extract port i = info.find_key("port"); if (i == 0 || i->type() != entry::int_t) { fail(-1, "invalid response from tracker"); return false; } ret.port = (unsigned short)i->integer(); return true; }
void dht_tracker::start(entry const& bootstrap) { std::vector<udp::endpoint> initial_nodes; if (bootstrap.type() == entry::dictionary_t) { TORRENT_TRY { if (entry const* nodes = bootstrap.find_key("nodes")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes); } TORRENT_CATCH(std::exception&) {} }
void dht_tracker::start(entry const& bootstrap , find_data::nodes_callback const& f) { std::vector<udp::endpoint> initial_nodes; #if TORRENT_USE_IPV6 std::vector<udp::endpoint> initial_nodes6; #endif if (bootstrap.type() == entry::dictionary_t) { TORRENT_TRY { if (entry const* nodes = bootstrap.find_key("nodes")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes); } TORRENT_CATCH(std::exception&) {} #if TORRENT_USE_IPV6 TORRENT_TRY{ if (entry const* nodes = bootstrap.find_key("nodes6")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes6); } TORRENT_CATCH(std::exception&) {} #endif }
void dht_tracker::start(entry const& bootstrap , find_data::nodes_callback const& f) { TORRENT_ASSERT(m_ses.is_network_thread()); std::vector<udp::endpoint> initial_nodes; if (bootstrap.type() == entry::dictionary_t) { TORRENT_TRY { if (entry const* nodes = bootstrap.find_key("nodes")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes); } TORRENT_CATCH(std::exception&) {} }
// class that puts the networking and the kademlia node in a single // unit and connecting them together. dht_tracker::dht_tracker(asio::io_service& ios, dht_settings const& settings , asio::ip::address listen_interface, entry const& bootstrap) : m_strand(ios) , m_socket(ios, udp::endpoint(listen_interface, settings.service_port)) , m_dht(bind(&dht_tracker::send_packet, this, _1), settings , read_id(bootstrap)) , m_buffer(0) , m_last_new_key(time_now() - minutes(key_refresh)) , m_timer(ios) , m_connection_timer(ios) , m_refresh_timer(ios) , m_settings(settings) , m_refresh_bucket(160) , m_abort(false) , m_host_resolver(ios) , m_refs(0) { using boost::bind; m_in_buf[0].resize(1000); m_in_buf[1].resize(1000); #ifdef TORRENT_DHT_VERBOSE_LOGGING m_counter = 0; std::fill_n(m_replies_bytes_sent, 5, 0); std::fill_n(m_queries_bytes_received, 5, 0); std::fill_n(m_replies_sent, 5, 0); std::fill_n(m_queries_received, 5, 0); m_announces = 0; m_failed_announces = 0; m_total_message_input = 0; m_ut_message_input = 0; m_lt_message_input = 0; m_mp_message_input = 0; m_gr_message_input = 0; m_mo_message_input = 0; m_total_in_bytes = 0; m_total_out_bytes = 0; m_queries_out_bytes = 0; // turns on and off individual components' logging // rpc_log().enable(false); // node_log().enable(false); // traversal_log().enable(false); // dht_tracker_log.enable(false); #endif std::vector<udp::endpoint> initial_nodes; if (bootstrap.type() == entry::dictionary_t) { try { if (entry const* nodes = bootstrap.find_key("nodes")) read_endpoint_list<udp::endpoint>(nodes, initial_nodes); } catch (std::exception&) {} } m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); m_timer.expires_from_now(seconds(1)); m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1))); m_connection_timer.expires_from_now(seconds(10)); m_connection_timer.async_wait(m_strand.wrap( bind(&dht_tracker::connection_timeout, self(), _1))); m_refresh_timer.expires_from_now(seconds(5)); m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1))); m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self())); }
void http_tracker_connection::parse(int status_code, entry const& e) { boost::shared_ptr<request_callback> cb = requester(); if (!cb) return; // parse the response entry const* failure = e.find_key("failure reason"); if (failure && failure->type() == entry::string_t) { fail(status_code, failure->string().c_str()); return; } entry const* warning = e.find_key("warning message"); if (warning && warning->type() == entry::string_t) { cb->tracker_warning(tracker_req(), warning->string()); } std::vector<peer_entry> peer_list; if (tracker_req().kind == tracker_request::scrape_request) { std::string ih = tracker_req().info_hash.to_string(); entry const* files = e.find_key("files"); if (files == 0 || files->type() != entry::dictionary_t) { fail(-1, "invalid or missing 'files' entry in scrape response"); return; } entry const* scrape_data = files->find_key(ih); if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t) { fail(-1, "missing or invalid info-hash entry in scrape response"); return; } entry const* complete = scrape_data->find_key("complete"); entry const* incomplete = scrape_data->find_key("incomplete"); entry const* downloaded = scrape_data->find_key("downloaded"); if (complete == 0 || incomplete == 0 || downloaded == 0 || complete->type() != entry::int_t || incomplete->type() != entry::int_t || downloaded->type() != entry::int_t) { fail(-1, "missing 'complete' or 'incomplete' entries in scrape response"); return; } cb->tracker_scrape_response(tracker_req(), int(complete->integer()) , int(incomplete->integer()), int(downloaded->integer())); return; } entry const* interval = e.find_key("interval"); if (interval == 0 || interval->type() != entry::int_t) { fail(-1, "missing or invalid 'interval' entry in tracker response"); return; } entry const* peers_ent = e.find_key("peers"); if (peers_ent && peers_ent->type() == entry::string_t) { std::string const& peers = peers_ent->string(); for (std::string::const_iterator i = peers.begin(); i != peers.end();) { if (std::distance(i, peers.end()) < 6) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v4_address(i).to_string(ec); if (ec) continue; p.port = detail::read_uint16(i); peer_list.push_back(p); } } else if (peers_ent && peers_ent->type() == entry::list_t) { entry::list_type const& l = peers_ent->list(); for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) { peer_entry p; if (!extract_peer_info(*i, p)) return; peer_list.push_back(p); } } else { peers_ent = 0; } entry const* ipv6_peers = e.find_key("peers6"); if (ipv6_peers && ipv6_peers->type() == entry::string_t) { std::string const& peers = ipv6_peers->string(); for (std::string::const_iterator i = peers.begin(); i != peers.end();) { if (std::distance(i, peers.end()) < 18) break; peer_entry p; p.pid.clear(); error_code ec; p.ip = detail::read_v6_address(i).to_string(ec); if (ec) continue; p.port = detail::read_uint16(i); peer_list.push_back(p); } } else { ipv6_peers = 0; } if (peers_ent == 0 && ipv6_peers == 0) { fail(-1, "missing 'peers' and 'peers6' entry in tracker response"); return; } // look for optional scrape info int complete = -1; int incomplete = -1; address external_ip; entry const* ip_ent = e.find_key("external ip"); if (ip_ent && ip_ent->type() == entry::string_t) { std::string const& ip = ip_ent->string(); char const* p = &ip[0]; if (ip.size() == address_v4::bytes_type::static_size) external_ip = detail::read_v4_address(p); else if (ip.size() == address_v6::bytes_type::static_size) external_ip = detail::read_v6_address(p); } entry const* complete_ent = e.find_key("complete"); if (complete_ent && complete_ent->type() == entry::int_t) complete = int(complete_ent->integer()); entry const* incomplete_ent = e.find_key("incomplete"); if (incomplete_ent && incomplete_ent->type() == entry::int_t) incomplete = int(incomplete_ent->integer()); cb->tracker_response(tracker_req(), peer_list, interval->integer(), complete , incomplete, external_ip); }