void entry::copy(entry const& e) { switch (e.type()) { case int_t: new (&data) integer_type(e.integer()); break; case string_t: new (&data) string_type(e.string()); break; case list_t: new (&data) list_type(e.list()); break; case dictionary_t: new (&data) dictionary_type(e.dict()); break; case undefined_t: TORRENT_ASSERT(e.type() == undefined_t); break; case preformatted_t: new (&data) preformatted_type(e.preformatted()); break; } m_type = e.type(); #if TORRENT_USE_ASSERTS m_type_queried = true; #endif }
int bencode_recursive(OutIt& out, const entry& e) { int ret = 0; switch(e.type()) { case entry::int_t: write_char(out, 'i'); ret += write_integer(out, e.integer()); write_char(out, 'e'); ret += 2; break; case entry::string_t: ret += write_integer(out, e.string().length()); write_char(out, ':'); ret += write_string(e.string(), out); ret += 1; break; case entry::list_t: write_char(out, 'l'); for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) ret += bencode_recursive(out, *i); write_char(out, 'e'); ret += 2; break; case entry::dictionary_t: write_char(out, 'd'); for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { // write key ret += write_integer(out, i->first.length()); write_char(out, ':'); ret += write_string(i->first, out); // write value ret += bencode_recursive(out, i->second); ret += 1; } write_char(out, 'e'); ret += 2; break; default: // trying to encode a structure with uninitialized values! TORRENT_ASSERT_VAL(false, e.type()); // do nothing break; } return ret; }
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())); }
torrent_handle session_handle::add_torrent( char const* tracker_url , sha1_hash const& info_hash , char const* name , std::string const& save_path , entry const& resume_data , storage_mode_t storage_mode , bool paused , storage_constructor_type sc , void* userdata) { TORRENT_ASSERT_PRECOND(!save_path.empty()); add_torrent_params p(sc); p.trackers.push_back(tracker_url); p.info_hash = info_hash; p.save_path = save_path; p.storage_mode = storage_mode; if (paused) p.flags |= add_torrent_params::flag_paused; else p.flags &= ~add_torrent_params::flag_paused; p.userdata = userdata; p.name = name; if (resume_data.type() != entry::undefined_t) { bencode(std::back_inserter(p.resume_data), resume_data); } return add_torrent(p); }
void wx_entry_print(entry e, int depth) { wxString padding(wxT("")); switch(e.type()) { case entry::int_t: wxLogMessage(wxT("print:")+padding.Pad(depth, '\t')+wxString::Format(_T("int: %u"), e.integer())); break; case entry::string_t: wxLogMessage(wxT("print:")+padding.Pad(depth, '\t')+wxString::Format(wxT("str-len: %u "), e.string().length())+wxT("str: ")+wxString(e.string().c_str(), wxConvUTF8)); break; case entry::list_t: for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) { wx_entry_print(*i, depth+1); } break; case entry::dictionary_t: for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { wx_entry_print(i->first, depth+1);// write key wx_entry_print(i->second, depth+1);// write value } break; default: break; } }
int bencode_recursive(OutIt& out, const entry& e) { int ret = 0; switch(e.type()) { case entry::int_t: write_char(out, 'i'); ret += write_integer(out, e.integer()); write_char(out, 'e'); ret += 2; break; case entry::string_t: ret += write_integer(out, e.string().length()); write_char(out, ':'); ret += write_string(e.string(), out); ret += 1; break; case entry::list_t: write_char(out, 'l'); for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) ret += bencode_recursive(out, *i); write_char(out, 'e'); ret += 2; break; case entry::dictionary_t: write_char(out, 'd'); for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { // write key ret += write_integer(out, i->first.length()); write_char(out, ':'); ret += write_string(i->first, out); // write value ret += bencode_recursive(out, i->second); ret += 1; } write_char(out, 'e'); ret += 2; break; case entry::preformatted_t: std::copy(e.preformatted().begin(), e.preformatted().end(), out); ret += int(e.preformatted().size()); break; case entry::undefined_t: // empty string write_char(out, '0'); write_char(out, ':'); ret += 2; break; } return ret; }
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 session::load_state(entry const& ses_state) { if (ses_state.type() == entry::undefined_t) return; std::vector<char> buf; bencode(std::back_inserter(buf), ses_state); lazy_entry e; error_code ec; int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec); TORRENT_ASSERT(ret == 0); TORRENT_SYNC_CALL1(load_state, &e); }
void save_struct(entry& e, void const* s, bencode_map_entry const* m, int num, void const* def) { if (e.type() != entry::dictionary_t) e = entry(entry::dictionary_t); for (int i = 0; i < num; ++i) { char const* key = m[i].name; void const* src = ((char*)s) + m[i].offset; if (def) { // if we have a default value for this field // and it is the default, don't save it void const* default_value = ((char*)def) + m[i].offset; switch (m[i].type) { case std_string: if (*((std::string*)src) == *((std::string*)default_value)) continue; break; case character: if (*((char*)src) == *((char*)default_value)) continue; break; case integer: if (*((int*)src) == *((int*)default_value)) continue; break; case size_integer: if (*((size_type*)src) == *((size_type*)default_value)) continue; break; case time_integer: if (*((time_t*)src) == *((time_t*)default_value)) continue; break; case floating_point: if (*((float*)src) == *((float*)default_value)) continue; break; case boolean: if (*((bool*)src) == *((bool*)default_value)) continue; break; default: TORRENT_ASSERT(false); } } entry& val = e[key]; TORRENT_ASSERT_VAL(val.type() == entry::undefined_t, val.type()); switch (m[i].type) { case std_string: val = *((std::string*)src); break; case character: val = *((char*)src); break; case integer: val = *((int*)src); break; case size_integer: val = *((size_type*)src); break; case time_integer: val = *((time_t*)src); break; case floating_point: val = size_type(*((float*)src) * 1000.f); break; case boolean: val = *((bool*)src); break; default: TORRENT_ASSERT(false); } } }
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&) {} }
void session::load_state(entry const& ses_state) { if (ses_state.type() == entry::undefined_t) return; std::vector<char> buf; bencode(std::back_inserter(buf), ses_state); lazy_entry e; error_code ec; int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec); TORRENT_ASSERT(ret == 0); #ifndef BOOST_NO_EXCEPTIONS if (ret != 0) throw libtorrent_exception(ec); #endif TORRENT_SYNC_CALL1(load_state, &e); }
void entry::copy(entry const& e) { switch (e.type()) { case int_t: new(data) integer_type(e.integer()); break; case string_t: new(data) string_type(e.string()); break; case list_t: new(data) list_type(e.list()); break; case dictionary_t: new (data) dictionary_type(e.dict()); break; default: TORRENT_ASSERT(e.type() == undefined_t); } m_type = e.type(); #ifdef TORRENT_DEBUG m_type_queried = true; #endif }
static object convert0(entry const& e) { switch (e.type()) { case entry::int_t: return object(e.integer()); case entry::string_t: return object(e.string()); case entry::list_t: return convert(e.list()); case entry::dictionary_t: return convert(e.dict()); default: return object(); } }
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 session_handle::load_state(entry const& ses_state , std::uint32_t const flags) { if (ses_state.type() == entry::undefined_t) return; std::vector<char> buf; bencode(std::back_inserter(buf), ses_state); bdecode_node e; error_code ec; #if TORRENT_USE_ASSERTS || !defined BOOST_NO_EXCEPTIONS int ret = #endif bdecode(&buf[0], &buf[0] + buf.size(), e, ec); TORRENT_ASSERT(ret == 0); #ifndef BOOST_NO_EXCEPTIONS if (ret != 0) throw system_error(ec); #endif sync_call(&session_impl::load_state, &e, flags); }
// if the torrent already exists, this will throw duplicate_torrent torrent_handle session::add_torrent( torrent_info const& ti , std::string const& save_path , entry const& resume_data , storage_mode_t storage_mode , bool paused , storage_constructor_type sc) { boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti)); add_torrent_params p(sc); p.ti = tip; p.save_path = save_path; if (resume_data.type() != entry::undefined_t) { bencode(std::back_inserter(p.resume_data), resume_data); } p.storage_mode = storage_mode; p.paused = paused; return add_torrent(p); }
// if the torrent already exists, this will throw duplicate_torrent torrent_handle session_handle::add_torrent( torrent_info const& ti , std::string const& save_path , entry const& resume_data , storage_mode_t storage_mode , bool paused , storage_constructor_type sc) { add_torrent_params p(sc); p.ti = std::make_shared<torrent_info>(ti); p.save_path = save_path; if (resume_data.type() != entry::undefined_t) { bencode(std::back_inserter(p.resume_data), resume_data); } p.storage_mode = storage_mode; if (paused) p.flags |= add_torrent_params::flag_paused; else p.flags &= ~add_torrent_params::flag_paused; return add_torrent(p); }
bool entry::operator==(entry const& e) const { if (type() != e.type()) return false; switch (m_type) { case int_t: return integer() == e.integer(); case string_t: return string() == e.string(); case list_t: return list() == e.list(); case dictionary_t: return dict() == e.dict(); case preformatted_t: return preformatted() == e.preformatted(); default: TORRENT_ASSERT(m_type == undefined_t); return true; } }
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 bencode_recursive(OutIt& out, const entry& e) { switch(e.type()) { case entry::int_t: write_char(out, 'i'); write_integer(out, e.integer()); write_char(out, 'e'); break; case entry::string_t: write_integer(out, e.string().length()); write_char(out, ':'); write_string(out, e.string()); break; case entry::list_t: write_char(out, 'l'); for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) bencode_recursive(out, *i); write_char(out, 'e'); break; case entry::dictionary_t: write_char(out, 'd'); for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { // write key write_integer(out, i->first.length()); write_char(out, ':'); write_string(out, i->first); // write value bencode_recursive(out, i->second); } write_char(out, 'e'); break; default: // do nothing break; } }
torrent_handle session::add_torrent( boost::intrusive_ptr<torrent_info> ti , std::string const& save_path , entry const& resume_data , storage_mode_t storage_mode , bool paused , storage_constructor_type sc , void* userdata) { add_torrent_params p(sc); p.ti = ti; p.save_path = save_path; std::vector<char> buf; if (resume_data.type() != entry::undefined_t) { bencode(std::back_inserter(buf), resume_data); p.resume_data = &buf; } p.storage_mode = storage_mode; p.paused = paused; p.userdata = userdata; return add_torrent(p); }
Value entryToJson(const entry &e) { Array lst; Object o; switch( e.type() ) { case entry::int_t: return e.integer(); case entry::string_t: return e.string(); case entry::list_t: for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) { lst.push_back( entryToJson(*i) ); } return lst; case entry::dictionary_t: for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { o.push_back(Pair(i->first, entryToJson(i->second))); } return o; default: return string("<uninitialized>"); } }
bool default_storage::write_resume_data(entry& rd) const { TORRENT_ASSERT(rd.type() == entry::dictionary_t); return false; }
// 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())); }