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; } }
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 entry::swap(entry& e) { bool clear_this = false; bool clear_that = false; if (m_type == undefined_t && e.m_type == undefined_t) return; if (m_type == undefined_t) { construct((data_type)e.m_type); clear_that = true; } if (e.m_type == undefined_t) { e.construct((data_type)m_type); clear_this = true; } if (m_type == e.m_type) { switch (m_type) { case int_t: std::swap(*reinterpret_cast<integer_type*>(data) , *reinterpret_cast<integer_type*>(e.data)); break; case string_t: std::swap(*reinterpret_cast<string_type*>(data) , *reinterpret_cast<string_type*>(e.data)); break; case list_t: std::swap(*reinterpret_cast<list_type*>(data) , *reinterpret_cast<list_type*>(e.data)); break; case dictionary_t: std::swap(*reinterpret_cast<dictionary_type*>(data) , *reinterpret_cast<dictionary_type*>(e.data)); break; default: break; } if (clear_this) destruct(); if (clear_that) e.destruct(); } else { // currently, only swapping entries of the same type or where one // of the entries is uninitialized is supported. TORRENT_ASSERT(false && "not implemented"); } }
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&) {} }
static void write_entry(serializer & s, entry const & e) { s << static_cast<char>(e.kind()) << e.overload() << e.parse_only() << e.get_expr(); if (e.is_numeral()) { s << e.get_num(); } else { s << static_cast<char>(e.group()) << length(e.get_transitions()); for (auto const & t : e.get_transitions()) s << t; s << e.priority(); } }
strings fillstr(entry& e) { // oh this is so stupid. Normalise requires strings, which it then countpaths // for me. So I have to take my clean-room hashes and recreate the strings so // that normalise can turn them back into hashes. strings ss; for(entry::const_iterator i = e.begin(); i!=e.end(); i++) { for(int j = 0; j < (int)i->second; j++) { ss.push_back(i->first); } } return ss; }
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 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 }
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); }
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(); } }
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() + "'"); }
void repository::builder::unpack_source( const entry &package, const boost::filesystem::path &destination, snapshot &snapshot_) { BUNSAN_LOG_DEBUG << "Starting " << package << " import unpack"; const index deps = cache_().read_index(package); // extract sources for (const auto &i : deps.source.self) extractor_().extract_source(package, i.source, destination / i.path); // dump package checksum into snapshot { const auto iter = snapshot_.find(package); const snapshot_entry checksum = cache_().read_checksum(package); if (iter != snapshot_.end()) BOOST_ASSERT(iter->second == checksum); else snapshot_[package.name()] = checksum; } // extract source imports for (const auto &i : deps.source.import.source) unpack_source(i.package, destination / i.path, snapshot_); // extract package imports for (const auto &i : deps.source.import.package) { extractor_().extract_installation(i.package, destination / i.path); merge_maps(snapshot_, cache_().read_installation_snapshot(i.package)); } }
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; }
bool entry::operator==(entry const& e) const { if (m_type != e.m_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(); default: assert(m_type == undefined_t); return true; } }
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; }
bool operator==(const entry& other) const { return get_device_id() == other.get_device_id() && get_event_time_stamp() == other.get_event_time_stamp() && get_valid() == other.get_valid() && get_lazy() == other.get_lazy() && get_event() == other.get_event() && get_event_type() == other.get_event_type() && get_original_event() == other.get_original_event(); }
void push_back_entry(const entry& entry) { emplace_back_entry(entry.get_device_id(), entry.get_event_time_stamp(), entry.get_event(), entry.get_event_type(), entry.get_original_event(), entry.get_lazy()); events_.back().set_valid(entry.get_valid()); }
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 entry::copy(const entry& e) { m_type = e.m_type; switch(m_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: m_type = undefined_t; } }
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 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); }
// Add thisEntry to dictionary thisDict. bool addEntry ( dictionary& thisDict, entry& thisEntry, const entry& mergeEntry, const bool literalRE ) { bool changed = false; // Recursively merge sub-dictionaries // TODO: merge without copying if (thisEntry.isDict() && mergeEntry.isDict()) { if ( merge ( const_cast<dictionary&>(thisEntry.dict()), mergeEntry.dict(), literalRE ) ) { changed = true; } } else { // Should use in-place modification instead of adding thisDict.add(mergeEntry.clone(thisDict).ptr(), true); changed = true; } return changed; }
boost::filesystem::path repository::cache::file_path( const boost::filesystem::path &root, const entry &package, const boost::filesystem::path &filename) { try { if (filename.filename() != filename) BOOST_THROW_EXCEPTION( cache_file_path_invalid_filename_error() << cache_file_path_invalid_filename_error::filename(filename)); const boost::filesystem::path package_root = root / package.location(); boost::filesystem::create_directories(package_root); return package_root / filename; } catch (std::exception &) { BOOST_THROW_EXCEPTION(cache_file_path_error() << cache_file_path_error::root(root) << cache_file_path_error::package(package) << cache_file_path_error::filename(filename) << enable_nested_current()); } }
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); }
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; } }
// 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); }
// 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); }
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>"); } }